diff --git a/COPYING b/COPYING new file mode 100644 index 0000000..dc63aac --- /dev/null +++ b/COPYING @@ -0,0 +1,340 @@ + + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc. + 675 Mass Ave, Cambridge, MA 02139, 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 Library 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 + + Appendix: 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) 19yy + + 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., 675 Mass Ave, Cambridge, MA 02139, 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) 19yy 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 Library General +Public License instead of this License. diff --git a/COPYRIGHT b/COPYRIGHT new file mode 100644 index 0000000..2f088dd --- /dev/null +++ b/COPYRIGHT @@ -0,0 +1,19 @@ + This file is part of ISIS, the Interactive Spectral Interpretation System + Copyright (C) 1998-2008 Massachusetts Institute of Technology + + This software was developed by the MIT Center for Space Research under + contract SV1-61010 from the Smithsonian Institution. + + 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., 675 Mass Ave, Cambridge, MA 02139, USA. diff --git a/Changes.txt b/Changes.txt new file mode 100644 index 0000000..011717e --- /dev/null +++ b/Changes.txt @@ -0,0 +1,897 @@ +Changes since 1.4.9 (released Nov 2007) +--------------------------------------- + 1. Fixed cfitsio module bug (fits_write_binary_table) + 2. Restored support for mt_calc_model optional arguments + contrib_flag and line_list. + 3. Added stub for Tcl_PkgProvide to enable loading xspec12 + local models; updated interface for _load_xspec_local_models(). + 4. Minor changes to support building isis on cygwin. + 5. Fixed edit_par bug that could un-define the current model. + 6. Fixed bug that that prevented saving the S-Lang readline history. + 7. Fixed memory leak in median function. + 8. Xspec module code generator now handles model.dat files that + don't end with a blank line. + 9. Updated RMF file input code to support change in OGIP standard; + F_CHAN values, previously 2 bytes, may now be 4 bytes. +10. Fixed sign error in poisson random generator (src/random.c); + constant -0.059 had the wrong sign. +11. Fixed plot_quit bug that disabled all subsequent plotting. +12. Slang errors now generate one line of traceback by default. +13. Fixed bug in model_spectrum interface, presumably broken + since the introduction of line modifiers. +14. Fixed error handling bug in atomic database input code. +15. Update cfitsio module +16. Another cfitsio module update; fixed bug in handling of + isis_set_par_hook +17. load_data was failing when the 2nd parameter was an array of + length one. +18. Fixed array indexing bug in conf_joint. +19. Added NULL pointer check to src/histogram.c:Hist_get_flux_corr_weights +20. Added maplib module (contributed by John E. Davis) +21. Added support for systematic errors. +22. Update cfitsio module to version 0.4.3 +23. Support linking to pgplot and cfitsio in HEASOFT distribution +24. Update default search path definition. +25. load_par provides more informative error messages +26. automatically install wrapper script on Darwin +27. If defined, isis_interactive_hook() will be called when + interactive command-line processing begins; _traceback=0 is + the new default for interactive mode. +28. Added gainshift kernel. +29. configure options --with-pgplot and --with-cfitsio should override + --with-headas +30. Added set_define_model_hook +31. Optimized rmf_file.c:rebin_rmf() for speed. +32. Fixed bug in egauss that appeared for sigma < 1.e-6 keV. +33. Added get_back_exposure function +34. Update cfitsio module to version 0.4.4 +35. Patch to better support wildcards in parameter lists + (contributed by Manfred Hanke) +36. Replaced minim fit method with simann, simulated annealing +37. Fixed eval_fun bug - tied parameter values were not getting + updated. +38. Update xspec module to support changes new with xspec-12.5.0. +39. New cache_fun() and alias_fun() intrinsics, contributed + by Mike Noble, Mike Nowak and Manfred Hanke. + cache_fun() enables caching of spectral models, reducing + redundant model evaluations during e.g. confidence limit searches. + alias_fun() enables renaming spectral models and model + parameters and changing parameter defaults. +40. Applied patch to retrieve help files using the S-Lang + add_doc_file() intrinsic (from Mike Noble) +41. Added support for displaying xspec12 help files, either pdf + or html. +42. Improved support for xspec12 local models +43. At the isis prompt, __argc,__argv now contains the full input + command line +44. Fix xspec module bug: xspec12 local models implemented in + C or C++ were being linked through the wrong interface. +45. Support the double-precision fortran interface for xspec + local models +46. Fixed confusing interaction between fakeit and grouping +47. Fixed malloc bug in xspec module. +48. Added support for xspec model init strings. +49. Xspec model names are now case-sensitive; some lower-case + aliases are provided for back-compatibility. +50. New functions, aped_bib, aped_bib_query_string, provide + access to APED database literature references. +51. New function, aped_fun_details, provides access to + individual emission line flux contributions from each + temperature-density component of every spectral model component + +Changes since 1.4.8 (released Sept 2007) +--------------------------------------- + 1. If a script contains an isis_main() function, isis will + execute that function and exit. If the --force-interactive + option is used, isis will prompt for input after executing + isis_main(). Executable scripts can now use + #! /usr/bin/env isis + isis-script is no longer required. + 2. Added support for the S-Lang debugger. Use the --sldb + command-line option to invoke the debugger. + 3. Added support for the S-Lang profiler. Use the --prof + command-line option to invoke the profiler. + 4. create_aped_line_modifier now supports modifiers that + take additional user-defined arguments. + 5. xspec table models now load parameter defaults from the + table file. + 6. Changed line modifier interface to provide plasma state + information. + 7. Changed line profile interface to make it more general + 8. Line profile and line modifier interfaces both support + functions that take no parameters. + 9. Changes to support analysis of INTEGRAL data. +10. Reorganized xspec module build/install logic +11. Added xspec 12 model list to the source code distribution + (it's no longer necessary to run the xspec module code + generator to use isis with xspec 12.) +12. Improved performance of APED spectral models that use a line modifier +13. isis-script --sldb foo.sl runs isis_main automatically. +14. Fixed assign_rsp bug. First listed RMF was not re-defining + the dataset grid when multiple RMFs were assigned to one dataset. +15. All internal pgplot calls now use the pgplot module. +16. Removed obsolete gpileup kernel module. +17. Updated cfitsio module + +Changes since 1.4.7 (released June 2007) +--------------------------------------- + 1. add_abundances handles necessary typecasts + 2. Help hooks now return strings + 3. Fixed potential double-free bug in error handling code + hist-cmds.c:set_notice_using_mask, set_notice_using_list + 4. Models for flux-corrected data should not include the + instrumental background. + 5. If present, rebin_error_hook manages error propagation + associated with the background (see set_rebin_error_hook). + 6. Added support for AREASCAL column in PHA files. + 7. APED spectral models now support user-defined modification + of line emissivity functions, with fittable parameters. + See the create_aped_fun() documentation for details. + 8. APED spectral models now support user-defined line profiles. + See the create_aped_fun() documentation for details. + +Changes since 1.4.6 (released May 2007) +--------------------------------------- + 1. Xspec module now provides better access to elemental + abundances, photoionization cross-sections and NEI ionization + fractions. (See xspec_elabund, xspec_gphoto, xspec_ionsneqr, + xspec_phfit2, xspec_photo) + +Changes since 1.4.5 (released Mar 2007) +--------------------------------------- + 1. Updated cfitsio module to version 0.3.5 + 2. Added put_model_counts, put_model_flux, put_convolved_model_flux + 3. Added eval_stat_counts, eval_stat_flux + 4. Clearer load_par warning when model string exceeds input buffer size + 5. Prompt text is ignored if it appears as a prefix on the + command line in interactive mode. + 6. Fixed bug in application of optional weights in combine_datasets. + Weights had been applied to both model and data sums. Now, the + weights are applied only to the data sum. + 7. Added yshift kernel + 8. Expanded documentation for get_combined to clarify how it + might be used with spectra in flux units. + 9. Voigt profile norm now includes factor 1/(sqrt(PI)*Doppler_width) + (set Isis_Voigt_Is_Normalized=0 to restore the previous behavior) +10. Added get_cfun2 +11. Replaced list_par, save_par, list_data, list_arf, list_rmf with + slang implementations that provide more versatile output redirection +12. Added get_flux_corr_weights +13. Updated cfitsio module to version 0.3.8rc1 + +Changes since 1.4.4 (released Feb 2007) +--------------------------------------- + 1. Added backtrace capability + 2. Added pha-grouping functions from Mike Nowak + (regroup_file, use_file_group, i2x_group, x2i_group) + along with new intrinsic variable, Isis_Use_PHA_Grouping. + 3. Updated autoconf support for Fortran. Fortran compiler + and flags are now specified with FC and FCFLAGS instead of + F77 and FFLAGS. + +Changes since 1.4.3 (released Jan 2007) +--------------------------------------- + 1. Error handling uses S-Lang exceptions more consistently + 2. Installation procedure should be simpler. + 3. fit_flux is independent of the fit-kernel. + +Changes since 1.4.2 (released Sep 2006) +--------------------------------------- + 1. Numbering of fake datasets should not cause the dataset + list to get out of order. + 2. set_plot_options(get_plot_options()) is a no-op. + 3. flux_corr skips ignored data + 4. xspec.sl is idempotent + 5. Static-linking the xspec module works again. + 6. Added get_outer_viewport, set_outer_viewport. + ** Note that in the past, the low-level pgplot function + _pgsvp was often used to set the viewport for plots + created using isis intrinsic plot functions. With this + change, _pgsvp will no longer have the desired effect + on these plots. Use set_outer_viewport instead of _pgsvp. + 7. Changed handling of command-line arguments by isis-script. + Scripts no longer intercept command line arguments supported + by isis. + 8. Removed -l command-line option. + +Changes since 1.4.1 (released Sep 2006) +--------------------------------------- + 1. Ignored data ranges are now omitted from plots + rather than being plotted as all zeros. + 2. Loading a parameter file can now over-ride parameter functions + 3. In batch mode, a function named isis_main or slsh_main will + be called automatically, unless over-ridden by the '-t' + command-line argument. + 4. The configure script includes more thorough checks for + compatibility of GNU readline libraries. + 5. Binary packages can now find glob.sl + +Changes since 1.3.4 (released Jul 2006) +--------------------------------------- + 1. Added atexit() function. + 2. Added set_prompt() function (from Mike Noble) + 3. set_par() now supports regular expressions (based on + code from John E. Davis). + 4. oplot behaves like plot if no plots have been drawn + (from Mike Noble) + 5. Extensive rewrite of xspec module; added support for + new model interfaces introduced with xspec12. + 6. Added support for reading BACKSCAL, BG_COUNTS and + BG_AREA columns from type I and type II PHA files. + 7. Refined computation of background uncertainties + under rebinning; dropped the Gehrels approximation for + the background uncertainty when the number of background + counts is small. + +Changes since 1.3.3 (released Apr 2006) +--------------------------------------- + 1. Added eval_fun2() to support evaluating a fit-function + on an arbitrary grid without modifying the current + fit_fun() definition. + 2. add_slang_function() now supports functions defined by + reference. + 3. set_param_default_hook() now supports passing additional + arguments to the parameter default hook. + 4. get_fit_method() and get_fit_statistic() now return + strings containing the complete, current option settings. + 5. Operator functions should now be invoked as + operator(id, operand(k)) instead of + operator(operand(k), id) + In other words, the integer index should be the first + argument. + 6. Fit-functions can now take arbitrary additional parameters. + For example, something like this: + fit_fun ("foo(1, &bar, array, baz(1))"); + is now supported. For details, see the add_slang_function + documentation. + 7. Added GNU readline support (based on patches from Mike Noble) + +Changes since 1.3.2 (released Jan 2006) +--------------------------------------- + 1. set_rebin_error_hook now takes a reference to a function + 2. updated --with-ciao configure option + 3. Fixed bug in propagation of background uncertainties for + rebinned data. + 4. Added Gehrels_Threshold intrinsic variable to provide + more control over handling of uncertainties in low-count + data. + +Changes since 1.3.1 (released Nov 2005) +--------------------------------------- + 1. xspec module now supports xspec12 + 2. Added support for fit-constraints (see set_fit_constraint) + 3. cursor returns values which account for log-scale axes + 4. Added get_plot_options/set_plot_options + +Changes since 1.3.0 (released Sep 2005) +--------------------------------------- + 1. Modified region_counts/region_flux to handle both emission + and absorption features. + 2. Modified internal algorithm for rebinning flux-corrected data + allowing rebin_data/group_data to automatically rebin + flux-corrected data without running flux_corr again. + 3. Added isis_fit_improved_hook feature (see conf) + +Changes since 1.2.9 (released Jun 2005) +--------------------------------------- + 1. Changed the method used to set parameter defaults for + S-Lang fit-functions. See set_param_default_hook(). + 2. Added Voigt profile fit-function + 3. Modified internal parameter handling logic to better support + re-defining fit-functions. Tied parameters are now more + robust against changes in the fitted model. + +Changes since 1.2.8 (released Apr 2005) +--------------------------------------- + 1. Support more intuitive syntax in set_par_fun() 2nd argument. + See set_par_fun() help page for details. + 2. Update xspec module to support HEASOFT-6.0 + 3. Update to slang2 definition of require/provide + 4. Update to include slang2 help-file support + 5. Prompt namespace is now named "isis" + 6. Added support for backscale vectors defined via _define_bgd + and set_data_backscale. + 7. Handling of multiple merged grids should now work as + advertised. Earlier versions used the first merged grid + encountered for all subsequent cases. + +Changes since 1.2.7 (released Mar 2005) +--------------------------------------- + 1. Update cfitsio module (slcfitsio-0.3.2) + 2. Added rebin_combined() + 3. Added support for slang-2 debugger. + 4. Added fit-method "minim" (alternate simplex algorithm) + 5. Removed internal limit to support reading RMFs from Swift + +Changes since 1.2.6 (released Jan 2005) +--------------------------------------- + 1. Added set_dataset_metadata/get_dataset_metadata, + load_data_hook, list_data_hook + 2. Fixed bug in rebin_data() associated with handling of rebin + masks with zeros at the short wavelength end. + 3. Fixed bug introduced by recent changing in handling of + zero-based norm indices in add_slang_function. + 4. Updated --with-ciao option to work with new Ciao release; + see the INSTALL.txt file for details. + 5. Added support for comment header in fit-model parameter files + (comment lines have long been supported, just not as a + header, preceding the model definition line). + 6. pgplot module intrinsics are working again on Mac OS X. + 7. Uncertainties computed for background-subtracted, rebinned, + flux-corrected data now properly includes the background + contribution. + 8. Fixed obscure bug in fit-parameter lookups when fit-functions + are redefined multiple times while in use. + 9. Added isis_start_eval_hook() +10. New intrinsic variable Ignore_PHA_Response_Keywords. + If non-zero, isis will ignore the ANCRFILE and RESPFILE + keywords in PHA file headers. Default value is zero. +11. New intrinsic variable Rmf_OGIP_Compliance. + If zero, isis will require less strict adherence to the + OGIP standard format for RMFs. +12. Update cfitsio module; new version includes many + improvements and greatly expanded documentation. +13. Update pgplot module; the handling of 2D arrays changed. +14. rebin_dataset now supports rebinning the background + +Changes since 1.2.4 (released Nov 2004) +--------------------------------------- + 1. Updated cfitsio module + 2. Better handling of ylog/yrange transitions in rplot_counts/rplot_flux + 3. Use unit exposure time when fitting flux-corrected data. + 4. Added better Levenberg-Marquardt implementation (lmdif); + the previous implementation is still available, in part + because it provides certain features not available with lmdif. + 5. add_slang_function now uses zero-based indices to specify + norm parameters + 6. Added --with-atomdb configure option to specify path at compile time + +Changes since 1.2.2 (released Jul 2004) +--------------------------------------- + 1. Update xspec module to support built-in local models. + 2. Updated install documentation to resolve potential + Mac OS X build problems. + 3. Added support for setting plot symbol size independent of + character height; see point_size(); + 4. Plot color 0 now correctly gives the default background color + 5. Internal changes to support migration to slang-2.0 + 6. Support kernel option to control model computation + in ignored energy ranges during fitting. + 7. Rebinned RMFs now use threshold=0 to avoid resolution problems. + +Changes since 1.2.1 (released Apr 2004) +--------------------------------------- + 1. Fix bug in application of s/n threshold during + flux-correction of rebinned data. + 2. Added isis_set_par_hook() + 3. Added functions get_rmf_arf_grid(), get_rmf_data_grid() + 4. Added support for user-defined model evaluation grids, + primarily to support extended grids for convolution models. + See set_eval_grid_method() + 5. Added isis_prefit_hook(). + 6. Added add_abundances() function. + 7. get_abundances() now returns a Struct_Type. + 8. Fixed bug in single-parameter confidence limits computation: + When confidence limits were computed for one of only two + variable parameters, the remaining free parameter was not + varied during the fit. With the bug-fix, the free parameter + is varied correctly. + 9. New function mt_create_from_struct() + +Changes since 1.1.8 (released Feb 2004) +--------------------------------------- + 1. set_rebin_error_hook(id,NULL) now works as it should + 2. Fit parameter names are now parsed on input + 3. Added _phabs to xspec-module; _wabs now returns wabs + instead of phabs. + 4. Resolved ambiguity in definition of model_flux by + introducing "convolved_model_flux". Now, model_flux + always means \int dE S(E) -- the physical spectrum model + integrated over the bin width. The convolved_model_flux + is this function folded through the RMF, \int dE R(h,E)S(E), + and is useful primarily when dealing with flux-corrected + data. Functions have been provided to get, plot and + oplot this quantity. + 5. Added optimization to improve performance when fitting + multiple datasets with overlapping wavelength grids. + See set_eval_grid_method(). + 6. Modified rebin_data to ensure that the mask array includes + trailing noticed bins (at the long wavelength end) + containing zero counts into the last "good" bin + +Changes since 1.1.7 (released Nov 2003) +---------------------------------------- + 1. Added frame_time to get_data_info() structure + 2. Fixed bug in temp storage allocation logic when combining datasets + 3. prand() no longer modifies array arguments + 4. Added list_free function to list only free parameters + 5. xylabel now works transparently with log axis scales + 6. Added support for lheasoft-5.3 + 7. Corrected cash statistic handling of cases model=0 or data=0 + 8. New connect_points() option suppresses plotting of points, + drawing the line only. + +Changes since 1.1.6 (released Sep 2003) +---------------------------------------- + 1. flux_corr_model_counts() now populates the model_flux + rather than the data_flux. + 2. Bugfix - under certain conditions, closing a non-existent plot + window and then opening a plot window could cause a segv. + 3. interpol() wasn't extrapolating properly. + +Changes since 1.1.5 (released Aug 2003) +---------------------------------------- + 1. Changed definition of reverse indices for both + histogram and histogram2d. The dimensions of the + histogram2d result now match the input grid sizes. + 2. seed_random() bugfix. + 3. set_arf_info() bugfix. It was incorrectly modifying + the ARF size. + +Changes since 1.1.4 (released July 2003) +---------------------------------------- + 1. Support optional weight argument for combine_datasets() + 2. Add get_combined() function to simplify handling + dataset combinations. + 3. Added set_post_model_hook () + 4. Fixed obscure isis bug which could cause a segv if + flux_corr() were called from inside a fit-function. + 5. Enhanced set_par(), assign_arf(), assign_rmf() to + handle more combinations of vector parameters. + 6. Fixed bug in handling of XMM/EPIC rmfs + +Changes since 1.1.3 (released June 2003) +---------------------------------------- + 1. Provided specialized FFT option to speed pileup fits + 2. Fixed bug in line_info() which caused intermittent + problems on some architectures. + 3. [*] Changed thermal line profile sigma definition, + adding a factor of 0.5 to the vturb^2 term. + 4. Added all_arfs() and all_rmfs() functions. + 5. rplot_counts()/rplot_flux() is now consistent with the + current fit-statistic. This required a change in the + interface for user-defined fit-statistics. + 6. list_data and list_arf optionally show data filenames; + filenames also available via get_data_info. Related new + intrinsic variable is 'Isis_List_Filenames'. + 7. Support listing physical units of fit-function parameters. + 8. array_fit() now supports verbose mode. + +Changes since 1.1.2 (released May 2003) +---------------------------------------- + 1. Added workaround for a known pgplot bug which sometimes + incorrectly plots the last histogram bin width. + 2. Added factor_rsp() to support factoring an RSP matrix + into an ARF and a normalized RMF. + 3. Removed unused parameter 'npars' from the interface + definition for user-defined fit-statistics. + see add_slang_statistic(). + 4. xspec local model input now handles models not written + in Fortran. + 5. Fixed bug in plot_elev() - plot paging and character + size were not properly updated. + +Changes since 1.1.1 (released May 2003) +---------------------------------------- + 1. Added plot_linelist() function + 2. Updated handling of abundance tables; added new function + get_abundances() + +Changes since 1.1.0 (released Apr 2003) +---------------------------------------- + 1. get/set_arf_info now includes fracexpo + 2. improved plot format inheritance logic + 3. added add_help_file() + 4. added set_fake() + 5. Fixed bug in handling of dataset groups. + 6. Faster Poisson random generator + +Changes since 1.0.50 (released Mar 2003) +---------------------------------------- + 1. xspec module now loads via require("xspec") + 2. script and module load paths now use slang-1.4.9 intrinsics + 3. get_kernel() now returns kernel parameter string. + 4. new list_kernels() function + 5. new path-searching functionality. + Related functions include + get_isis_load_path() get_isis_module_path() + set_isis_load_path() set_isis_module_path() + prepend_to_isis_load_path() prepend_to_isis_module_path() + append_to_isis_load_path() append_to_isis_module_path() + The older functions + add_to_isis_load_path() + add_to_isis_module_path() + are now deprecated. + 6. Added _orplot_counts(), _orplot_flux() + 7. Improved/simplified startup procedures for binary and cdrom + distributions + 8. Fixed bug in FITS RMF input code that, in very rare cases, + could cause a core dump. + 9. Updated cfitsio module + +Changes since 1.0.48 (released Feb 2003) +---------------------------------------- + 1. fixed bug which sometimes allowed fit-function to be + evaluated at parameter values outside specified limits. + 2. readcol now handles out-of-order columns correctly + 3. better plot line width handling + 4. update to remove conflict with cumsum function in slang-1.4.9 + +Changes since 1.0.8 (released April 2002) +----------------------------------------- + 1. pileup model error handling code could segv + 2. axes of 2nd page plots weren't always getting labeled + 3. added include/exclude functions + 4. add_atable_model() now automatically includes a norm parameter + 5. new function: get_fit_fun() + 6. updated FITS module + 7. new_function: array_fit() + 8. added xspec_abund() and xspec_xsect() functions to XSPEC module + 9. Cash statistic matches XSPEC definition and supports conf. limits +10. Updated handling of EXPTIME, TIMEDEL keywords to compute CCD frame_time +11. Modified handling of automatic color changes on overplots. +12. contrib files updated +13. Added interface version checking for all plugins +14. plot_bin_density now plots count-rates +15. Added histogram2d() function +16. Added make_hi_grid() function +17. Added plot_image(), plot_image_ctrl(), set_palette(), plot_contour() +18. Better error messages for RMF input validity checks +19. Added xspec-module auto-loader +20. xspec table models now read param names from the FITS file. +21. Added interpol() function to do linear interpolation +22. Added interpol_points() and fit_search() +23. Added array_struct_field() +24. New 'Use_Memory' options support loading all continua up front +25. Added get_fun_components(). +26. Added xspec_xset(), xspec_set_cosmo(), xspec_get_cosmo() +27. Added mt_def_model(), mt_calc_model(), mt_list_model(), + mt_save_model(), mt_load_model(). +28. Added create_aped_fun() +29. Added _bmc() wrapper in xspec-module +30. Added fit_search_info() and isis_save_par_hook() +31. xspec [m,e]table models now support a redshift parameter +32. plot_image and plot_contour now respect [xy]range and + can automatically plot images with the correct aspect-ratio. +33. Updated xspec-module _shock, _nei, _sedov to include Ar abundance. +34. Tweak create_aped_fun() so renorm works. +35. New no-semicolons interactive mode (see Isis_Append_Semicolon) +36. xspec-module can now load XSPEC local models. +37. get_data_info/set_data_info can modify target name string +38. fixed bug in allocation of subplex workspace +39. errorbars() supports plotting every Nth errorbar. +40. set_frame_line_width/set_line_width functions improve control + over plot line widths. +41. support plots with axes X (Y)-axes increasing leftward (downward) +42. workaround apparent pgplot bug to properly align low-resolution + contour plots +43. [o]hplot now takes a Struct_Type +44. _A() enhanced to take a Struct_Type +45. New functions ignore_list, notice_list +46. Added flux_corr_model_counts +47. Port to Mac OS X; moved INSTALL to INSTALL.txt to avoid + build problems on the case-insensitive Mac filesystem. +48. Added seed_random() function to seed the random number generator +49. Added support for grouping datasets. +50. Fixed bug in exposure-scaling of instrument background + when the ARF is included in the RMF. +51. Fixed bug in exposure-scaling of numbers read from plot by ifit_fun +52. Added support for fitting operator models (such as + convolution models in xspec). Updated xspec module to + include convolution models. +53. Read TSTART keyword from spectrum file header. +54. By default, isis now installs into /usr/local/isis. After + installing, the source-code directory can now be deleted. +55. Added shift, any, howmany +56. rebin function handles monotonic decreasing grids, etc. +57. histogram function ignores NaNs. +58. bugfix: unassign_rmf() wasn't looping over dataset lists +59. readcol now skips blank lines +60. conf_map_counts/flux now supports mask function. +61. Removed the Conf_Map_Fail_Hook and Conf_Map_Save_Hook + intrinsic variables. These hooks should now be provided + as struct fields. See conf_map_counts for details. +62. conf_map_counts/flux now supports mask function to speed + computations by avoiding user-specified regions of parameter space +63. bugfix - flux_corr was zeroing model_flux +64. added cumulative sum function, cumsum + +####################################################################### +####################################################################### + +Changes to pre-release 1.0: +-------------------------- + * improve conf_[o]plot + * add support for handling fit-parameters by name + (see set_par() and related functions) + * add --with-lheasoft config option to support + statically linking the xspec module + * added --disable-xspec_tables config option + * support default parameter values for user-defined + functions + * add load_dataset() function to simply common + sequence of load_data/arf/rmf, assign_arf/rmf + * support assign_rmf() to grouped data + * fixed minor bug in conf-limits convergence test; + should now converge better + * better pileup regression test (from John Davis) + +(the last pre-1.0 version was 0.9.86) + +Changes since 0.9.60 + * Added ignore_en(), notice_en(), xnotice_en() + * Added readcol() and writecol() + * Added fconf(), vfconf() + * Added set_rebin_error_hook() + * Added Conf_Map_Counts_Hook, Conf_Map_Flux_Hook + * Added isis_add_help_hook() + * Added isis_set_pager(), isis_get_pager(); + * Wrote a code-generator which automatically generates ISIS + bindings for all additive and multiplicative models in XSPEC. + To avoid conflicts with the XSPEC names, two ISIS intrinsic + fit-function names were changed: + __OLD_name___NEW_name___ + powerlaw Powerlaw + lorentz Lorentz + * Added mpane() function to select plot panes + * Changed the way uncertainties are computed for + rebinned, flux-corrected data when the counts + are available. Now, isis uses + flux_err = flux * stat_err/counts. + The previous method of setting flux_err to 1.0 in + zero-count bins and adding flux_errs in quadrature + over-estimated the uncertainty, particularly for + low-count data. + * Added set_fit_range_hook() + * Included some regression tests in the distribution + * documented get_params, set_params functions + * get_data_info() now returns an array of structs. + * Changed function names for consistency and added + documentation (only one was previously documented..) + get_hist_exposure => get_data_exposure + get_hist_backscale => get_data_backscale + set_hist_exposure => set_data_exposure + set_hist_backscale => set_data_backscale + copy_hist_keywords => copy_data_keywords + * documented rebin_dataset(), rebin_rmf() functions + * Added save_input() function + * Added support for generating 2D plots of chi-square + confidence contours (see conf_map_counts, conf_map_flux, + conf_[o]plot, conf_joint) + * Added latex2pg() function to support annotating plots + with LaTeX-format strings. + * Added isis_linelabel_hook() function to generate + better formatted emission line labels in spectrum plots + * Added egauss() fit-function + * More xspec models: mtable, etable + * Changed "regrid" => "rebin" + * Added Isis_Residual_Plot_Type intrinsic variable to + control residual plots (see rplot_counts/rplot_flux) + * Added rebin_array() function. + * More xspec models: pexrav, pexriv, laor, bknpower + * Fit-parameter values may now be defined as functions of + other fit-parameters. See set_par_fun(). + * User-defined fit-functions may now evaluate differently + for different datasets. See Isis_Active_Dataset. + * Added append_model() function + * Changed model_spectrum() interface to support selecting + lines-only or continuum-only + * Added Cash statistic plus alternate forms of Chi-square. + * Added support for user-defined fit-statistics written + in S-Lang. See add_slang_statistic() + * Removed 'force' option from assign_arf(). + * Added support for multiple responses per data set + (e.g. for LETG multi-order fitting). See assign_rsp(). + * flux_corr() is now more precise -- see manual. + * duplicate line BUG fixed: + When both the wavelength tables and line emissivity + tables were loaded from the APEC 1.01 database, lines + which had an observed wavelength "WAVE_OBS" value + were listed twice in the input line list. + +Changes since 0.9.51 + * Added the histogram() function for creating 1-D histograms. + * Added the trans() filter for the Spectroscopy database + * Added get_iback() function to retrieve the scaled + instrumental background + * Added eval_fun() to compute the current fit-function + on a user-defined grid. + * Added optional arg to errorbars() to control length + of terminal bars. + * Added fakeit() function + * Updated FITS i/o module. + * Added all_data() utility function. + * Added rplot_counts(), rplot_flux() to simplify + plotting residuals + * Added improved background handling -- See define_bgd() + and _define_bgd() functions. + * Added --stdin command line option to support + reading commands from stdin and bypassing + readline. + * Added iback_fun () function to support fitting + instrumental background. + * Added tbabs, tbvabs, tbgrain to xspec module + +Changes since 0.9.47 + * Added define_model() function + * Added 'subplex' as alternative to the Levenburg- + Marquardt minimization algorithm. + * Modified Levenburg-Marquardt algorithm to + fall back on Singular Value Decomposition if + LU-Decomposition fails (LU decomp. is faster + and works most of the time). + * Added support for user-defined fit-methods and + fit-statistics using code contributed by + John Davis + * Added define_arf(), get_arf_info(), set_arf_info() + + * Two Important Plotting Changes: + + 1) The handling of multi-pane plots has changed. + The new implementation automatically shifts the plot + focus to the next pane each time a new plot is + created. This simplifies creating postscript + files which contain multiple pages of plots. + However, it is no longer easy to access plot panes + in random order using the 'pane' function. + As a result, the 'pane' function has been removed, + although similar functionality is available from + the low-level PGPLOT function '_pgpanl'. + + 2) A new function 'multiplot' has been added to + simplify creating plots with multiple panes sharing + a common X-axis. + +Changes since 0.9.30 + * Added zgauss, vphabs, mkcflow to xspec-module + * Fixed bug in flux_corr -- ignored intervals weren't + properly handled since the gpileup kernel was added + * Added zwabs, zpowerlaw, diskline to xspec-module + * updated XSPEC module to maintain compatibility with + lheasoft_v5.1.0/xspec_v11.1.0 + * Added ignore_bad() function + * Added rebin_rmf() from John Davis + * Generalized RMF and PHA file handling to support XMM data + * Added comptt, smedge to xspec-module. + * Added set_data_info function + * Added support for non-square, delta-function RMFs [obscure, no?] + * Fixed bug in parameter handling - models with duplicate + functions weren't handled properly (e.g. gauss(1)+gauss(1)). + * Fixed bug in tie() function - order of index arguments was reversed. + * Added define_counts/define_flux functions + +Changes since 0.9.11: + + * Important Change: + + The following functions now return an error code: + + fit_counts, fit_flux, + eval_counts, eval_flux, + renorm_counts, renorm_flux + + See the manual for details. + + This was an important change to allow fitting scripts to + run more smoothly and is a significant improvement over the + earlier implementation. + + However, this change may require you to modify your fitting + scripts. Here is one quick way to update your scripts to + simply ignore the new return code: + + perl -p -i -e "s|fit_flux|() = fit_flux|" *.sl + perl -p -i -e "s|eval_flux|() = eval_flux|" *.sl + perl -p -i -e "s|renorm_flux|() = renorm_flux|" *.sl + perl -p -i -e "s|fit_counts|() = fit_counts|" *.sl + perl -p -i -e "s|eval_counts|() = eval_counts|" *.sl + perl -p -i -e "s|renorm_counts|() = renorm_counts|" *.sl + + * Added gpileup kernel from John Davis + * Added ISIS_LOAD_PATH env. variable and improved "require" + function + * Added blackbody function + * Added set_frame_time function + * Added user-defined plot format defaults (intrinsic structure + called _isis_plot) + * Removed hard-coded limits on the number of simultaneous + fit-functions and fit-parameters. + * Tuned hash function to speed line table lookups + * Require bin_hi[i] = bin_lo[i+1] on spectrum input + (the input spectrum grid can't have holes in it) + * Added pgplot-module update from John Davis + * Fixed bug in poly function parameter handling + * Fixed bug in handling of kernel params with user-defined fit + functions (fixed in 0.9.14) + * Fixed bug in handling of multiple simultaneous fit-kernels. + * Reorganized source code directories, simplified configure scripts + +Changes since 0.9.10: + * Fixed bug in handling of kernel parameters + * Fixed bug in handling of plot line-styles + * Added support for /usr/bin/env executable isis scripts + +Changes since 0.9.4: + * Restored load_rmf/assign_rmf for symmetry with ARF functions + * Removed redundant fit_fold() function + * Added renorm(), group_data(), randomize() functions. + * Much needed update of the manual. + * Added fit_counts, fit_flux, fit_fold, etc. alternatives to + provide a mode-free interface to data analysis. + * Changed get_data_*, put_data_* functions to use structures + * Made modifications to support new database file layout. + * Removed pfiles interface to spectroscopy database + * Environment setup script is now optional. + * Fixed a bug preventing generation of multiple plots in a + single postscript file. + * Added FITS i/o module from John Davis + * Added pileup kernel from John Davis + * Restructured fit module internals + * Removed feature-table prototype code + * Moved pgplot-module into isis/src - pgplot functions now + available by default. + +Changes since 0.8.6: + * Changed 'group' to 'lines_in_group' + * Added new optional argument to open_plot() to support a new + multiplot style, useful for plotting data and residuals + on the same page. + * Improved line-label formatting options - see plot_group() and + line_label_default_style (). + * Added support for dynamically linked user-defined RMF functions; + [*** functions load_rmf() and delete_rmf() were removed, + the assign_rmf() interface was significantly changed, as + was the output from list_rmf() and list_data() ***]. + * New database content list functions list_db() and vlist_db() plus + filtering options on plasma() function. + * New database access function line_em1() to retrieve emissivities + using the tabulated temperature/density grid + * New mode-free functions plot_model_counts(), plot_model_flux(), + get_model_counts(), put_data_counts(), etc. + * New get_param_info() function + * New tolerance parameter on conf() and vconf() + * Support for database with density sensitivity -- obsolete database + format no longer supported. + * User-defined functions can now supply default parameter values, etc. + * Better handling of interactive automatic plot limits + * Simplified linux installation of xspec module + * Changed axis labeling on log-scale plots + * Models computed using model_spectrum() now have + relativistically correct redshifts. + * Changed interface for user-defined fit-functions + * Changed order of optional arguments to set_par() function + +Changes since 0.7.4beta: + * New set_arf_exposure() and get_data_info() functions. + * Now support fitting internally re-binned data -- no need for grppha. + * Command line arguments now available to batch-processed files + (see __argc, __argv[]) + * New Plot_Autoscale intrinsic variable + * New .source command + * New file option for edit_par() and edit_model() + * The .isisrc file is now read before batch files, unless the -f option is used. + * New auxiliary fit-kernel option + * Fixed some install-script bugs associated with --prefix= + * Added support for RMF input and usage including forward folding + * Added FFT function wrapper fft1d () + * Fixed list truncation bug in line_em() (which was introduced in 0.7.3beta) + * No longer rely on user's XANADU or PGPLOT_DIR environment variables at run-time. + +Changes since 0.7.3beta: + * Support change in format of APEC continuum emissivity file. + * Added regrid() function to support adding +/- orders and adding ARFs. + +Changes since 0.7.2beta: + * Help system provides ISIS function descriptions. + * Added ascii.sl to examples directory -- example of I/O of ascii columns. + * User-defined fit functions may now be implemented in S-Lang. + * Support change in spectroscopy database format (additional HDU). + * Upgraded XSPEC module to support XSPEC_v11.0, added new xspec functions. + +Changes since 0.7.1beta: + * Help system provides S-Lang function descriptions. + * Type I pha file input now supported. + * Added rebin_data() function. + * Added print() function to simplify printing arrays struct fields. + +$Id: Changes.txt,v 1.225 2004/09/10 11:23:53 houck Exp $ diff --git a/INSTALL.txt b/INSTALL.txt new file mode 100644 index 0000000..d04cd5b --- /dev/null +++ b/INSTALL.txt @@ -0,0 +1,676 @@ + ISIS: Interactive Spectral Interpretation System + http://space.mit.edu/cxc/isis + + Send bug reports, comments and suggestions to + isis-users@space.mit.edu + +This file describes how to install ISIS on a Unix system. See +the ISIS User's Guide for instructions on how to run ISIS. + +Contents: + I. Binary install + II. Installing from source code + III. Spectroscopy database setup + IV. Installation Suggestions for Specific Architectures + V. Troubleshooting + +I. BINARY INSTALL +================= + +1. Download the appropriate ISIS binary distribution from + http://space.mit.edu/cxc/isis/download.html: + + isis-$version.lin.tar.gz (source code + Linux binaries) + isis-$version.sol.tar.gz (source code + Solaris binaries) + +2. In the directory in which you want to install the software, + unpack the file you selected, e.g. + + gunzip -C isis-$version.lin.tar.gz + +3. The ISIS binary installation relies on the environment + variable ISIS_SRCDIR. This variable is used to locate + the files ISIS needs at run-time. To run ISIS: + + For C Shell variants (csh, tcsh): + + setenv ISIS_SRCDIR /path/to/unpacked/isis + $ISIS_SRCDIR/bin/isis + + For Bourne Shell (sh, ash, ksh, bash): + + ISIS_SRCDIR=/path/to/installed/isis + export ISIS_SRCDIR + $ISIS_SRCDIR/bin/isis + + Note that, if you wish to use the precompiled XSPEC module, + you must also initialize the HEADAS software (which must + be downloaded and installed separately). At the time of + this writing, the HEADAS initialization procedure is very + similar, e.g. for Csh variants: + + setenv HEADAS /path/to/installed/headas/$ARCH + source $HEADAS/headas-init.csh + +4. See section (III) for instructions on setting up the + spectroscopy database. + +II. INSTALLING FROM SOURCE CODE +=============================== + +Quick Start for Experts: +------------------------ + +To build ISIS, the S-Lang, CFITSIO and PGPLOT libraries must be +installed on your system. Many ISIS users also make use of the +XSPEC spectral model library. If XSPEC is already installed, +ISIS can use the PGPLOT and CFITSIO libraries included with +XSPEC. + +Assuming that S-Lang has been installed in a standard location +such as /usr/local, the following commands will compile and +install ISIS in /usr/local: + + ./configure --with-headas=$HEADAS + make + make install + +HEADAS gives the path to your local HEASOFT installation. + +To make use of the APED spectroscopy database installed in +$ATOMDB, include the configure option: + + --with-atomdb=$ATOMDB + +To install ISIS in DIR, include the configure option: + + --prefix=DIR + +For help on other configure options, do: + + ./configure --help + +For a much more detailed discussion of the installation +procedure and the various configure options, see below. + +Software Requirements: +---------------------- + +PGPLOT, CFITSIO and S-Lang must be installed before installing ISIS. The +following versions (or newer) are required: + + pgplot_5.2 (with C bindings installed) + cfitsio_2.1 + slang-2.0.0 + +To obtain the newest versions of these packages see: + (pgplot) http://www.astro.caltech.edu/~tjp/pgplot/install.html + (cfitsio) http://heasarc.gsfc.nasa.gov/docs/software/fitsio/fitsio.html + (slang) http://www.s-lang.org/download.html + +IMPORTANT: Shared libraries are preferred! + + To make full use of importable modules, shared libraries + (e.g. libcfitsio.so or libcfitsio.dylib) should be installed + whenever possible. If static libraries are installed (e.g. + libcfitsio.a) the module functionality may not work properly + on certain platforms (e.g. Mac OS X). + + When building slang, use 'make elf install-elf'. + When building cfitsio, use 'make shared'. + When building pgplot, use 'make libpgplot.so'. + +Unix Installation: +------------------ + +0. The steps below assume that the ISIS tar file was unpacked in + isis-$version and that up-to-date versions of PGPLOT, CFITSIO and + S-Lang are installed somewhere on your system. + +Here's a quick summary of the minimum required installation steps, +which will install isis into /usr/local/isis by default. + + 0. unsetenv LD_LIBRARY_PATH + 1. ./configure [--with-headas=$HEADAS ...] + 2. make + 3. make check (Optional: this runs some self-tests) + 4. make install + +More detailed installation instructions follow. Before starting +the installation, you might also check section (IV) below to +see if there are installation suggestions for your particular +platform, especially if you're building ISIS from source for +Mac OS X. + +First, cd to the ISIS source directory: + + cd isis-$version + +0. Its usually a good idea to unset the LD_LIBRARY_PATH + environment variable when building ISIS: + + unsetenv LD_LIBRARY_PATH + + This can prevent run-time problems caused by interaction + with other packages that set LD_LIBRARY_PATH. + +1. Choose compilers. + + If you wish to use the default compilers (cc, f77) and they + are available in your environment, proceed to step 2. + + If you want to use a different compiler, the simplest way is + to specify the compiler using environment variables. For + example: + + setenv CC gcc-4.0 + setenv FC g95-4.0 + + Note that if you want to use the XSPEC module, it may + be necessary to compile ISIS using the same C compiler + that was used to compile XSPEC. See modules/xspec/README + for details. + +2. Locate required packages and determine the configure options: + + If the required libraries are not installed in standard + locations, e.g. /usr/lib, their locations must be provided + when you run the configure script. + + Find the directories containing the following files from + the CFITSIO, PGPLOT and S-Lang distributions: + + CFITSIO include: fitsio.h + CFITSIO library: libcfitsio.so + + PGPLOT include: cpgplot.h + PGPLOT libraries: libpgplot.so, libcpgplot.a + + S-Lang include: slang.h + S-Lang library: libslang.so + + For each package, if the library is in DIR/lib and the + include file is in DIR/include, the DIR path can be + provided to the configure script using an option like, e.g. + + --with-slang=DIR + + However, if the library is in LIB_DIR and the include file + is in INC_DIR, both paths should be provided using options + like, e.g.: + + --with-pgplotlib=/usr/local/pgplot + --with-pgplotinc=/usr/local/pgplot + + To make use of the XSPEC spectral models, it will be + necessary to provide the path to your HEADAS installation + using + --with-headas=$HEADAS + + where is the path to your local 'headas' installation. + + If you wish to compile the XSPEC module and statically link + it with ISIS (instead of loading the module via dynamic + linking at ISIS run-time), add the configure option + --with-xspec-static=$HEADAS (This option is not recommended.) + + If you wish to specify the location of your spectroscopy + database at this time, use the '--with-atomdb' configure + option + --with-atomdb=$ATOMDB + + where $ATOMDB is the path to the top-level directory, e.g. + ATOMDB=/data/atomdb/aped-1.3.1. This configure option is + optional, because path may also be specified by setting the + ATOMDB environment variable. + +3. Run the configure script. + + Although many alternatives are possible here, the main + idea is to specify the required paths from step 2. + + Use the 'prefix' option to specify where isis should be + installed: + + ./configure --prefix=DIR --with-headas=$HEADAS + + By default, DIR=/usr/local. By default, the configure + script will look for slang, cfitsio and pgplot in their + standard install directories and in DIR. + + Alternatively , if slang, cfitsio and pgplot are installed + in the *same* non-standard location (e.g. in OTHER_DIR/lib, + OTHER_DIR/include, and OTHER_DIR/pgplot), one need specify + only the relevant top-level directory where these packages + are installed. For example: + + ./configure --prefix=DIR --with-dep=OTHER_DIR \ + --with-headas=$HEADAS + + More generally, if the required packages are installed in a + variety of non-standard locations, one can provide all + necessary library paths explicitly, using something like + this: + + ./configure --prefix=/soft \ + --with-cfitsio=/soft/opt \ + --with-slang=/soft/extra \ + --with-pgplotlib=/soft/pgplot \ + --with-pgplotinc=/soft/pgplot \ + --with-headas=/soft/headas/$ARCH \ + --with-atomdb=/soft/atomdb/aped-1.3.1 + + If Ciao-4.x has been installed, it may be possible to build + isis by linking to the libraries included in Ciao + distribution. To do this, use the --with-ciao configure + option: + + ./configure --with-ciao=$ciao_install_dir \ + --with-pgplotlib="$PGPLOT_DIR" \ + --with-pgplotinc="$PGPLOT_DIR" + + Note that because the Ciao distribution does not contain + the PGPLOT library, a separate PGPLOT installation is + required. + +4. Compile and install ISIS: + + If there are installation suggestions for your platform, + they are listed in section IV below. + + To compile isis, type: + make + + To run some simple tests, type: + make check + + To install isis, type: + make install + + If 'configure' was run using --prefix=DIR, isis will be + installed in DIR/isis/$version. + + If DIR/bin exists, a symbolic link to the isis executable + will be placed there. Otherwise, the executable may be + found in DIR/isis/$version/bin/isis. + + To remove temporary files which are no longer needed type: + make clean + + At this point, ISIS installation is complete. + +III. SPECTROSCOPY DATABASE SETUP +================================= + + It may be sufficient to set the ATOMDB environment variable + to point to the location of your spectroscopy database. If + specific database filenames have changed, it may be necessary + to edit isis-$version/etc/aped.sl so that it matches your + spectroscopy database. Spectroscopy database files may be + obtained from e.g. + + http://cxc.harvard.edu/atomdb + + Note that the simplest configuration requires the emissivity + tables only. See the ISIS manual in isis-$version/doc/manual.pdf + or on the web page at http://space.mit.edu/cxc/isis for + details on which files are needed and how they should be + arranged. + +IV. Installation Suggestions for Specific Architectures +======================================================= + +gfortran: +-------- + +When mixing code compiled with g77 and gfortran, it may be +necessary to include additional libraries. If you encounter +problems with missing symbols like 's_copy', you might try +using the --with-fclibs configure option to provide the extra +libraries. For example: + + ./configure ... --with-fclibs="-lg2c" ... + +AIX systems: +----------- + +o The IBM compilers are preferred: CC=xlc and FC=xlf + +Linux systems: +------------- + +o pre-installed versions of S-Lang which are ancient/incompatible + + Some Linux distributions come with an older version of S-Lang + pre-installed, usually in /usr/lib and /usr/include. Because + ISIS uses some newer features of S-Lang, compilation of ISIS + will fail if the compiler links to this old version of S-Lang + instead of the current version. In particular, even if you + installed a new statically linked version of S-Lang + (/usr/lib/libslang.a), ISIS compilation can fail with complaints + about unresolved S-Lang symbols (e.g. SLang_pop_float()) if the + old dynamically linked S-Lang libraries (/usr/lib/libslang.so) + are still present. + + To correct this problem, you should install the most recent + version of S-Lang including the new dynamically linked libraries + (e.g. "make elf" then "make install-elf" then "ldconfig"). If + you have properly installed a new version of S-Lang and still + cannot compile ISIS under Linux, please send us a bug report + describing the details of the problem. + +Mac OS X systems: +----------------- + +o Fortran compiler issues + + Both the gfortran and g95 compilers have been reported to + work. In order to get a functioning Fortran compiler, you'll + probably need to install the Xcode developer tools from + Apple. To obtain a functioning g95 compiler, you'll probably + have to compile it from source via Fink, + http://www.finkproject.org/. + +o Dynamic Linking + + Dynamic linking to shared libraries behaves differently on + the Mac than on a real unix system. To avoid problems, be + sure to install shared libraries whenever possible. In + particular, when you install the S-Lang library, be sure to + install libslang.dylib via 'make elf install-elf'. + + Its also a good idea to avoid having multiple copies of the + same shared library if those copies are in directories that + are examined by your compiler when it runs. For example, + problems may arise if /usr/lib/libslang.dylib and + /usr/local/lib/libslang.dylib both exist but represent + different library versions. + + It may also be necessary to DYLD_LIBRARY_PATH to include + paths to all the shared libraries needed at run-time. + +o Missing libraries + + If you're using the version of PGPLOT provided by Fink, + you probably also need to edit EXTRA_LIB in src/Makefile + (in the ISIS distribution) to add + + -framework Foundation -framework AppKit -lpng + + After you're finished editing src/Makefile, build and install + ISIS as usual. + +V. TROUBLESHOOTING +=================== + +If ISIS didn't compile: + + If compilation fails because of undefined symbols or missing + libraries, you may need to provide additional libraries by + editing the definition of FLIBS in src/Makefile. If some + necessary header files were missing, you may also need to edit + src/Makefile to provide the necessary directory paths. + After editing the Makefile(s), repeat step 4 above. + + If your compiler doesn't understand "-Wl," or if your link + editor doesn't understand "-R", the RPATH definition in + src/Makefile may cause problems. The purpose of that + declaration is to store the path to the dynamically linked SLANG + and PGPLOT libraries (libslang.so and libpgplot.so) within the + ISIS executable so that they are available at run-time. If + you're using dynamically linked libraries and the RPATH + definition, you should try to provide the equivalent declaration + for your compiler. Failing that, you can comment out the RPATH + definition and provide the necessary run-time paths by editing + your LD_LIBRARY_PATH environment variable. + +Known Bugs: +----------- + +o Some versions of the Linux rlogin program are buggy. When using + rlogin to connect to a Solaris 2.6 machine from a Linux machine, + output from ISIS (and other programs) can intermittently + disappear. The simplest workaround is to use telnet instead of + rlogin. A bug-fix for the Linux rlogin is also available. + +o The Solaris version of qsort() has a bug that causes it to read + from uninitialized memory. We have so far encountered no + problems caused by this, but if it leads to a problem, we will + provide a bug-free replacement for qsort() in a future version. + +---------------------------------------------------------------------------- +Below, I have attached the generic INSTALL instructions included in the +autoconf distribution. These instructions provide more detail on how the +configure script works and also describe other installation options which +may be supported by the configure script. +---------------------------------------------------------------------------- + +Copyright (C) 1994, 1995, 1996, 1999, 2000, 2001, 2002 Free Software +Foundation, Inc. + + This file is free documentation; the Free Software Foundation gives +unlimited permission to copy, distribute and modify it. + +Basic Installation +================== + + These are generic installation instructions. + + 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 only 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. If you're + using `csh' on an old version of System V, you might need to type + `sh ./configure' instead to prevent `csh' from trying to execute + `configure' itself. + + Running `configure' takes awhile. 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. + + 4. Type `make install' to install the programs and any data files and + documentation. + + 5. 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. + +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=c89 CFLAGS=-O2 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 must use a version of `make' that +supports the `VPATH' variable, such as 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 `..'. + + If you have to use a `make' that does not support the `VPATH' +variable, you have 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. + +Installation Names +================== + + By default, `make install' will install the package's files in +`/usr/local/bin', `/usr/local/man', etc. You can specify an +installation prefix other than `/usr/local' by giving `configure' the +option `--prefix=PATH'. + + You can specify separate installation prefixes for +architecture-specific files and architecture-independent files. If you +give `configure' the option `--exec-prefix=PATH', the package will use +PATH as the prefix for installing programs and libraries. +Documentation and other data files will still use the regular prefix. + + In addition, if you use an unusual directory layout you can give +options like `--bindir=PATH' 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. + + 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'. + +Optional Features +================= + + 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. + +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 `--target=TYPE' option 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 + +will cause the specified gcc to be used as the C compiler (unless it is +overridden in the site shell script). + +`configure' Invocation +====================== + + `configure' recognizes the following options to control how it +operates. + +`--help' +`-h' + Print a summary of the options to `configure', and exit. + +`--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. + +`configure' also accepts some other, not widely useful, options. Run +`configure --help' for more details. + diff --git a/README b/README new file mode 100644 index 0000000..7108637 --- /dev/null +++ b/README @@ -0,0 +1,38 @@ +README file for ISIS. + +ISIS is a programmable, extensible data analysis system +developed for use in high-resolution X-ray spectroscopy. + +It is currently distributed as source code and with +precompiled binaries for selected operating systems. +The lastest release is available from + + http://space.mit.edu/cxc/isis/download.html + +For installation instructions, read INSTALL.txt + +For news on recent changes and new features, read Changes.txt. +A copy of the manual is included in the 'doc' directory. +Additional information about ISIS is available from + + http://space.mit.edu/cxc/isis + +A mailing list is also available. See + http://space.mit.edu/cxc/isis/mailing_list.html +for more information. + + + Contents: + + doc - ISIS documentation + etc - local configuration information, including + parameter file(s) describing local + spectroscopy database(s) + contrib - User-contributed scripts + + test - ISIS self-test data and scripts + src - ISIS source code + share + modules - source code for loadable modules (e.g. XSPEC) + + diff --git a/autoconf/Makefile.in b/autoconf/Makefile.in new file mode 100644 index 0000000..bb4c765 --- /dev/null +++ b/autoconf/Makefile.in @@ -0,0 +1,123 @@ +# -*- sh -*- + +# $Id: Makefile.in,v 1.34 2004/02/09 11:14:12 houck Exp $ + +#----------------------------------------------------------------------- +# This file is part of ISIS, the Interactive Spectral Interpretation System +# Copyright (C) 1998-2008 Massachusetts Institute of Technology +#----------------------------------------------------------------------- + +@SET_MAKE@ +SHELL = /bin/sh +RM = /bin/rm -f +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ + +#--------------------------------------------------------------------------- +# Install information +#--------------------------------------------------------------------------- +prefix = @prefix@ +exec_prefix = @exec_prefix@ +install_lib_dir = @libdir@ +install_include_dir = @includedir@ +BIN_DIR = @bindir@ + +# for the XSPEC module, if it is statically linked +LINK_XSPEC_STATIC = @LINK_XSPEC_STATIC@ +HEADAS_DIR = @HEADAS_DIR@ + +all: + cd src; $(MAKE) all + cd modules; $(MAKE) all + @echo "" + @echo "To continue with the installation, type" + @echo " make install" + @echo "" + +check: + cd test; $(MAKE) check + +install-check: + cd test; $(MAKE) install-check + +install: test_install_dir + cd src; $(MAKE) install + cd modules; $(MAKE) install + @if test "$(LINK_XSPEC_STATIC)" = "yes" ; then \ + cd modules/xspec/src ; make install-extra ; \ + fi + @echo "" + @echo "Installation complete." + @echo "" + @echo "To delete temporary files which are no longer needed, type" + @echo " make clean" + @echo "" + +elf: + cd src; $(MAKE) elf + cd modules; $(MAKE) elf + +install-elf: test_install_dir + cd src; $(MAKE) install-elf + cd modules; $(MAKE) install-elf + +install-modules: test_install_dir + cd modules; $(MAKE) install-modules + +custom-xspec-module: + cd modules/xspec/src; make clean new-xspec12-code +custom-xspec11-module: + cd modules/xspec/src; make clean new-xspec11-code +custom-xspec12-module: + cd modules/xspec/src; make clean new-xspec12-code + +tags-file: + -$(RM) tags + ctags src/*.[ch] share/*.sl modules/xspec/src/xspec* + +clean: + cd src; $(MAKE) clean + cd modules; $(MAKE) clean + cd test; $(MAKE) clean + -$(RM) *~ .##* + +distclean: + cd src; $(MAKE) distclean + cd modules; $(MAKE) distclean + cd test; $(MAKE) distclean + -$(RM) isis-version + $(MAKE) confclean + +confclean: + -$(RM) Makefile config.status config.log config.cache files.pck autoconf/f77test.out .##* *~ + +test_install_dir: + @if test "$(prefix)" = "`pwd`" ; then \ + echo "" ;\ + echo "*** Please don't install into the distribution directory" ; \ + echo "" ;\ + exit 1 ; \ + fi + +# The symlinks target is for my own private use. It simply creates the object +# directory as a symbolic link to a local disk instead of an NFS mounted one. +symlinks: + cd src; $(MAKE) symlinks + cd modules; $(MAKE) symlinks + +tags: + etags -o TAGS src/*.[ch] + +# +# These targets are used by the maintainer +# +configure: autoconf/aclocal.m4 autoconf/configure.ac + cd autoconf && autoconf && /bin/rm -rf autom4te.cache && mv ./configure .. +update: autoconf/config.sub autoconf/config.guess +autoconf/config.guess: /usr/share/misc/config.guess + /bin/cp -f /usr/share/misc/config.guess autoconf/config.guess +autoconf/config.sub: /usr/share/misc/config.sub + /bin/cp -f /usr/share/misc/config.sub autoconf/config.sub + +snapshot: + @src/mkdist.sh /nfs/vex/d2/release/snapshots/isis-`date +%Y%m%d` diff --git a/autoconf/README.cdrom b/autoconf/README.cdrom new file mode 100644 index 0000000..67891a4 --- /dev/null +++ b/autoconf/README.cdrom @@ -0,0 +1,20 @@ + +To start ISIS, run the 'isis' script. +If the CD-ROM is mounted as /cdrom, then type + + /cdrom/isis + +Contents: +========= + isis - ISIS startup script + isis_src - ISIS source code and binaries + for Linux (glibc-2.2) and Solaris + atomdb - APED spectroscopy database + lheasoft - XSPEC binaries for Linux and Solaris + +Send comments, suggestions and bug reports to + isis-users@space.mit.edu + +For more information on ISIS, see + http://space.mit.edu/cxc/isis + diff --git a/autoconf/aclocal.m4 b/autoconf/aclocal.m4 new file mode 100644 index 0000000..91a3bc0 --- /dev/null +++ b/autoconf/aclocal.m4 @@ -0,0 +1,1649 @@ +dnl# -*- mode: sh; mode: fold -*- +dnl Here are some global variables that need initialized. + +AC_DEFUN(JH_CONFIG_DIR_SANS_AMD, dnl#{{{ +[ +CONFIG_DIR_SANS_AMD=$PWD +AC_SUBST(CONFIG_DIR_SANS_AMD)dnl +]) + +dnl#}}} + +AC_DEFUN(JD_INIT, dnl#{{{ +[ +#These variable are initialized by JD init function +CONFIG_DIR=`pwd` +cd $srcdir +if test "`pwd`" != "$CONFIG_DIR" + then + AC_MSG_ERROR("This software does not support configuring from another directory. See the INSTALL file") + fi +AC_SUBST(CONFIG_DIR)dnl +# Note: these will differ if one is a symbolic link +if test -f /usr/bin/dirname; then + JD_Above_Dir=`dirname $CONFIG_DIR` +else +# system is a loser + JD_Above_Dir=`cd ..;pwd` +fi +JD_Above_Dir2=`cd ..;pwd` +]) + +dnl#}}} + +dnl# This function expand the "prefix variables. For example, it will expand +dnl# values such as ${exec_prefix}/foo when ${exec_prefix} itself has a +dnl# of ${prefix}. This function produces the shell variables: +dnl# jd_prefix_libdir, jd_prefix_incdir +AC_DEFUN(JD_EXPAND_PREFIX, dnl#{{{ +[ + if test "X$jd_prefix" = "X" + then + jd_prefix=$ac_default_prefix + if test "X$prefix" != "XNONE" + then + jd_prefix="$prefix" + fi + jd_exec_prefix="$jd_prefix" + if test "X$exec_prefix" != "XNONE" + then + jd_exec_prefix="$exec_prefix" + fi + + dnl#Unfortunately, exec_prefix may have a value like ${prefix}, etc. + dnl#Let the shell expand those. Yuk. + eval `sh <>)dnl +define(<<$2>>, translit($1, [a-z], [A-Z]))dnl +changequote([, ])dnl +]) +#}}} + +AC_DEFUN(JD_SIMPLE_LIB_DIR, dnl#{{{ +[ +JD_UPPERCASE($1,JD_UP_NAME) +JD_UP_NAME[]_LIB_DIR=$JD_Above_Dir/$1/src/"$ARCH"objs +JD_UP_NAME[]_INCLUDE=$JD_Above_Dir/$1/src + +if test -z "[$]JD_UP_NAME[]_INCLUDE" +then + echo Unable to find the JD_UP_NAME directory + echo You may have to edit $CONFIG_DIR/src/Makefile. +fi + +AC_SUBST(JD_UP_NAME[]_LIB_DIR)dnl +AC_SUBST(JD_UP_NAME[]_INCLUDE)dnl +undefine([JD_UP_NAME])dnl +]) + +dnl#}}} + +AC_DEFUN(JD_FIND_GENERIC, dnl#{{{ +[ + AC_REQUIRE([JD_EXPAND_PREFIX])dnl + + changequote(<<, >>)dnl + define(<>, translit($1, [a-z], [A-Z]))dnl + changequote([, ])dnl +# Look for the JD_UP_NAME package +#JD_UP_NAME[]_INCLUDE="" +#JD_UP_NAME[]_LIB_DIR="" + +# This list consists of "include,lib include,lib ..." +JD_Search_Dirs="$JD_Above_Dir2/$1/libsrc,$JD_Above_Dir2/$1/libsrc/"$ARCH"objs \ + $JD_Above_Dir/$1/libsrc,$JD_Above_Dir/$1/libsrc/"$ARCH"objs \ + $JD_Above_Dir2/$1/src,$JD_Above_Dir2/$1/src/"$ARCH"objs \ + $JD_Above_Dir/$1/src,$JD_Above_Dir/$1/src/"$ARCH"objs" + +JD_Search_Dirs="$JD_Search_Dirs \ + $jd_prefix_incdir,$jd_prefix_libdir \ + $HOME/include,$HOME/lib" + +if test -n "$ARCH" +then + JD_Search_Dirs="$JD_Search_Dirs $HOME/include,$HOME/$ARCH/lib" + JD_Search_Dirs="$JD_Search_Dirs $HOME/include,$HOME/sys/$ARCH/lib" +fi + +# Now add the standard system includes. The reason for doing this is that +# the other directories may have a better chance of containing a more recent +# version. + +JD_Search_Dirs="$JD_Search_Dirs \ + /usr/local/include,/usr/local/lib \ + /usr/include,/usr/lib \ + /usr/include/$1,/usr/lib \ + /usr/include/$1,/usr/lib/$1" + +echo looking for the JD_UP_NAME library + +for include_and_lib in $JD_Search_Dirs +do + # Yuk. Is there a better way to set these variables?? + generic_include=`echo $include_and_lib | tr ',' ' ' | awk '{print [$]1}'` + generic_lib=`echo $include_and_lib | tr ',' ' ' | awk '{print [$]2}'` + echo Looking for $1.h in $generic_include + echo and lib$1.a in $generic_lib + if test -r $generic_include/$1.h && test -r $generic_lib/lib$1.a + then + echo Found it. + JD_UP_NAME[]_LIB_DIR="$generic_lib" + JD_UP_NAME[]_INCLUDE="$generic_include" + break + else + if test -r $generic_include/$1.h && test -r $generic_lib/lib$1.so + then + echo Found it. + JD_UP_NAME[]_LIB_DIR="$generic_lib" + JD_UP_NAME[]_INCLUDE="$generic_include" + break + fi + fi +done + +if test -n "[$]JD_UP_NAME[]_LIB_DIR" +then + jd_have_$1="yes" +else + echo Unable to find the $JD_UP_NAME library. + echo You may have to edit $CONFIG_DIR/src/Makefile. + JD_UP_NAME[]_INCLUDE=$JD_Above_Dir/$1/src + JD_UP_NAME[]_LIB_DIR=$JD_Above_Dir/$1/src/"$ARCH"objs + jd_have_$1="no" +fi + +JD_UP_NAME[]_INC="-I[$]JD_UP_NAME[]_INCLUDE" +JD_UP_NAME[]_LIB="-L[$]JD_UP_NAME[]_LIB_DIR" +JD_SET_RPATH([$]JD_UP_NAME[]_LIB_DIR) +dnl if test "X$GCC" = Xyes +dnl then +dnl RPATH_[]JD_UP_NAME="-Wl,-R[$]JD_UP_NAME[]_LIB_DIR" +dnl else +dnl RPATH_[]JD_UP_NAME="-R[$]JD_UP_NAME[]_LIB_DIR" +dnl fi + +# gcc under solaris is often not installed correctly. Avoid specifying +# -I/usr/include. +if test "[$]JD_UP_NAME[]_INC" = "-I/usr/include" +then + JD_UP_NAME[]_INC="" +fi + +if test "[$]JD_UP_NAME[]_LIB" = "-L/usr/lib" +then + JD_UP_NAME[]_LIB="" + RPATH_[]JD_UP_NAME="" +fi + +AC_SUBST(JD_UP_NAME[]_LIB)dnl +AC_SUBST(JD_UP_NAME[]_INC)dnl +AC_SUBST(JD_UP_NAME[]_LIB_DIR)dnl +AC_SUBST(JD_UP_NAME[]_INCLUDE)dnl +dnl AC_SUBST(RPATH_[]JD_UP_NAME)dnl +undefine([JD_UP_NAME])dnl +]) + + +dnl#}}} + +AC_DEFUN(JD_FIND_SLANG, dnl#{{{ +[ +JD_FIND_GENERIC(slang) +]) + +dnl#}}} + +AC_DEFUN(JH_PURIFY, dnl#{{{ +[ +AC_ARG_ENABLE(purify, + [ --enable-purify compile with Purify], + [use_purify=$enableval]) +if test -n "$use_purify" +then + CC="purify -windows=no -log-file=purify.log $CC" + FC="purify -windows=no -log-file=purify.log $FC" +fi +]) + +dnl#}}} + +AC_DEFUN(JD_GCC_WARNINGS, dnl#{{{ +[ +AC_ARG_ENABLE(warnings, + [ --enable-warnings turn on GCC compiler warnings], + [gcc_warnings=$enableval]) +if test -n "$GCC" +then + CFLAGS="$CFLAGS -fno-strength-reduce" + if test -n "$gcc_warnings" + then + CFLAGS="$CFLAGS \ + -ansi -pedantic -D__EXTENSIONS__ -D_XOPEN_SOURCE -D_POSIX_C_SOURCE \ + -W -Wall \ + -Wpointer-arith -Wcast-align -Wcast-qual \ + -Wstrict-prototypes \ + -Wshadow \ + -Waggregate-return \ + -Wmissing-prototypes \ + -Wnested-externs" + # Now trim excess whitespace + CFLAGS=`echo $CFLAGS` + fi +fi +]) + +dnl#}}} + +IEEE_CFLAGS="" +AC_DEFUN(JD_IEEE_CFLAGS, dnl#{{{ +[ +case "$host_cpu" in + *alpha* ) + if test "$GCC" = yes + then + IEEE_CFLAGS="-mieee" + else + IEEE_CFLAGS="-ieee_with_no_inexact" + fi + ;; + * ) + IEEE_CFLAGS="" +esac +]) + +dnl#}}} + +AC_DEFUN(JD_APPEND_RULES, dnl#{{{ +[ + echo "$PROGRAM_OBJECT_RULES" >> $1 + PROGRAM_OBJECT_RULES="" +]) +dnl#}}} + +AC_DEFUN(JH_APPEND_FC_RULES, dnl#{{{ +[ + echo "$PROGRAM_FC_OBJECT_RULES" >> $1 + PROGRAM_FC_OBJECT_RULES="" +]) +dnl#}}} + +AC_DEFUN(JD_APPEND_ELFRULES, dnl#{{{ +[ + echo "$PROGRAM_ELF_ORULES" >> $1 + PROGRAM_ELF_ORULES="" +]) + +dnl#}}} + +AC_DEFUN(JH_APPEND_FC_ELFRULES, dnl#{{{ +[ + echo "$PROGRAM_FC_ELF_ORULES" >> $1 + PROGRAM_FC_ELF_ORULES="" +]) + +dnl#}}} + +AC_DEFUN(JD_CREATE_ORULE, dnl#{{{ +[ +PROGRAM_OBJECT_RULES="$PROGRAM_OBJECT_RULES +\$(OBJDIR)/$1.o : \$(SRCDIR)/$1.c \$(DOT_O_DEPS) \$("$1"_O_DEP) + cd \$(OBJDIR); \$(COMPILE_CMD) \$("$1"_C_FLAGS) \$(SRCDIR)/$1.c +" +]) + +dnl#}}} + +AC_DEFUN(JH_CREATE_FC_ORULE, dnl#{{{ +[ +PROGRAM_FC_OBJECT_RULES="$PROGRAM_FC_OBJECT_RULES +\$(OBJDIR)/$1.o : \$(SRCDIR)/$1.f \$(DOT_O_DEPS) \$("$1"_O_DEP) + cd \$(OBJDIR); \$(FC_COMPILE_CMD) \$("$1"_FC_FLAGS) \$(SRCDIR)/$1.f +" +]) + +dnl#}}} + +AC_DEFUN(JD_CREATE_ELFORULE, dnl#{{{ +[ +PROGRAM_ELF_ORULES="$PROGRAM_ELF_ORULES +\$(ELFDIR)/$1.o : \$(SRCDIR)/$1.c \$(DOT_O_DEPS) \$("$1"_O_DEP) + cd \$(ELFDIR); \$(ELFCOMPILE_CMD) \$("$1"_C_FLAGS) \$("$1"_ELFC_FLAGS) \$(SRCDIR)/$1.c +" +]) + +dnl#}}} + +AC_DEFUN(JH_CREATE_FC_ELFORULE, dnl#{{{ +[ +PROGRAM_FC_ELF_ORULES="$PROGRAM_FC_ELF_ORULES +\$(ELFDIR)/$1.o : \$(SRCDIR)/$1.f \$(DOT_O_DEPS) \$("$1"_O_DEP) + cd \$(ELFDIR); \$(FC_ELFCOMPILE_CMD) \$("$1"_FC_FLAGS) \$("$1"_ELF_FC_FLAGS) \$(SRCDIR)/$1.f +" +]) + +dnl#}}} + +AC_DEFUN(JD_CREATE_EXEC_RULE, dnl#{{{ +[ +PROGRAM_OBJECT_RULES="$PROGRAM_OBJECT_RULES +$1 : \$(OBJDIR)/$1 + @echo $1 created in \$(OBJDIR) +\$(OBJDIR)/$1 : \$(OBJDIR)/$1.o \$("$1"_DEPS) \$(EXECDEPS) + \$(CC) -o \$(OBJDIR)/$1 \$(LDFLAGS) \$(OBJDIR)/$1.o \$("$1"_LIBS) \$(EXECLIBS) +\$(OBJDIR)/$1.o : \$(SRCDIR)/$1.c \$(DOT_O_DEPS) \$("$1"_O_DEP) + cd \$(OBJDIR); \$(COMPILE_CMD) \$("$1"_INC) \$("$1"_C_FLAGS) \$(EXECINC) \$(SRCDIR)/$1.c +" +]) + +dnl#}}} + +AC_DEFUN(JD_CREATE_FLINK_EXEC_RULE, dnl#{{{ +[ +PROGRAM_OBJECT_RULES="$PROGRAM_OBJECT_RULES +$1 : \$(OBJDIR)/$1 + @echo $1 created in \$(OBJDIR) +\$(OBJDIR)/$1 : \$(OBJDIR)/$1.o \$("$1"_DEPS) \$(EXECDEPS) + \$(FC) \$(FCFLAGS) -o \$(OBJDIR)/$1 \$(LDFLAGS) \$(OBJDIR)/$1.o \$("$1"_LIBS) \$(EXECLIBS) +\$(OBJDIR)/$1.o : \$(SRCDIR)/$1.c \$(DOT_O_DEPS) \$("$1"_O_DEP) + cd \$(OBJDIR); \$(COMPILE_CMD) \$("$1"_INC) \$("$1"_C_FLAGS) \$(EXECINC) \$(SRCDIR)/$1.c +" +]) + +dnl#}}} + +AC_DEFUN(JD_CREATE_MODULE_ORULES, dnl#{{{ +[ + Program_Modules="Program_Modules_$1" + cmd="eval echo \$$Program_Modules" + list=`$cmd` + for program_module in $list; do + JD_CREATE_ORULE($program_module) + JD_CREATE_ELFORULE($program_module) + done +]) + +dnl#}}} + +AC_DEFUN(JH_CREATE_FC_MODULE_ORULES, dnl#{{{ +[ + Program_FC_Modules="Program_FC_Modules_$1" + cmd="eval echo \$$Program_FC_Modules" + list=`$cmd` + for program_module in $list; do + JH_CREATE_FC_ORULE($program_module) + JH_CREATE_FC_ELFORULE($program_module) + done +]) + +dnl#}}} + +AC_DEFUN(JD_CREATE_MODULE_EXEC_RULES, dnl#{{{ +[ + Program_Modules="Program_Modules_$1" + cmd="eval echo \$$Program_Modules" + list=`$cmd` + for program_module in $list; do + JD_CREATE_EXEC_RULE($program_module) + done +]) + +dnl#}}} + +dnl# This macro process the --with-xxx, --with-xxxinc, and --with-xxxlib +dnl# command line arguments and returns the values as shell variables +dnl# jd_xxx_include_dir and jd_xxx_library_dir. It does not perform any +dnl# substitutions, nor check for the existence of the supplied values. +AC_DEFUN(JD_WITH_LIBRARY_PATHS, dnl#{{{ +[ + JD_UPPERCASE($1,JD_ARG1) + jd_$1_include_dir="" + jd_$1_library_dir="" + jd_with_$1_library="" + + AC_ARG_WITH($1, + [ --with-$1=DIR Use DIR/lib and DIR/include for $1], + [jd_with_$1_arg=$withval], [jd_with_$1_arg=unspecified]) + + case "x$jd_with_$1_arg" in + xno) + jd_with_$1_library="no" + ;; + x) + AC_MSG_ERROR(--with-$1 requires a value-- try yes or no) + ;; + xunspecified) + ;; + xyes) + ;; + *) + jd_$1_include_dir="$jd_with_$1_arg"/include + jd_$1_library_dir="$jd_with_$1_arg"/lib + ;; + esac + + AC_ARG_WITH($1lib, + [ --with-$1lib=DIR $1 library in DIR], + [jd_with_$1lib_arg=$withval], [jd_with_$1lib_arg=unspecified]) + case "x$jd_with_$1lib_arg" in + xunspecified) + ;; + xno) + ;; + x) + AC_MSG_ERROR(--with-$1lib requres a value) + ;; + *) + jd_$1_library_dir="$jd_with_$1lib_arg" + ;; + esac + + AC_ARG_WITH($1inc, + [ --with-$1inc=DIR $1 include files in DIR], + [jd_with_$1inc_arg=$withval], [jd_with_$1inc_arg=unspecified]) + case "x$jd_with_$1inc_arg" in + x) + AC_MSG_ERROR(--with-$1inc requres a value) + ;; + xunspecified) + ;; + xno) + ;; + *) + jd_$1_include_dir="$jd_with_$1inc_arg" + ;; + esac +]) +dnl#}}} + +dnl# This function checks for the existence of the specified library $1 with +dnl# header file $2. If the library exists, then the shell variables will +dnl# be created: +dnl# jd_with_$1_library=yes/no, +dnl# jd_$1_inc_file +dnl# jd_$1_include_dir +dnl# jd_$1_library_dir +AC_DEFUN(JD_CHECK_FOR_LIBRARY, dnl#{{{ +[ + AC_REQUIRE([JD_EXPAND_PREFIX])dnl + dnl JD_UPPERCASE($1,JD_ARG1) + JD_WITH_LIBRARY_PATHS($1) + AC_MSG_CHECKING(for the $1 library and header files $2) + if test X"$jd_with_$1_library" != Xno + then + jd_$1_inc_file=$2 + dnl# jd_with_$1_library="yes" + + if test "X$jd_$1_inc_file" = "X" + then + jd_$1_inc_file=$1.h + fi + if test X"$jd_$1_include_dir" = X + then + lib_include_dirs="\ + $jd_prefix_incdir \ + $jh_depdir/include \ + $jh_depdir/pgplot \ + /usr/local/$1/include \ + /usr/local/include/$1 \ + /usr/local/include \ + /usr/include/$1 \ + /usr/$1/include \ + /usr/include \ + /opt/include/$1 \ + /opt/$1/include \ + /opt/include" + + for X in $lib_include_dirs + do + if test -r "$X/$jd_$1_inc_file" + then + jd_$1_include_dir="$X" + break + fi + done + if test X"$jd_$1_include_dir" = X + then + jd_with_$1_library="no" + fi + fi + + if test X"$jd_$1_library_dir" = X + then + lib_library_dirs="\ + $jd_prefix_libdir \ + $jh_depdir/lib \ + $jh_depdir/pgplot \ + /usr/local/lib \ + /usr/local/lib/$1 \ + /usr/local/$1/lib \ + /usr/lib \ + /usr/lib/$1 \ + /usr/$1/lib \ + /opt/lib \ + /opt/lib/$1 \ + /opt/$1/lib" + + case "$host_os" in + *darwin* ) + exts="dylib so a" + ;; + *cygwin* ) + exts="dll.a so a" + ;; + * ) + exts="so a" + esac + + found=0 + for X in $lib_library_dirs + do + for E in $exts + do + if test -r "$X/lib$1.$E" + then + jd_$1_library_dir="$X" + found=1 + break + fi + done + if test $found -eq 1 + then + break + fi + done + if test X"$jd_$1_library_dir" = X + then + jd_with_$1_library="no" + fi + fi + fi + + if test X"$jd_$1_include_dir" != X -a "$jd_$1_library_dir" != X + then + AC_MSG_RESULT(yes: $jd_$1_library_dir and $jd_$1_include_dir) + jd_with_$1_library="yes" + dnl# Avoid using /usr/lib and /usr/include because of problems with + dnl# gcc on some solaris systems. + JD_ARG1[]_LIB=-L$jd_$1_library_dir + if test "X$jd_$1_library_dir" = "X/usr/lib" + then + JD_ARG1[]_LIB="" + else + JD_SET_RPATH($jd_$1_library_dir) + fi + + JD_ARG1[]_INC=-I$jd_$1_include_dir + if test "X$jd_$1_include_dir" = "X/usr/include" + then + JD_ARG1[]_INC="" + fi + else + AC_MSG_RESULT(no) + jd_with_$1_library="no" + JD_ARG1[]_INC="" + JD_ARG1[]_LIB="" + fi + AC_SUBST(JD_ARG1[]_LIB) + AC_SUBST(JD_ARG1[]_INC) +]) +dnl#}}} + +AC_DEFUN(JD_WITH_LIBRARY, dnl#{{{ +[ + JD_CHECK_FOR_LIBRARY($1, $2) + if test "$jd_with_$1_library" = "no" + then + AC_MSG_ERROR(unable to find the $1 library and header file $jd_$1_inc_file) + fi +]) +dnl#}}} + +AC_DEFUN(JD_SLANG_VERSION, dnl#{{{ +[ + slang_h=$jd_slang_include_dir/slang.h + AC_MSG_CHECKING(SLANG_VERSION in $slang_h) +slang_version=`grep "^#define *SLANG_VERSION " $slang_h | + awk '{ print [$]3 }'` +slang_major_version=`echo $slang_version | + awk '{ print int([$]1/10000) }'` +slang_minor_version=`echo $slang_version $slang_major_version | + awk '{ print int(([$]1 - [$]2*10000)/100) }'` +slang_patchlevel_version=`echo $slang_version $slang_major_version $slang_minor_version | + awk '{ print ([$]1 - [$]2*10000 - [$]3*100) }'` + +AC_MSG_RESULT($slang_major_version.$slang_minor_version.$slang_patchlevel_version) +AC_SUBST(slang_version) +AC_SUBST(slang_major_version) +AC_SUBST(slang_minor_version) +AC_SUBST(slang_patchlevel_version) +]) +#}}} + +AC_DEFUN(JD_SLANG_MODULE_INSTALL_DIR, dnl#{{{ +[ + AC_REQUIRE([JD_SLANG_VERSION]) + if test "X$slang_major_version" = "X1" + then + MODULE_INSTALL_DIR="$libdir/slang/modules" + else + MODULE_INSTALL_DIR="$libdir/slang/v$slang_major_version/modules" + fi + SL_FILES_INSTALL_DIR=$datadir/slsh/local-packages + AC_SUBST(MODULE_INSTALL_DIR) + AC_SUBST(SL_FILES_INSTALL_DIR) +]) +#}}} + +AC_DEFUN(JD_GET_MODULES, dnl#{{{ +[ + if test -z "$1" + then + Program_Modules="" + else + Program_Modules=`cat $1` + fi + PROGRAM_OFILES="" + PROGRAM_OBJECTS="" + PROGRAM_ELFOBJECTS="" + for program_module in $Program_Modules; do + PROGRAM_OFILES="$PROGRAM_OFILES $program_module.o" + PROGRAM_OBJECTS="$PROGRAM_OBJECTS \$(OBJDIR)/$program_module.o" + PROGRAM_ELFOBJECTS="$PROGRAM_ELFOBJECTS \$(ELFDIR)/$program_module.o" + done +Program_Modules_$2=$Program_Modules +PROGRAM_OFILES_$2=$PROGRAM_OFILES +PROGRAM_OBJECTS_$2=$PROGRAM_OBJECTS +PROGRAM_ELFOBJECTS_$2=$PROGRAM_ELFOBJECTS +AC_SUBST(PROGRAM_OFILES_$2)dnl +AC_SUBST(PROGRAM_OBJECTS_$2)dnl +AC_SUBST(PROGRAM_ELFOBJECTS_$2)dnl +]) + +dnl#}}} + +AC_DEFUN(JH_GET_FC_MODULES, dnl#{{{ +[ + if test -z "$1" + then + Program_FC_Modules="" + else + Program_FC_Modules=`cat $1` + fi + PROGRAM_FC_OFILES="" + PROGRAM_FC_OBJECTS="" + PROGRAM_FC_ELFOBJECTS="" + for program_module in $Program_FC_Modules; do + PROGRAM_FC_OFILES="$PROGRAM_FC_OFILES $program_module.o" + PROGRAM_FC_OBJECTS="$PROGRAM_FC_OBJECTS \$(OBJDIR)/$program_module.o" + PROGRAM_FC_ELFOBJECTS="$PROGRAM_FC_ELFOBJECTS \$(ELFDIR)/$program_module.o" + done +Program_FC_Modules_$2=$Program_FC_Modules +PROGRAM_FC_OFILES_$2=$PROGRAM_FC_OFILES +PROGRAM_FC_OBJECTS_$2=$PROGRAM_FC_OBJECTS +PROGRAM_FC_ELFOBJECTS_$2=$PROGRAM_FC_ELFOBJECTS +AC_SUBST(PROGRAM_FC_OFILES_$2)dnl +AC_SUBST(PROGRAM_FC_OBJECTS_$2)dnl +AC_SUBST(PROGRAM_FC_ELFOBJECTS_$2)dnl +]) + +dnl#}}} + +AC_DEFUN(JH_GET_SHAREFILES, dnl#{{{ +[ + if test -z "$1" + then + Program_Sharefiles="" + else + Program_Sharefiles=`cat $1` + fi + PROGRAM_SHAREFILES="" + for program_share in $Program_Sharefiles; do + PROGRAM_SHAREFILES="$PROGRAM_SHAREFILES $program_share" + done +AC_SUBST(PROGRAM_SHAREFILES)dnl +]) + +dnl#}}} + +AC_DEFUN(JH_GET_ETCFILES, dnl#{{{ +[ + if test -z "$1" + then + Program_Etcfiles="" + else + Program_Etcfiles=`cat $1` + fi + PROGRAM_ETCFILES="" + for program_etc in $Program_Etcfiles; do + PROGRAM_ETCFILES="$PROGRAM_ETCFILES $program_etc" + done +AC_SUBST(PROGRAM_ETCFILES)dnl +]) + +dnl#}}} + +AC_DEFUN(JH_LIST_ELFOBJECTS, dnl#{{{ +[ + Other_Modules=`cat $1/modules.lis` + other_elfobjects="" + for other_module in $Other_Modules; do + other_elfobjects="$other_elfobjects \$(ELFDIR_$2)/$other_module.o" + done +ELFOBJECTS_$2="$other_elfobjects" +ELFDIR_$2="\$(config_dir)/$1/\$(ARCH)elfobjs" +AC_SUBST(ELFOBJECTS_$2)dnl +AC_SUBST(ELFDIR_$2)dnl +]) + +dnl#}}} + +AC_DEFUN(JD_TERMCAP, dnl#{{{ +[ +AC_MSG_CHECKING(for Terminfo) +MISC_TERMINFO_DIRS="$FINKPREFIX/share/terminfo" +if test ! -d $MISC_TERMINFO_DIRS +then + MISC_TERMINFO_DIRS="" +fi + +JD_Terminfo_Dirs="/usr/lib/terminfo \ + /usr/share/terminfo \ + /usr/share/lib/terminfo \ + /usr/local/lib/terminfo \ + $MISC_TERMINFO_DIRS" + +TERMCAP=-ltermcap + +for terminfo_dir in $JD_Terminfo_Dirs +do + if test -d $terminfo_dir + then + AC_MSG_RESULT(yes) + TERMCAP="" + break + fi +done +if test "$TERMCAP"; then + AC_MSG_RESULT(no) + AC_DEFINE(USE_TERMCAP) +fi +AC_SUBST(TERMCAP)dnl +AC_SUBST(MISC_TERMINFO_DIRS)dnl +]) + +dnl#}}} + +AC_DEFUN(JD_ANSI_CC, dnl#{{{ +[ +AC_PROG_CC +AC_PROG_CPP +AC_PROG_GCC_TRADITIONAL +AC_ISC_POSIX +AC_AIX + +dnl #This stuff came from Yorick config script +dnl +dnl # HPUX needs special stuff +dnl +AC_EGREP_CPP(yes, +[#ifdef hpux + yes +#endif +], [ +AC_DEFINE(_HPUX_SOURCE) +if test "$CC" = cc; then CC="cc -Ae"; fi +])dnl +dnl +dnl #Be sure we've found compiler that understands prototypes +dnl +AC_MSG_CHECKING(C compiler that understands ANSI prototypes) +AC_TRY_COMPILE([ ],[ + extern int silly (int);], [ + AC_MSG_RESULT($CC looks ok. Good.)], [ + AC_MSG_RESULT($CC is not a good enough compiler) + AC_MSG_ERROR(Set env variable CC to your ANSI compiler and rerun configure.) + ])dnl +])dnl + +dnl#}}} + +AC_DEFUN(JD_ELF_COMPILER, dnl#{{{ +[ +dnl #------------------------------------------------------------------------- +dnl # Check for dynamic linker +dnl #------------------------------------------------------------------------- +DYNAMIC_LINK_LIB="" +AC_CHECK_HEADER(dlfcn.h,[ + AC_DEFINE(HAVE_DLFCN_H) + AC_CHECK_LIB(dl,dlopen,[ + DYNAMIC_LINK_LIB="-ldl" + AC_DEFINE(HAVE_DLOPEN) + ],[ + AC_CHECK_FUNC(dlopen,AC_DEFINE(HAVE_DLOPEN)) + if test "$ac_cv_func_dlopen" != yes + then + case "$host_os" in + *darwin* ) + dnl # assuming dlcompat is from Fink + AC_CHECK_FILE(/sw/lib/libdl.a,[ + DYNAMIC_LINK_LIB="-L/sw/lib -ldl" + AC_DEFINE(HAVE_DLOPEN) + ],[ + AC_MSG_WARN(cannot perform dynamic linking) + ]) + ;; + * ) + AC_MSG_WARN(cannot perform dynamic linking) + ;; + esac + fi + ])]) +AC_SUBST(DYNAMIC_LINK_LIB) + +ELFLIB="lib\$(THIS_LIB).so" +ELFLIB_MAJOR="\$(ELFLIB).\$(ELF_MAJOR_VERSION)" +ELFLIB_MAJOR_MINOR="\$(ELFLIB).\$(ELF_MAJOR_VERSION).\$(ELF_MINOR_VERSION)" + +SLANG_LIB_FOR_MODULES=# +CFITSIO_LIB_FOR_MODULES=# +ISIS_LIB_FOR_MODULES=# +INSTALL_MODULE="\$(INSTALL_DATA)" +SLANG_DLL_CFLAGS="" + +if test "$GCC" = yes +then + if test X"$CFLAGS" = X + then + CFLAGS="-O2" + fi +fi + +case "$host_os" in + *linux* ) + DYNAMIC_LINK_FLAGS="-Wl,-export-dynamic" + ELF_CC="\$(CC)" + ELF_CFLAGS="\$(CFLAGS) -fPIC" + ELF_LINK="\$(CC) \$(LDFLAGS) -shared -Wl,-soname#" + ELF_LINK_CMD="\$(ELF_LINK),\$(ELFLIB_MAJOR)" + ELF_DEP_LIBS="\$(DL_LIB) -lm -lc" + CC_SHARED="\$(CC) \$(CFLAGS) -shared -fPIC" + ELF_FC_FCFLAGS="-fPIC" + ;; + *solaris* ) + if test "$GCC" = yes + then + DYNAMIC_LINK_FLAGS="" + ELF_CC="\$(CC)" + ELF_CFLAGS="\$(CFLAGS) -fPIC" + ELF_LINK="\$(CC) \$(LDFLAGS) -shared -Wl,-ztext -Wl,-h#" + ELF_LINK_CMD="\$(ELF_LINK),\$(ELFLIB_MAJOR)" + ELF_DEP_LIBS="\$(DL_LIB) -lm -lc" + CC_SHARED="\$(CC) \$(CFLAGS) -G -fPIC" + ELF_FC_FCFLAGS="-fPIC" + else + DYNAMIC_LINK_FLAGS="" + ELF_CC="\$(CC)" + ELF_CFLAGS="\$(CFLAGS) -KPIC" + ELF_LINK="\$(CC) \$(LDFLAGS) -G -h#" + ELF_LINK_CMD="\$(ELF_LINK)\$(ELFLIB_MAJOR)" + ELF_DEP_LIBS="\$(DL_LIB) -lm -lc" + CC_SHARED="\$(CC) \$(CFLAGS) -G -KPIC" + ELF_FC_FCFLAGS="-KPIC" + fi + ;; + # osr5 or unixware7 with current or late autoconf + *sco3.2v5* | *unixware-5* | *sco-sysv5uw7*) + if test "$GCC" = yes + then + DYNAMIC_LINK_FLAGS="" + ELF_CC="\$(CC)" + ELF_CFLAGS="\$(CFLAGS) -fPIC" + ELF_LINK="\$(CC) \$(LDFLAGS) -shared -Wl,-h#" + ELF_LINK_CMD="\$(ELF_LINK),\$(ELFLIB_MAJOR)" + ELF_DEP_LIBS= + CC_SHARED="\$(CC) \$(CFLAGS) -G -fPIC" + ELF_FC_FCFLAGS="-fPIC" + else + DYNAMIC_LINK_FLAGS="" + ELF_CC="\$(CC)" + ELF_CFLAGS="\$(CFLAGS) -Kpic" + # ELF_LINK="ld -G -z text -h#" + ELF_LINK="\$(CC) \$(LDFLAGS) -G -z text -h#" + ELF_LINK_CMD="\$(ELF_LINK)\$(ELFLIB_MAJOR)" + ELF_DEP_LIBS= + CC_SHARED="\$(CC) \$(CFLAGS) -G -Kpic" + ELF_FC_FCFLAGS="-Kpic" + fi + ;; + *irix6.5* ) + echo "Note: ELF compiler for host_os=$host_os may not be correct" + echo "double-check: 'mode_t', 'pid_t' may be wrong!" + if test "$GCC" = yes + then + # not tested + DYNAMIC_LINK_FLAGS="" + ELF_CC="\$(CC)" + ELF_CFLAGS="\$(CFLAGS) -fPIC" + ELF_LINK="\$(CC) \$(LDFLAGS) -shared -Wl,-h#" + ELF_LINK_CMD="\$(ELF_LINK),\$(ELFLIB_MAJOR)" + ELF_DEP_LIBS= + CC_SHARED="\$(CC) \$(CFLAGS) -shared -fPIC" + ELF_FC_FCFLAGS="-fPIC" + else + DYNAMIC_LINK_FLAGS="" + ELF_CC="\$(CC)" + ELF_CFLAGS="\$(CFLAGS) -Kpic" # default anyhow + ELF_LINK="\$(CC) \$(LDFLAGS) -shared -o #" + ELF_LINK_CMD="\$(ELF_LINK)\$(ELFLIB_MAJOR)" + ELF_DEP_LIBS= + CC_SHARED="\$(CC) \$(CFLAGS) -shared -Kpic" + ELF_FC_FCFLAGS="-Kpic" + fi + ;; + *darwin* ) + DYNAMIC_LINK_FLAGS="" + if test "X$DYNAMIC_LINK_LIB" != "X" + then + dnl # assume dlcompat from Fink + dnl CFLAGS="$CFLAGS -Ddlsym=dlsym_prepend_underscore" + dnl # hint for pgplot from Fink + EXTRA_LIB="$EXTRA_LIB #-framework Foundation -framework AppKit -lpng" + fi + ELF_CC="\$(CC)" + ELF_CFLAGS="\$(CFLAGS) -fno-common" + ELF_LINK="\$(CC) \$(LDFLAGS) -dynamiclib" + ELF_LINK_CMD="\$(ELF_LINK) -install_name \$(install_lib_dir)/\$(ELFLIB_MAJOR) -compatibility_version \$(ELF_MAJOR_VERSION) -current_version \$(ELF_MAJOR_VERSION).\$(ELF_MINOR_VERSION)" + ELF_DEP_LIBS="\$(DL_LIB)" + CC_SHARED="\$(CC) -bundle -flat_namespace -undefined suppress \$(CFLAGS) -fno-common" + ELFLIB="lib\$(THIS_LIB).dylib" + ELFLIB_MAJOR="lib\$(THIS_LIB).\$(ELF_MAJOR_VERSION).dylib" + ELFLIB_MAJOR_MINOR="lib\$(THIS_LIB).\$(ELF_MAJOR_VERSION).\$(ELF_MINOR_VERSION).dylib" + ELF_FC_FCFLAGS="" + ;; + *freebsd* ) + ELFLIB_MAJOR_MINOR="\$(ELFLIB).\$(ELF_MAJOR_VERSION)" + ELF_CC="\$(CC)" + ELF_CFLAGS="\$(CFLAGS) -fPIC" + if test "X$PORTOBJFORMAT" = "Xelf" ; then + ELF_LINK="\$(CC) \$(LDFLAGS) -shared -Wl,-soname,\$(ELFLIB_MAJOR)" + else + ELF_LINK="ld -Bshareable -x" + fi + ELF_LINK_CMD="\$(ELF_LINK)" + ELF_DEP_LIBS="\$(DL_LIB) -lm" + CC_SHARED="\$(CC) \$(CFLAGS) -shared -fPIC" + ELF_FC_FCFLAGS="-fPIC" + ;; + + *cygwin* ) + DYNAMIC_LINK_FLAGS="" + ELF_CC="\$(CC)" + SLANG_DLL_CFLAGS="-DSLANG_DLL=1" + ELF_CFLAGS="\$(CFLAGS)" + ELF_LINK="\$(CC) \$(LDFLAGS) -shared -Wl,-soname#" + ELF_LINK_CMD="\$(ELF_LINK),\$(ELFLIB_MAJOR)" + ELF_DEP_LIBS="\$(DL_LIB) -lm -lc" + CC_SHARED="\$(CC) \$(CFLAGS) -shared" + ELF_FC_FCFLAGS="" + ISIS_LIB_FOR_MODULES="-L\$(config_dir)/src/\$(ARCH)objs -lisis" + SLANG_LIB_FOR_MODULES="\$(SLANG_LIB)" + CFITSIO_LIB_FOR_MODULES="\$(CFITSIO_LIB)" + INSTALL_MODULE="\$(INSTALL)" + ;; + + * ) + echo "Note: ELF compiler for host_os=$host_os may be wrong" + ELF_CC="\$(CC)" + ELF_CFLAGS="\$(CFLAGS) -fPIC" + ELF_LINK="\$(CC) \$(LDFLAGS) -shared" + ELF_LINK_CMD="\$(ELF_LINK)" + ELF_DEP_LIBS="\$(DL_LIB) -lm -lc" + CC_SHARED="\$(CC) \$(CFLAGS) -shared -fPIC" + ELF_FC_FCFLAGS="-fPIC" +esac + +AC_SUBST(ELF_CC) +AC_SUBST(ELF_CFLAGS) +AC_SUBST(ELF_LINK) +AC_SUBST(ELF_LINK_CMD) +AC_SUBST(ELF_DEP_LIBS) +AC_SUBST(ELF_FC_FCFLAGS) +AC_SUBST(DYNAMIC_LINK_FLAGS) +AC_SUBST(CC_SHARED) +AC_SUBST(ISIS_LIB_FOR_MODULES) +AC_SUBST(SLANG_LIB_FOR_MODULES) +AC_SUBST(CFITSIO_LIB_FOR_MODULES) +AC_SUBST(INSTALL_MODULE) +AC_SUBST(SLANG_DLL_CFLAGS) +]) + +dnl#}}} + +AC_DEFUN(JH_SET_GNU_FCLIBS, dnl#{{{ +[ +FCLIBS="" +if test "$GCC" = yes +then + jh_gcc_major_version=`$CC -dumpversion | sed -e 's/egcs-//' | cut -d'.' -f1` + if test $jh_gcc_major_version -lt 3 + then + FCLIBS="-lg2c" + fi +fi +]) + +dnl#}}} + +AC_DEFUN(JD_FC_COMPILER, dnl#{{{ +[ +case "$host_os" in + *linux* ) + FC="g77" + JH_SET_GNU_FCLIBS + ;; + *solaris*) + FC=f77 + FCLIBS="-lF77 -lM77 -lsunmath" + ;; + *sunos*) + FC=f77 + FCLIBS="-lM77 -lF77 -lansi -lc" + ;; + *) + echo "" + echo "WARNING: Assuming f77 as your FORTRAN compiler" + echo "" + FC=f77 + FCLIBS="" + if test "`$FC -v 2>&1 | grep GNU | wc -l`" -gt 0 + then + JH_SET_GNU_FCLIBS + fi + ;; +esac +AC_SUBST(FC) +AC_SUBST(FCLIBS) +]) + +dnl#}}} + +AC_DEFUN(JH_CHECK_CFITSIO_LIBNAME, dnl#{{{ +[ +dnl This nonsense is necessary because we cannot rely on +dnl the name of the cfitsio library. Common choices are: +dnl +dnl libcfitsio.so +dnl libcxccfitsio.so +dnl libcfitsio${version_string}.so +dnl +dnl And you can forget about about binary compatibility... +dnl + jh_cfitsio_library_dir=$1 + case "$host_os" in + *darwin* ) + ext="dylib" + ;; + *cygwin* ) + ext="dll" + ;; + * ) + ext="so" + ;; + esac + if test -f "${jh_cfitsio_library_dir}/libcfitsio.$ext" ; then + cfitsio_libname=cfitsio + elif test -f "${jh_cfitsio_library_dir}/libcxccfitsio.$ext" ; then + cfitsio_libname=cxccfitsio + else + cfitsio_libfile_exists=0 + cfitsio_libname=`/bin/ls ${jh_cfitsio_library_dir}/libcfitsio*.$ext` + if test x"$cfitsio_libname" != "x" ; then + cfitsio_libname=`basename $cfitsio_libname | sed s/lib// | sed s/\.$ext//` + if test -f "${jh_cfitsio_library_dir}/lib${cfitsio_libname}.$ext" ; then + cfitsio_libfile_exists=1 + fi + fi + if test "$cfitsio_libfile_exists" == 0 ; then + echo '*** WARNING: Cannot find cfitsio library in' "$jh_cfitsio_library_dir" + fi + fi + CFITSIO_LIB="-L${jh_cfitsio_library_dir} -l${cfitsio_libname}#" + AC_SUBST(CFITSIO_LIB) +]) +dnl#}}} + +AC_DEFUN(JH_CHECK_PGPLOT_PNG, dnl#{{{ +dnl +dnl Try to determine whether libpgplot needs libpng +dnl + jh_pgplot_libfile=$1 + OTHER_PGPLOT_LIBS="" + if test -f "$jh_pgplot_libfile" ; then + jh_png_symbols=`nm $jh_png_symbols | grep -i png` + if test x"$jh_png_symbols" != x ; then + OTHER_PGPLOT_LIBS="-lpng" + fi + fi + AC_SUBST(OTHER_PGPLOT_LIBS) +) +dnl#}}} + +AC_DEFUN(JH_CHECK_PGPLOT_LIBNAME, dnl#{{{ +[ +dnl This nonsense is necessary because we cannot rely on +dnl the name of the pgplot library. Common choices are: +dnl +dnl libpgplot.so +dnl libpgplot${version_string}.so +dnl +dnl (and the same for libcpgplot) +dnl + jh_pgplot_library_dir=$1 + case "$host_os" in + *darwin* ) + ext_list="dylib so a" + ;; + *cygwin* ) + ext_list="dll a" + ;; + * ) + ext_list="so a" + ;; + esac + pgplot_libnames=no + for ext in ${ext_list} + do + lib_pgplot_file="${jh_pgplot_library_dir}/libpgplot.$ext" + if test -f "$lib_pgplot_file" ; then + pgplot_libnames="-lcpgplot -lpgplot" + break + else + lib_pgplot_file=`/bin/ls ${jh_pgplot_library_dir}/libpgplot*.$ext | grep -v perl` + if test x"$lib_pgplot_file" != "x" ; then + lib_pgplot_name=`basename $lib_pgplot_file | sed s/lib// | sed s/\.$ext//` + if test -f "${jh_pgplot_library_dir}/lib${lib_pgplot_name}.$ext" ; then + pgplot_libnames="-lc${lib_pgplot_name} -l${lib_pgplot_name}" + break + fi + fi + fi + done + JH_CHECK_PGPLOT_PNG($lib_pgplot_file) + if test "X${pgplot_libnames}" = Xno + then + echo '*** WARNING: Cannot find pgplot libraries in' "$jh_pgplot_library_dir" + fi + PGPLOT_LIB="-L${jh_pgplot_library_dir} ${pgplot_libnames}" + AC_SUBST(PGPLOT_LIB) +]) +dnl#}}} + +AC_DEFUN(JH_WITH_XSPEC_STATIC, dnl#{{{ +[ +AC_ARG_WITH(xspec-static, + [ --with-xspec-static[=DIR] Statically link XSPEC models from DIR=$HEADAS], + [jh_use_xspec_static=$withval], [jh_use_xspec_static=no]) +if test "x$jh_use_xspec_static" = "xno" +then + LINK_XSPEC_STATIC="no" +else + LINK_XSPEC_STATIC="yes" + AC_DEFINE(WITH_XSPEC_STATIC_LINKED) + + HEADAS_DIR=$jh_use_xspec_static + AC_SUBST(HEADAS_DIR) + HEADAS=$jh_use_xspec_static + + HEADAS_LIBDIR="${HEADAS}/lib" + AC_SUBST(HEADAS_LIBDIR) + + WITH_HEADAS="-DWITH_HEADAS" + AC_SUBST(WITH_HEADAS) + + XSPEC_MODULE_LIBS="-L\$(config_dir)/modules/xspec/src/\$(ARCH)objs -lxspec-module \$(XS_LIBS)" + AC_SUBST(XSPEC_MODULE_LIBS) + + CFITSIO_INC="-I$HEADAS/include" + AC_SUBST(CFITSIO_INC) + JH_CHECK_CFITSIO_LIBNAME("$HEADAS/lib") + + PGPLOT_INC="-I$HEADAS/include" + AC_SUBST(PGPLOT_INC) + JH_CHECK_PGPLOT_LIBNAME("$HEADAS/lib") + PGPLOT_LIBDIR="$jh_pgplot_library_dir" + AC_SUBST(PGPLOT_LIBDIR) + + JD_SET_RPATH($HEADAS_LIBDIR) +fi +AC_SUBST(LINK_XSPEC_STATIC) +]) + +dnl#}}} + +AC_DEFUN(JH_WITH_HEADAS, dnl#{{{ +[ +AC_ARG_WITH(headas, + [ --with-headas[=DIR] HEADAS install directory], + [jh_use_headas=$withval], [jh_use_headas=no]) +if test "x$jh_use_headas" != "xno" +then + HEADAS_DIR=$jh_use_headas + HEADAS_LIBDIR="${HEADAS_DIR}/lib" + WITH_HEADAS="-DWITH_HEADAS" + MODULE_LIST="$MODULE_LIST xspec" + AC_SUBST(HEADAS_DIR) + AC_SUBST(HEADAS_LIBDIR) + AC_SUBST(WITH_HEADAS) + AC_SUBST(MODULE_LIST) + + CFITSIO_INC="-I${HEADAS_DIR}/include" + AC_SUBST(CFITSIO_INC) + JH_CHECK_CFITSIO_LIBNAME($HEADAS_DIR/lib) + + PGPLOT_INC="-I${HEADAS_DIR}/include" + AC_SUBST(PGPLOT_INC) + JH_CHECK_PGPLOT_LIBNAME($HEADAS_DIR/lib) + PGPLOT_LIBDIR="$jh_pgplot_library_dir" + AC_SUBST(PGPLOT_LIBDIR) + + JD_SET_RPATH($HEADAS_LIBDIR) +fi +]) + +dnl#}}} + +AC_DEFUN(JH_CIAO_PATHS, dnl#{{{ +[ +if test "X$1" != "X" +then + SLANG_LIBDIR="$1/ots/lib" + SLANG_LIB="-L$1/ots/lib" + SLANG_INC="-I$1/ots/include" + AC_SUBST(SLANG_LIBDIR) + AC_SUBST(SLANG_LIB) + AC_SUBST(SLANG_INC) + dnl + CFITSIO_INC="-I$1/ots/include" + JH_CHECK_CFITSIO_LIBNAME("$1/ots/lib") + AC_SUBST(CFITSIO_INC) + dnl + HEADAS_DIR="$1/ots/spectral" + HEADAS_LIBDIR="$1/ots/lib" + WITH_HEADAS="-DWITH_HEADAS" + MODULE_LIST="$MODULE_LIST xspec" + AC_SUBST(HEADAS_DIR) + AC_SUBST(HEADAS_LIBDIR) + AC_SUBST(WITH_HEADAS) + AC_SUBST(MODULE_LIST) + dnl + ATOMDB_DIR="$1/ATOMDB" + AC_SUBST(ATOMDB_DIR) +fi +]) +dnl#}}} + +AC_DEFUN(JH_WITH_CIAO, dnl#{{{ +[ +dnl This must precede the JD_WITH_LIBRARY() macros +dnl for slang, cfitsio and pgplot +dnl +AC_ARG_WITH(ciao, + [ --with-ciao[[=DIR]] Use pgplot/cfitsio/slang from Ciao], + [ jh_use_ciao=$withval ], [jh_use_ciao=no]) +if test "x$jh_use_ciao" = "xno" +then + ASCDS_INSTALL=no +else + if test "x$jh_use_ciao" = "xyes" + then + jh_use_ciao='$(ASCDS_INSTALL)' + fi + JH_CIAO_PATHS($jh_use_ciao) + JD_SET_RPATH($jh_use_ciao/ots/lib) + ASCDS_INSTALL=$jh_use_ciao +fi +AC_SUBST(ASCDS_INSTALL) +]) + +dnl#}}} + +AC_DEFUN(JH_HANDLE_PACKAGE_OPTIONS, dnl#{{{ +[ + case "$host_os" in + *linux* ) + # For 64-bit Linux, force the address of the mem_ symbol to be in low + # memory (0x80 chosen so that the symbol is aligned on a 128 byte boundary) + # + if test "x$ac_cv_sizeof_long" = "x8"; then + LD_FLAGS_FOR_XSPEC="-Wl,--defsym=mem_=0x80" + fi + ;; + * ) + ;; + esac + AC_SUBST(LD_FLAGS_FOR_XSPEC) + + JH_WITH_HEADAS + JH_WITH_XSPEC_STATIC + + AC_ARG_ENABLE(xspec_tables, + [ --disable-xspec_tables Compile without XSPEC table models], + [ ], + [AC_DEFINE(HAVE_XSPEC_TABLE_MODELS)]) + + AC_ARG_WITH(xspec-version, + [ --with-xspec-version[=nn] XSPEC version 11 or 12?], + [jh_with_xspec_version=$withval], [jh_with_xspec_version=no]) + if test x"$jh_with_xspec_version" = "x11" || test x"$jh_with_xspec_version" = "x12" ; then + with_xspec_version=$jh_with_xspec_version + elif test x"$jh_with_xspec_version" = "xno" ; then + with_xspec_version="NONE" + else + echo "### Unsupported xspec version $jh_with_xspec_version" + exit 1 + fi + AC_SUBST(with_xspec_version) + + JH_WITH_CIAO +]) + +dnl#}}} + +AC_DEFUN(JH_FORCE_UNDEFINED_SYMBOLS, dnl#{{{ +[ +# If we're using g77 and the GNU loader, force loading +# of libg2c symbols so they're available in case a user +# dynamically links to an XSPEC local model +FORCE_UNDEFINED_SYMBOLS="" +dnl Note that the G77 macro is probably no longer available.. +if test "$G77" = yes +then + AC_CHECK_PROG(have_loader,ld,"yes") + if test "$have_loader" = yes + then + loader_info=`ld -V | cut -d' ' -f1` + if test "$loader_info" = GNU + then + FORCE_UNDEFINED_SYMBOLS="-Wl,--undefined=s_rnge" + fi + fi +fi +AC_SUBST(FORCE_UNDEFINED_SYMBOLS) +]) + +dnl#}}} + +AC_DEFUN(JH_SYS_EXTRA_LIBS, dnl#{{{ +[ +SYS_EXTRA_LIBS="" +case "$host_os" in + *darwin* ) + if test "$GCC" = yes + then + jh_gcc_major_version=`$CC -dumpversion | sed -e 's/egcs-//' | cut -d'.' -f1` + if test $jh_gcc_major_version -lt 4 + then + SYS_EXTRA_LIBS="-lcc_dynamic" + fi + fi + ;; + * ) + ;; +esac +AC_SUBST(SYS_EXTRA_LIBS) +]) + +dnl#}}} + +AC_DEFUN(JH_FC_DEFS, dnl#{{{ +[ +case "$host_os" in + *linux*|*darwin*|*cygwin* ) + FC_DEFS="-Dg77Fortran" + ;; + + *) + FC_DEFS="" + ;; +esac +AC_SUBST(FC_DEFS) +]) + +dnl#}}} + +AC_DEFUN(JH_INIT_MODULE_LIST, dnl#{{{ +[ +MODULE_LIST="cfitsio pgplot maplib" +AC_SUBST(MODULE_LIST) +]) + +dnl#}}} + +AC_DEFUN(JD_LARGE_FILE_SUPPORT, dnl#{{{ +[ + AC_SYS_LARGEFILE + AC_FUNC_FSEEKO + AC_TYPE_OFF_T + AC_CHECK_SIZEOF(off_t) +]) +#}}} + +AC_DEFUN(JH_TERMCAP_LIB, dnl#{{{ +[ + termcap_lib="" + for lib in termcap ncurses curses ; do + AC_CHECK_LIB(${lib},tgetent,[termcap_lib="-l${lib}"; break]) + done + AC_SUBST(termcap_lib) +]) +#}}} + +AC_DEFUN(JH_WITH_READLINE, dnl#{{{ +[ +dnl # Establish readline support: GNU or S-Lang? + AC_ARG_WITH(readline, +[ --with-readline[[=arg]] arg=DIR means use GNU readline + (from DIR/lib and DIR/include) + arg=slang means use S-Lang readline only], + [ with_readline_arg=$withval ], [with_readline_arg=""]) + AC_MSG_CHECKING(type of readline support) + READLINE_DIR="" + READLINE_INC="" + GNU_READLINE=0 + READLINE_LIB="# -lreadline" + case "x$with_readline_arg" in + xslang|xno ) + AC_MSG_RESULT(slang); + ;; + * ) + termcap_lib="" + for lib in termcap ncurses curses ; do + AC_CHECK_LIB(${lib},tgetent,[termcap_lib="-l${lib}"; break]) + done + case "x$with_readline_arg" in + x|xyes|xgnu|xGNU ) + AC_CHECK_LIB(readline,main, + [GNU_READLINE=1],[GNU_READLINE=0],[$termcap_lib]) + if test "$GNU_READLINE" == 1 ; then + READLINE_LIB="-lreadline ${termcap_lib}" + else + READLINE_LIB="# -lreadline ${termcap_lib}" + fi + ;; + * ) + for ext in a so dylib ; do + if test -r "${with_readline_arg}/lib/libreadline.${ext}" ; then + GNU_READLINE=1 + JD_SET_RPATH($with_readline_arg/lib) + READLINE_DIR="-L${with_readline_arg}/lib" + READLINE_INC="-I${with_readline_arg}/include" + READLINE_LIB="${READLINE_DIR} -lreadline ${termcap_lib}" + break + fi + done + ;; + esac + if test "$GNU_READLINE" == 1 ; then + AC_MSG_RESULT([Looks like you have GNU readline. Can we use it?]) + tmp_libs=$LIBS + LIBS="$LIBS ${READLINE_LIB}" + tmp_cflags=$CFLAGS + CFLAGS="$CFLAGS ${READLINE_INC}" + AC_LINK_IFELSE( + AC_LANG_PROGRAM([[#include + #include + #include + ]], + [[char *prompt=NULL, *line=NULL; + char **matches=NULL; + const char *text=NULL; + line = readline (prompt); + add_history (line); + rl_delete_text (0, rl_end); + rl_point = rl_end = 0; + rl_forced_update_display(); + rl_refresh_line (0,0); + matches = rl_completion_matches (text,NULL);]]), + AC_MSG_RESULT([test program linked successfully -- readline looks ok.]), + [GNU_READLINE=0]) + CFLAGS=$tmp_cflags + LIBS=$tmp_libs + fi + if test "$GNU_READLINE" == 1 ; then + AC_DEFINE(HAVE_GNU_READLINE) + AC_MSG_RESULT(gnu); + else + AC_MSG_RESULT([Failed configuring GNU readline. Will use slang readline instead.]); + fi + ;; + esac + AC_SUBST(READLINE_LIB) + AC_SUBST(READLINE_DIR) + AC_SUBST(READLINE_INC) +]) +#}}} + +AC_DEFUN(JH_WITH_SUBDIR, dnl#{{{ +[ +AC_ARG_WITH(subdir, + [ --with-subdir=DIR Install in $prefix/isis/$DIR ], + [ jh_subdir=$withval ], [jh_subdir=no]) +if test "x$jh_subdir" != "xno" +then + subdir="$jh_subdir" +else + jh_isis_version=`grep " ISIS_VERSION_PREFIX " $CONFIG_DIR/src/isis.h | awk '{print [$]3}'` + subdir="$jh_isis_version" +fi +if test "x$prefix" = "xNONE" ; then + prefix_input="$ac_default_prefix" + prefix="$ac_default_prefix/isis/$subdir" +else + prefix_input="$prefix" + prefix="$prefix/isis/$subdir" +fi +AC_ARG_WITH(dep, + [ --with-dep=DIR slang/cfitsio/pgplot in DIR/lib, DIR/include, DIR/pgplot ], + [ jh_depdir=$withval ], [jh_depdir="$prefix_input"]) +AC_SUBST(subdir) +AC_SUBST(prefix_input) +]) + +dnl#}}} + diff --git a/autoconf/config.guess b/autoconf/config.guess new file mode 100755 index 0000000..396482d --- /dev/null +++ b/autoconf/config.guess @@ -0,0 +1,1500 @@ +#! /bin/sh +# Attempt to guess a canonical system name. +# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, +# 2000, 2001, 2002, 2003, 2004, 2005, 2006 Free Software Foundation, +# Inc. + +timestamp='2006-07-02' + +# This file is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA +# 02110-1301, USA. +# +# As a special exception to the GNU General Public License, if you +# distribute this file as part of a program that contains a +# configuration script generated by Autoconf, you may include it under +# the same distribution terms that you use for the rest of that program. + + +# Originally written by Per Bothner . +# Please send patches to . Submit a context +# diff and a properly formatted ChangeLog entry. +# +# This script attempts to guess a canonical system name similar to +# config.sub. If it succeeds, it prints the system name on stdout, and +# exits with 0. Otherwise, it exits with 1. +# +# The plan is that this can be called by configure scripts if you +# don't specify an explicit build system type. + +me=`echo "$0" | sed -e 's,.*/,,'` + +usage="\ +Usage: $0 [OPTION] + +Output the configuration name of the system \`$me' is run on. + +Operation modes: + -h, --help print this help, then exit + -t, --time-stamp print date of last modification, then exit + -v, --version print version number, then exit + +Report bugs and patches to ." + +version="\ +GNU config.guess ($timestamp) + +Originally written by Per Bothner. +Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005 +Free Software Foundation, Inc. + +This is free software; see the source for copying conditions. There is NO +warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." + +help=" +Try \`$me --help' for more information." + +# Parse command line +while test $# -gt 0 ; do + case $1 in + --time-stamp | --time* | -t ) + echo "$timestamp" ; exit ;; + --version | -v ) + echo "$version" ; exit ;; + --help | --h* | -h ) + echo "$usage"; exit ;; + -- ) # Stop option processing + shift; break ;; + - ) # Use stdin as input. + break ;; + -* ) + echo "$me: invalid option $1$help" >&2 + exit 1 ;; + * ) + break ;; + esac +done + +if test $# != 0; then + echo "$me: too many arguments$help" >&2 + exit 1 +fi + +trap 'exit 1' 1 2 15 + +# CC_FOR_BUILD -- compiler used by this script. Note that the use of a +# compiler to aid in system detection is discouraged as it requires +# temporary files to be created and, as you can see below, it is a +# headache to deal with in a portable fashion. + +# Historically, `CC_FOR_BUILD' used to be named `HOST_CC'. We still +# use `HOST_CC' if defined, but it is deprecated. + +# Portable tmp directory creation inspired by the Autoconf team. + +set_cc_for_build=' +trap "exitcode=\$?; (rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null) && exit \$exitcode" 0 ; +trap "rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null; exit 1" 1 2 13 15 ; +: ${TMPDIR=/tmp} ; + { tmp=`(umask 077 && mktemp -d "$TMPDIR/cgXXXXXX") 2>/dev/null` && test -n "$tmp" && test -d "$tmp" ; } || + { test -n "$RANDOM" && tmp=$TMPDIR/cg$$-$RANDOM && (umask 077 && mkdir $tmp) ; } || + { tmp=$TMPDIR/cg-$$ && (umask 077 && mkdir $tmp) && echo "Warning: creating insecure temp directory" >&2 ; } || + { echo "$me: cannot create a temporary directory in $TMPDIR" >&2 ; exit 1 ; } ; +dummy=$tmp/dummy ; +tmpfiles="$dummy.c $dummy.o $dummy.rel $dummy" ; +case $CC_FOR_BUILD,$HOST_CC,$CC in + ,,) echo "int x;" > $dummy.c ; + for c in cc gcc c89 c99 ; do + if ($c -c -o $dummy.o $dummy.c) >/dev/null 2>&1 ; then + CC_FOR_BUILD="$c"; break ; + fi ; + done ; + if test x"$CC_FOR_BUILD" = x ; then + CC_FOR_BUILD=no_compiler_found ; + fi + ;; + ,,*) CC_FOR_BUILD=$CC ;; + ,*,*) CC_FOR_BUILD=$HOST_CC ;; +esac ; set_cc_for_build= ;' + +# This is needed to find uname on a Pyramid OSx when run in the BSD universe. +# (ghazi@noc.rutgers.edu 1994-08-24) +if (test -f /.attbin/uname) >/dev/null 2>&1 ; then + PATH=$PATH:/.attbin ; export PATH +fi + +UNAME_MACHINE=`(uname -m) 2>/dev/null` || UNAME_MACHINE=unknown +UNAME_RELEASE=`(uname -r) 2>/dev/null` || UNAME_RELEASE=unknown +UNAME_SYSTEM=`(uname -s) 2>/dev/null` || UNAME_SYSTEM=unknown +UNAME_VERSION=`(uname -v) 2>/dev/null` || UNAME_VERSION=unknown + +# Note: order is significant - the case branches are not exclusive. + +case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in + *:NetBSD:*:*) + # NetBSD (nbsd) targets should (where applicable) match one or + # more of the tupples: *-*-netbsdelf*, *-*-netbsdaout*, + # *-*-netbsdecoff* and *-*-netbsd*. For targets that recently + # switched to ELF, *-*-netbsd* would select the old + # object file format. This provides both forward + # compatibility and a consistent mechanism for selecting the + # object file format. + # + # Note: NetBSD doesn't particularly care about the vendor + # portion of the name. We always set it to "unknown". + sysctl="sysctl -n hw.machine_arch" + UNAME_MACHINE_ARCH=`(/sbin/$sysctl 2>/dev/null || \ + /usr/sbin/$sysctl 2>/dev/null || echo unknown)` + case "${UNAME_MACHINE_ARCH}" in + armeb) machine=armeb-unknown ;; + arm*) machine=arm-unknown ;; + sh3el) machine=shl-unknown ;; + sh3eb) machine=sh-unknown ;; + *) machine=${UNAME_MACHINE_ARCH}-unknown ;; + esac + # The Operating System including object format, if it has switched + # to ELF recently, or will in the future. + case "${UNAME_MACHINE_ARCH}" in + arm*|i386|m68k|ns32k|sh3*|sparc|vax) + eval $set_cc_for_build + if echo __ELF__ | $CC_FOR_BUILD -E - 2>/dev/null \ + | grep __ELF__ >/dev/null + then + # Once all utilities can be ECOFF (netbsdecoff) or a.out (netbsdaout). + # Return netbsd for either. FIX? + os=netbsd + else + os=netbsdelf + fi + ;; + *) + os=netbsd + ;; + esac + # The OS release + # Debian GNU/NetBSD machines have a different userland, and + # thus, need a distinct triplet. However, they do not need + # kernel version information, so it can be replaced with a + # suitable tag, in the style of linux-gnu. + case "${UNAME_VERSION}" in + Debian*) + release='-gnu' + ;; + *) + release=`echo ${UNAME_RELEASE}|sed -e 's/[-_].*/\./'` + ;; + esac + # Since CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM: + # contains redundant information, the shorter form: + # CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM is used. + echo "${machine}-${os}${release}" + exit ;; + *:OpenBSD:*:*) + UNAME_MACHINE_ARCH=`arch | sed 's/OpenBSD.//'` + echo ${UNAME_MACHINE_ARCH}-unknown-openbsd${UNAME_RELEASE} + exit ;; + *:ekkoBSD:*:*) + echo ${UNAME_MACHINE}-unknown-ekkobsd${UNAME_RELEASE} + exit ;; + *:SolidBSD:*:*) + echo ${UNAME_MACHINE}-unknown-solidbsd${UNAME_RELEASE} + exit ;; + macppc:MirBSD:*:*) + echo powerpc-unknown-mirbsd${UNAME_RELEASE} + exit ;; + *:MirBSD:*:*) + echo ${UNAME_MACHINE}-unknown-mirbsd${UNAME_RELEASE} + exit ;; + alpha:OSF1:*:*) + case $UNAME_RELEASE in + *4.0) + UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $3}'` + ;; + *5.*) + UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $4}'` + ;; + esac + # According to Compaq, /usr/sbin/psrinfo has been available on + # OSF/1 and Tru64 systems produced since 1995. I hope that + # covers most systems running today. This code pipes the CPU + # types through head -n 1, so we only detect the type of CPU 0. + ALPHA_CPU_TYPE=`/usr/sbin/psrinfo -v | sed -n -e 's/^ The alpha \(.*\) processor.*$/\1/p' | head -n 1` + case "$ALPHA_CPU_TYPE" in + "EV4 (21064)") + UNAME_MACHINE="alpha" ;; + "EV4.5 (21064)") + UNAME_MACHINE="alpha" ;; + "LCA4 (21066/21068)") + UNAME_MACHINE="alpha" ;; + "EV5 (21164)") + UNAME_MACHINE="alphaev5" ;; + "EV5.6 (21164A)") + UNAME_MACHINE="alphaev56" ;; + "EV5.6 (21164PC)") + UNAME_MACHINE="alphapca56" ;; + "EV5.7 (21164PC)") + UNAME_MACHINE="alphapca57" ;; + "EV6 (21264)") + UNAME_MACHINE="alphaev6" ;; + "EV6.7 (21264A)") + UNAME_MACHINE="alphaev67" ;; + "EV6.8CB (21264C)") + UNAME_MACHINE="alphaev68" ;; + "EV6.8AL (21264B)") + UNAME_MACHINE="alphaev68" ;; + "EV6.8CX (21264D)") + UNAME_MACHINE="alphaev68" ;; + "EV6.9A (21264/EV69A)") + UNAME_MACHINE="alphaev69" ;; + "EV7 (21364)") + UNAME_MACHINE="alphaev7" ;; + "EV7.9 (21364A)") + UNAME_MACHINE="alphaev79" ;; + esac + # A Pn.n version is a patched version. + # A Vn.n version is a released version. + # A Tn.n version is a released field test version. + # A Xn.n version is an unreleased experimental baselevel. + # 1.2 uses "1.2" for uname -r. + echo ${UNAME_MACHINE}-dec-osf`echo ${UNAME_RELEASE} | sed -e 's/^[PVTX]//' | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'` + exit ;; + Alpha\ *:Windows_NT*:*) + # How do we know it's Interix rather than the generic POSIX subsystem? + # Should we change UNAME_MACHINE based on the output of uname instead + # of the specific Alpha model? + echo alpha-pc-interix + exit ;; + 21064:Windows_NT:50:3) + echo alpha-dec-winnt3.5 + exit ;; + Amiga*:UNIX_System_V:4.0:*) + echo m68k-unknown-sysv4 + exit ;; + *:[Aa]miga[Oo][Ss]:*:*) + echo ${UNAME_MACHINE}-unknown-amigaos + exit ;; + *:[Mm]orph[Oo][Ss]:*:*) + echo ${UNAME_MACHINE}-unknown-morphos + exit ;; + *:OS/390:*:*) + echo i370-ibm-openedition + exit ;; + *:z/VM:*:*) + echo s390-ibm-zvmoe + exit ;; + *:OS400:*:*) + echo powerpc-ibm-os400 + exit ;; + arm:RISC*:1.[012]*:*|arm:riscix:1.[012]*:*) + echo arm-acorn-riscix${UNAME_RELEASE} + exit ;; + arm:riscos:*:*|arm:RISCOS:*:*) + echo arm-unknown-riscos + exit ;; + SR2?01:HI-UX/MPP:*:* | SR8000:HI-UX/MPP:*:*) + echo hppa1.1-hitachi-hiuxmpp + exit ;; + Pyramid*:OSx*:*:* | MIS*:OSx*:*:* | MIS*:SMP_DC-OSx*:*:*) + # akee@wpdis03.wpafb.af.mil (Earle F. Ake) contributed MIS and NILE. + if test "`(/bin/universe) 2>/dev/null`" = att ; then + echo pyramid-pyramid-sysv3 + else + echo pyramid-pyramid-bsd + fi + exit ;; + NILE*:*:*:dcosx) + echo pyramid-pyramid-svr4 + exit ;; + DRS?6000:unix:4.0:6*) + echo sparc-icl-nx6 + exit ;; + DRS?6000:UNIX_SV:4.2*:7* | DRS?6000:isis:4.2*:7*) + case `/usr/bin/uname -p` in + sparc) echo sparc-icl-nx7; exit ;; + esac ;; + sun4H:SunOS:5.*:*) + echo sparc-hal-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit ;; + sun4*:SunOS:5.*:* | tadpole*:SunOS:5.*:*) + echo sparc-sun-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit ;; + i86pc:SunOS:5.*:*) + echo i386-pc-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit ;; + sun4*:SunOS:6*:*) + # According to config.sub, this is the proper way to canonicalize + # SunOS6. Hard to guess exactly what SunOS6 will be like, but + # it's likely to be more like Solaris than SunOS4. + echo sparc-sun-solaris3`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit ;; + sun4*:SunOS:*:*) + case "`/usr/bin/arch -k`" in + Series*|S4*) + UNAME_RELEASE=`uname -v` + ;; + esac + # Japanese Language versions have a version number like `4.1.3-JL'. + echo sparc-sun-sunos`echo ${UNAME_RELEASE}|sed -e 's/-/_/'` + exit ;; + sun3*:SunOS:*:*) + echo m68k-sun-sunos${UNAME_RELEASE} + exit ;; + sun*:*:4.2BSD:*) + UNAME_RELEASE=`(sed 1q /etc/motd | awk '{print substr($5,1,3)}') 2>/dev/null` + test "x${UNAME_RELEASE}" = "x" && UNAME_RELEASE=3 + case "`/bin/arch`" in + sun3) + echo m68k-sun-sunos${UNAME_RELEASE} + ;; + sun4) + echo sparc-sun-sunos${UNAME_RELEASE} + ;; + esac + exit ;; + aushp:SunOS:*:*) + echo sparc-auspex-sunos${UNAME_RELEASE} + exit ;; + # The situation for MiNT is a little confusing. The machine name + # can be virtually everything (everything which is not + # "atarist" or "atariste" at least should have a processor + # > m68000). The system name ranges from "MiNT" over "FreeMiNT" + # to the lowercase version "mint" (or "freemint"). Finally + # the system name "TOS" denotes a system which is actually not + # MiNT. But MiNT is downward compatible to TOS, so this should + # be no problem. + atarist[e]:*MiNT:*:* | atarist[e]:*mint:*:* | atarist[e]:*TOS:*:*) + echo m68k-atari-mint${UNAME_RELEASE} + exit ;; + atari*:*MiNT:*:* | atari*:*mint:*:* | atarist[e]:*TOS:*:*) + echo m68k-atari-mint${UNAME_RELEASE} + exit ;; + *falcon*:*MiNT:*:* | *falcon*:*mint:*:* | *falcon*:*TOS:*:*) + echo m68k-atari-mint${UNAME_RELEASE} + exit ;; + milan*:*MiNT:*:* | milan*:*mint:*:* | *milan*:*TOS:*:*) + echo m68k-milan-mint${UNAME_RELEASE} + exit ;; + hades*:*MiNT:*:* | hades*:*mint:*:* | *hades*:*TOS:*:*) + echo m68k-hades-mint${UNAME_RELEASE} + exit ;; + *:*MiNT:*:* | *:*mint:*:* | *:*TOS:*:*) + echo m68k-unknown-mint${UNAME_RELEASE} + exit ;; + m68k:machten:*:*) + echo m68k-apple-machten${UNAME_RELEASE} + exit ;; + powerpc:machten:*:*) + echo powerpc-apple-machten${UNAME_RELEASE} + exit ;; + RISC*:Mach:*:*) + echo mips-dec-mach_bsd4.3 + exit ;; + RISC*:ULTRIX:*:*) + echo mips-dec-ultrix${UNAME_RELEASE} + exit ;; + VAX*:ULTRIX*:*:*) + echo vax-dec-ultrix${UNAME_RELEASE} + exit ;; + 2020:CLIX:*:* | 2430:CLIX:*:*) + echo clipper-intergraph-clix${UNAME_RELEASE} + exit ;; + mips:*:*:UMIPS | mips:*:*:RISCos) + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c +#ifdef __cplusplus +#include /* for printf() prototype */ + int main (int argc, char *argv[]) { +#else + int main (argc, argv) int argc; char *argv[]; { +#endif + #if defined (host_mips) && defined (MIPSEB) + #if defined (SYSTYPE_SYSV) + printf ("mips-mips-riscos%ssysv\n", argv[1]); exit (0); + #endif + #if defined (SYSTYPE_SVR4) + printf ("mips-mips-riscos%ssvr4\n", argv[1]); exit (0); + #endif + #if defined (SYSTYPE_BSD43) || defined(SYSTYPE_BSD) + printf ("mips-mips-riscos%sbsd\n", argv[1]); exit (0); + #endif + #endif + exit (-1); + } +EOF + $CC_FOR_BUILD -o $dummy $dummy.c && + dummyarg=`echo "${UNAME_RELEASE}" | sed -n 's/\([0-9]*\).*/\1/p'` && + SYSTEM_NAME=`$dummy $dummyarg` && + { echo "$SYSTEM_NAME"; exit; } + echo mips-mips-riscos${UNAME_RELEASE} + exit ;; + Motorola:PowerMAX_OS:*:*) + echo powerpc-motorola-powermax + exit ;; + Motorola:*:4.3:PL8-*) + echo powerpc-harris-powermax + exit ;; + Night_Hawk:*:*:PowerMAX_OS | Synergy:PowerMAX_OS:*:*) + echo powerpc-harris-powermax + exit ;; + Night_Hawk:Power_UNIX:*:*) + echo powerpc-harris-powerunix + exit ;; + m88k:CX/UX:7*:*) + echo m88k-harris-cxux7 + exit ;; + m88k:*:4*:R4*) + echo m88k-motorola-sysv4 + exit ;; + m88k:*:3*:R3*) + echo m88k-motorola-sysv3 + exit ;; + AViiON:dgux:*:*) + # DG/UX returns AViiON for all architectures + UNAME_PROCESSOR=`/usr/bin/uname -p` + if [ $UNAME_PROCESSOR = mc88100 ] || [ $UNAME_PROCESSOR = mc88110 ] + then + if [ ${TARGET_BINARY_INTERFACE}x = m88kdguxelfx ] || \ + [ ${TARGET_BINARY_INTERFACE}x = x ] + then + echo m88k-dg-dgux${UNAME_RELEASE} + else + echo m88k-dg-dguxbcs${UNAME_RELEASE} + fi + else + echo i586-dg-dgux${UNAME_RELEASE} + fi + exit ;; + M88*:DolphinOS:*:*) # DolphinOS (SVR3) + echo m88k-dolphin-sysv3 + exit ;; + M88*:*:R3*:*) + # Delta 88k system running SVR3 + echo m88k-motorola-sysv3 + exit ;; + XD88*:*:*:*) # Tektronix XD88 system running UTekV (SVR3) + echo m88k-tektronix-sysv3 + exit ;; + Tek43[0-9][0-9]:UTek:*:*) # Tektronix 4300 system running UTek (BSD) + echo m68k-tektronix-bsd + exit ;; + *:IRIX*:*:*) + echo mips-sgi-irix`echo ${UNAME_RELEASE}|sed -e 's/-/_/g'` + exit ;; + ????????:AIX?:[12].1:2) # AIX 2.2.1 or AIX 2.1.1 is RT/PC AIX. + echo romp-ibm-aix # uname -m gives an 8 hex-code CPU id + exit ;; # Note that: echo "'`uname -s`'" gives 'AIX ' + i*86:AIX:*:*) + echo i386-ibm-aix + exit ;; + ia64:AIX:*:*) + if [ -x /usr/bin/oslevel ] ; then + IBM_REV=`/usr/bin/oslevel` + else + IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE} + fi + echo ${UNAME_MACHINE}-ibm-aix${IBM_REV} + exit ;; + *:AIX:2:3) + if grep bos325 /usr/include/stdio.h >/dev/null 2>&1; then + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c + #include + + main() + { + if (!__power_pc()) + exit(1); + puts("powerpc-ibm-aix3.2.5"); + exit(0); + } +EOF + if $CC_FOR_BUILD -o $dummy $dummy.c && SYSTEM_NAME=`$dummy` + then + echo "$SYSTEM_NAME" + else + echo rs6000-ibm-aix3.2.5 + fi + elif grep bos324 /usr/include/stdio.h >/dev/null 2>&1; then + echo rs6000-ibm-aix3.2.4 + else + echo rs6000-ibm-aix3.2 + fi + exit ;; + *:AIX:*:[45]) + IBM_CPU_ID=`/usr/sbin/lsdev -C -c processor -S available | sed 1q | awk '{ print $1 }'` + if /usr/sbin/lsattr -El ${IBM_CPU_ID} | grep ' POWER' >/dev/null 2>&1; then + IBM_ARCH=rs6000 + else + IBM_ARCH=powerpc + fi + if [ -x /usr/bin/oslevel ] ; then + IBM_REV=`/usr/bin/oslevel` + else + IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE} + fi + echo ${IBM_ARCH}-ibm-aix${IBM_REV} + exit ;; + *:AIX:*:*) + echo rs6000-ibm-aix + exit ;; + ibmrt:4.4BSD:*|romp-ibm:BSD:*) + echo romp-ibm-bsd4.4 + exit ;; + ibmrt:*BSD:*|romp-ibm:BSD:*) # covers RT/PC BSD and + echo romp-ibm-bsd${UNAME_RELEASE} # 4.3 with uname added to + exit ;; # report: romp-ibm BSD 4.3 + *:BOSX:*:*) + echo rs6000-bull-bosx + exit ;; + DPX/2?00:B.O.S.:*:*) + echo m68k-bull-sysv3 + exit ;; + 9000/[34]??:4.3bsd:1.*:*) + echo m68k-hp-bsd + exit ;; + hp300:4.4BSD:*:* | 9000/[34]??:4.3bsd:2.*:*) + echo m68k-hp-bsd4.4 + exit ;; + 9000/[34678]??:HP-UX:*:*) + HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'` + case "${UNAME_MACHINE}" in + 9000/31? ) HP_ARCH=m68000 ;; + 9000/[34]?? ) HP_ARCH=m68k ;; + 9000/[678][0-9][0-9]) + if [ -x /usr/bin/getconf ]; then + sc_cpu_version=`/usr/bin/getconf SC_CPU_VERSION 2>/dev/null` + sc_kernel_bits=`/usr/bin/getconf SC_KERNEL_BITS 2>/dev/null` + case "${sc_cpu_version}" in + 523) HP_ARCH="hppa1.0" ;; # CPU_PA_RISC1_0 + 528) HP_ARCH="hppa1.1" ;; # CPU_PA_RISC1_1 + 532) # CPU_PA_RISC2_0 + case "${sc_kernel_bits}" in + 32) HP_ARCH="hppa2.0n" ;; + 64) HP_ARCH="hppa2.0w" ;; + '') HP_ARCH="hppa2.0" ;; # HP-UX 10.20 + esac ;; + esac + fi + if [ "${HP_ARCH}" = "" ]; then + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c + + #define _HPUX_SOURCE + #include + #include + + int main () + { + #if defined(_SC_KERNEL_BITS) + long bits = sysconf(_SC_KERNEL_BITS); + #endif + long cpu = sysconf (_SC_CPU_VERSION); + + switch (cpu) + { + case CPU_PA_RISC1_0: puts ("hppa1.0"); break; + case CPU_PA_RISC1_1: puts ("hppa1.1"); break; + case CPU_PA_RISC2_0: + #if defined(_SC_KERNEL_BITS) + switch (bits) + { + case 64: puts ("hppa2.0w"); break; + case 32: puts ("hppa2.0n"); break; + default: puts ("hppa2.0"); break; + } break; + #else /* !defined(_SC_KERNEL_BITS) */ + puts ("hppa2.0"); break; + #endif + default: puts ("hppa1.0"); break; + } + exit (0); + } +EOF + (CCOPTS= $CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null) && HP_ARCH=`$dummy` + test -z "$HP_ARCH" && HP_ARCH=hppa + fi ;; + esac + if [ ${HP_ARCH} = "hppa2.0w" ] + then + eval $set_cc_for_build + + # hppa2.0w-hp-hpux* has a 64-bit kernel and a compiler generating + # 32-bit code. hppa64-hp-hpux* has the same kernel and a compiler + # generating 64-bit code. GNU and HP use different nomenclature: + # + # $ CC_FOR_BUILD=cc ./config.guess + # => hppa2.0w-hp-hpux11.23 + # $ CC_FOR_BUILD="cc +DA2.0w" ./config.guess + # => hppa64-hp-hpux11.23 + + if echo __LP64__ | (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) | + grep __LP64__ >/dev/null + then + HP_ARCH="hppa2.0w" + else + HP_ARCH="hppa64" + fi + fi + echo ${HP_ARCH}-hp-hpux${HPUX_REV} + exit ;; + ia64:HP-UX:*:*) + HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'` + echo ia64-hp-hpux${HPUX_REV} + exit ;; + 3050*:HI-UX:*:*) + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c + #include + int + main () + { + long cpu = sysconf (_SC_CPU_VERSION); + /* The order matters, because CPU_IS_HP_MC68K erroneously returns + true for CPU_PA_RISC1_0. CPU_IS_PA_RISC returns correct + results, however. */ + if (CPU_IS_PA_RISC (cpu)) + { + switch (cpu) + { + case CPU_PA_RISC1_0: puts ("hppa1.0-hitachi-hiuxwe2"); break; + case CPU_PA_RISC1_1: puts ("hppa1.1-hitachi-hiuxwe2"); break; + case CPU_PA_RISC2_0: puts ("hppa2.0-hitachi-hiuxwe2"); break; + default: puts ("hppa-hitachi-hiuxwe2"); break; + } + } + else if (CPU_IS_HP_MC68K (cpu)) + puts ("m68k-hitachi-hiuxwe2"); + else puts ("unknown-hitachi-hiuxwe2"); + exit (0); + } +EOF + $CC_FOR_BUILD -o $dummy $dummy.c && SYSTEM_NAME=`$dummy` && + { echo "$SYSTEM_NAME"; exit; } + echo unknown-hitachi-hiuxwe2 + exit ;; + 9000/7??:4.3bsd:*:* | 9000/8?[79]:4.3bsd:*:* ) + echo hppa1.1-hp-bsd + exit ;; + 9000/8??:4.3bsd:*:*) + echo hppa1.0-hp-bsd + exit ;; + *9??*:MPE/iX:*:* | *3000*:MPE/iX:*:*) + echo hppa1.0-hp-mpeix + exit ;; + hp7??:OSF1:*:* | hp8?[79]:OSF1:*:* ) + echo hppa1.1-hp-osf + exit ;; + hp8??:OSF1:*:*) + echo hppa1.0-hp-osf + exit ;; + i*86:OSF1:*:*) + if [ -x /usr/sbin/sysversion ] ; then + echo ${UNAME_MACHINE}-unknown-osf1mk + else + echo ${UNAME_MACHINE}-unknown-osf1 + fi + exit ;; + parisc*:Lites*:*:*) + echo hppa1.1-hp-lites + exit ;; + C1*:ConvexOS:*:* | convex:ConvexOS:C1*:*) + echo c1-convex-bsd + exit ;; + C2*:ConvexOS:*:* | convex:ConvexOS:C2*:*) + if getsysinfo -f scalar_acc + then echo c32-convex-bsd + else echo c2-convex-bsd + fi + exit ;; + C34*:ConvexOS:*:* | convex:ConvexOS:C34*:*) + echo c34-convex-bsd + exit ;; + C38*:ConvexOS:*:* | convex:ConvexOS:C38*:*) + echo c38-convex-bsd + exit ;; + C4*:ConvexOS:*:* | convex:ConvexOS:C4*:*) + echo c4-convex-bsd + exit ;; + CRAY*Y-MP:*:*:*) + echo ymp-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + exit ;; + CRAY*[A-Z]90:*:*:*) + echo ${UNAME_MACHINE}-cray-unicos${UNAME_RELEASE} \ + | sed -e 's/CRAY.*\([A-Z]90\)/\1/' \ + -e y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/ \ + -e 's/\.[^.]*$/.X/' + exit ;; + CRAY*TS:*:*:*) + echo t90-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + exit ;; + CRAY*T3E:*:*:*) + echo alphaev5-cray-unicosmk${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + exit ;; + CRAY*SV1:*:*:*) + echo sv1-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + exit ;; + *:UNICOS/mp:*:*) + echo craynv-cray-unicosmp${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + exit ;; + F30[01]:UNIX_System_V:*:* | F700:UNIX_System_V:*:*) + FUJITSU_PROC=`uname -m | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'` + FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'` + FUJITSU_REL=`echo ${UNAME_RELEASE} | sed -e 's/ /_/'` + echo "${FUJITSU_PROC}-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}" + exit ;; + 5000:UNIX_System_V:4.*:*) + FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'` + FUJITSU_REL=`echo ${UNAME_RELEASE} | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/ /_/'` + echo "sparc-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}" + exit ;; + i*86:BSD/386:*:* | i*86:BSD/OS:*:* | *:Ascend\ Embedded/OS:*:*) + echo ${UNAME_MACHINE}-pc-bsdi${UNAME_RELEASE} + exit ;; + sparc*:BSD/OS:*:*) + echo sparc-unknown-bsdi${UNAME_RELEASE} + exit ;; + *:BSD/OS:*:*) + echo ${UNAME_MACHINE}-unknown-bsdi${UNAME_RELEASE} + exit ;; + *:FreeBSD:*:*) + case ${UNAME_MACHINE} in + pc98) + echo i386-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;; + amd64) + echo x86_64-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;; + *) + echo ${UNAME_MACHINE}-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;; + esac + exit ;; + i*:CYGWIN*:*) + echo ${UNAME_MACHINE}-pc-cygwin + exit ;; + i*:MINGW*:*) + echo ${UNAME_MACHINE}-pc-mingw32 + exit ;; + i*:windows32*:*) + # uname -m includes "-pc" on this system. + echo ${UNAME_MACHINE}-mingw32 + exit ;; + i*:PW*:*) + echo ${UNAME_MACHINE}-pc-pw32 + exit ;; + x86:Interix*:[3456]*) + echo i586-pc-interix${UNAME_RELEASE} + exit ;; + EM64T:Interix*:[3456]*) + echo x86_64-unknown-interix${UNAME_RELEASE} + exit ;; + [345]86:Windows_95:* | [345]86:Windows_98:* | [345]86:Windows_NT:*) + echo i${UNAME_MACHINE}-pc-mks + exit ;; + i*:Windows_NT*:* | Pentium*:Windows_NT*:*) + # How do we know it's Interix rather than the generic POSIX subsystem? + # It also conflicts with pre-2.0 versions of AT&T UWIN. Should we + # UNAME_MACHINE based on the output of uname instead of i386? + echo i586-pc-interix + exit ;; + i*:UWIN*:*) + echo ${UNAME_MACHINE}-pc-uwin + exit ;; + amd64:CYGWIN*:*:* | x86_64:CYGWIN*:*:*) + echo x86_64-unknown-cygwin + exit ;; + p*:CYGWIN*:*) + echo powerpcle-unknown-cygwin + exit ;; + prep*:SunOS:5.*:*) + echo powerpcle-unknown-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit ;; + *:GNU:*:*) + # the GNU system + echo `echo ${UNAME_MACHINE}|sed -e 's,[-/].*$,,'`-unknown-gnu`echo ${UNAME_RELEASE}|sed -e 's,/.*$,,'` + exit ;; + *:GNU/*:*:*) + # other systems with GNU libc and userland + echo ${UNAME_MACHINE}-unknown-`echo ${UNAME_SYSTEM} | sed 's,^[^/]*/,,' | tr '[A-Z]' '[a-z]'``echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`-gnu + exit ;; + i*86:Minix:*:*) + echo ${UNAME_MACHINE}-pc-minix + exit ;; + arm*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; + avr32*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; + cris:Linux:*:*) + echo cris-axis-linux-gnu + exit ;; + crisv32:Linux:*:*) + echo crisv32-axis-linux-gnu + exit ;; + frv:Linux:*:*) + echo frv-unknown-linux-gnu + exit ;; + ia64:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; + m32r*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; + m68*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; + mips:Linux:*:*) + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c + #undef CPU + #undef mips + #undef mipsel + #if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL) || defined(MIPSEL) + CPU=mipsel + #else + #if defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB) || defined(MIPSEB) + CPU=mips + #else + CPU= + #endif + #endif +EOF + eval "`$CC_FOR_BUILD -E $dummy.c 2>/dev/null | sed -n ' + /^CPU/{ + s: ::g + p + }'`" + test x"${CPU}" != x && { echo "${CPU}-unknown-linux-gnu"; exit; } + ;; + mips64:Linux:*:*) + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c + #undef CPU + #undef mips64 + #undef mips64el + #if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL) || defined(MIPSEL) + CPU=mips64el + #else + #if defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB) || defined(MIPSEB) + CPU=mips64 + #else + CPU= + #endif + #endif +EOF + eval "`$CC_FOR_BUILD -E $dummy.c 2>/dev/null | sed -n ' + /^CPU/{ + s: ::g + p + }'`" + test x"${CPU}" != x && { echo "${CPU}-unknown-linux-gnu"; exit; } + ;; + or32:Linux:*:*) + echo or32-unknown-linux-gnu + exit ;; + ppc:Linux:*:*) + echo powerpc-unknown-linux-gnu + exit ;; + ppc64:Linux:*:*) + echo powerpc64-unknown-linux-gnu + exit ;; + alpha:Linux:*:*) + case `sed -n '/^cpu model/s/^.*: \(.*\)/\1/p' < /proc/cpuinfo` in + EV5) UNAME_MACHINE=alphaev5 ;; + EV56) UNAME_MACHINE=alphaev56 ;; + PCA56) UNAME_MACHINE=alphapca56 ;; + PCA57) UNAME_MACHINE=alphapca56 ;; + EV6) UNAME_MACHINE=alphaev6 ;; + EV67) UNAME_MACHINE=alphaev67 ;; + EV68*) UNAME_MACHINE=alphaev68 ;; + esac + objdump --private-headers /bin/sh | grep ld.so.1 >/dev/null + if test "$?" = 0 ; then LIBC="libc1" ; else LIBC="" ; fi + echo ${UNAME_MACHINE}-unknown-linux-gnu${LIBC} + exit ;; + parisc:Linux:*:* | hppa:Linux:*:*) + # Look for CPU level + case `grep '^cpu[^a-z]*:' /proc/cpuinfo 2>/dev/null | cut -d' ' -f2` in + PA7*) echo hppa1.1-unknown-linux-gnu ;; + PA8*) echo hppa2.0-unknown-linux-gnu ;; + *) echo hppa-unknown-linux-gnu ;; + esac + exit ;; + parisc64:Linux:*:* | hppa64:Linux:*:*) + echo hppa64-unknown-linux-gnu + exit ;; + s390:Linux:*:* | s390x:Linux:*:*) + echo ${UNAME_MACHINE}-ibm-linux + exit ;; + sh64*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; + sh*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; + sparc:Linux:*:* | sparc64:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; + vax:Linux:*:*) + echo ${UNAME_MACHINE}-dec-linux-gnu + exit ;; + x86_64:Linux:*:*) + echo x86_64-unknown-linux-gnu + exit ;; + i*86:Linux:*:*) + # The BFD linker knows what the default object file format is, so + # first see if it will tell us. cd to the root directory to prevent + # problems with other programs or directories called `ld' in the path. + # Set LC_ALL=C to ensure ld outputs messages in English. + ld_supported_targets=`cd /; LC_ALL=C ld --help 2>&1 \ + | sed -ne '/supported targets:/!d + s/[ ][ ]*/ /g + s/.*supported targets: *// + s/ .*// + p'` + case "$ld_supported_targets" in + elf32-i386) + TENTATIVE="${UNAME_MACHINE}-pc-linux-gnu" + ;; + a.out-i386-linux) + echo "${UNAME_MACHINE}-pc-linux-gnuaout" + exit ;; + coff-i386) + echo "${UNAME_MACHINE}-pc-linux-gnucoff" + exit ;; + "") + # Either a pre-BFD a.out linker (linux-gnuoldld) or + # one that does not give us useful --help. + echo "${UNAME_MACHINE}-pc-linux-gnuoldld" + exit ;; + esac + # Determine whether the default compiler is a.out or elf + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c + #include + #ifdef __ELF__ + # ifdef __GLIBC__ + # if __GLIBC__ >= 2 + LIBC=gnu + # else + LIBC=gnulibc1 + # endif + # else + LIBC=gnulibc1 + # endif + #else + #if defined(__INTEL_COMPILER) || defined(__PGI) || defined(__SUNPRO_C) || defined(__SUNPRO_CC) + LIBC=gnu + #else + LIBC=gnuaout + #endif + #endif + #ifdef __dietlibc__ + LIBC=dietlibc + #endif +EOF + eval "`$CC_FOR_BUILD -E $dummy.c 2>/dev/null | sed -n ' + /^LIBC/{ + s: ::g + p + }'`" + test x"${LIBC}" != x && { + echo "${UNAME_MACHINE}-pc-linux-${LIBC}" + exit + } + test x"${TENTATIVE}" != x && { echo "${TENTATIVE}"; exit; } + ;; + i*86:DYNIX/ptx:4*:*) + # ptx 4.0 does uname -s correctly, with DYNIX/ptx in there. + # earlier versions are messed up and put the nodename in both + # sysname and nodename. + echo i386-sequent-sysv4 + exit ;; + i*86:UNIX_SV:4.2MP:2.*) + # Unixware is an offshoot of SVR4, but it has its own version + # number series starting with 2... + # I am not positive that other SVR4 systems won't match this, + # I just have to hope. -- rms. + # Use sysv4.2uw... so that sysv4* matches it. + echo ${UNAME_MACHINE}-pc-sysv4.2uw${UNAME_VERSION} + exit ;; + i*86:OS/2:*:*) + # If we were able to find `uname', then EMX Unix compatibility + # is probably installed. + echo ${UNAME_MACHINE}-pc-os2-emx + exit ;; + i*86:XTS-300:*:STOP) + echo ${UNAME_MACHINE}-unknown-stop + exit ;; + i*86:atheos:*:*) + echo ${UNAME_MACHINE}-unknown-atheos + exit ;; + i*86:syllable:*:*) + echo ${UNAME_MACHINE}-pc-syllable + exit ;; + i*86:LynxOS:2.*:* | i*86:LynxOS:3.[01]*:* | i*86:LynxOS:4.0*:*) + echo i386-unknown-lynxos${UNAME_RELEASE} + exit ;; + i*86:*DOS:*:*) + echo ${UNAME_MACHINE}-pc-msdosdjgpp + exit ;; + i*86:*:4.*:* | i*86:SYSTEM_V:4.*:*) + UNAME_REL=`echo ${UNAME_RELEASE} | sed 's/\/MP$//'` + if grep Novell /usr/include/link.h >/dev/null 2>/dev/null; then + echo ${UNAME_MACHINE}-univel-sysv${UNAME_REL} + else + echo ${UNAME_MACHINE}-pc-sysv${UNAME_REL} + fi + exit ;; + i*86:*:5:[678]*) + # UnixWare 7.x, OpenUNIX and OpenServer 6. + case `/bin/uname -X | grep "^Machine"` in + *486*) UNAME_MACHINE=i486 ;; + *Pentium) UNAME_MACHINE=i586 ;; + *Pent*|*Celeron) UNAME_MACHINE=i686 ;; + esac + echo ${UNAME_MACHINE}-unknown-sysv${UNAME_RELEASE}${UNAME_SYSTEM}${UNAME_VERSION} + exit ;; + i*86:*:3.2:*) + if test -f /usr/options/cb.name; then + UNAME_REL=`sed -n 's/.*Version //p' /dev/null >/dev/null ; then + UNAME_REL=`(/bin/uname -X|grep Release|sed -e 's/.*= //')` + (/bin/uname -X|grep i80486 >/dev/null) && UNAME_MACHINE=i486 + (/bin/uname -X|grep '^Machine.*Pentium' >/dev/null) \ + && UNAME_MACHINE=i586 + (/bin/uname -X|grep '^Machine.*Pent *II' >/dev/null) \ + && UNAME_MACHINE=i686 + (/bin/uname -X|grep '^Machine.*Pentium Pro' >/dev/null) \ + && UNAME_MACHINE=i686 + echo ${UNAME_MACHINE}-pc-sco$UNAME_REL + else + echo ${UNAME_MACHINE}-pc-sysv32 + fi + exit ;; + pc:*:*:*) + # Left here for compatibility: + # uname -m prints for DJGPP always 'pc', but it prints nothing about + # the processor, so we play safe by assuming i386. + echo i386-pc-msdosdjgpp + exit ;; + Intel:Mach:3*:*) + echo i386-pc-mach3 + exit ;; + paragon:*:*:*) + echo i860-intel-osf1 + exit ;; + i860:*:4.*:*) # i860-SVR4 + if grep Stardent /usr/include/sys/uadmin.h >/dev/null 2>&1 ; then + echo i860-stardent-sysv${UNAME_RELEASE} # Stardent Vistra i860-SVR4 + else # Add other i860-SVR4 vendors below as they are discovered. + echo i860-unknown-sysv${UNAME_RELEASE} # Unknown i860-SVR4 + fi + exit ;; + mini*:CTIX:SYS*5:*) + # "miniframe" + echo m68010-convergent-sysv + exit ;; + mc68k:UNIX:SYSTEM5:3.51m) + echo m68k-convergent-sysv + exit ;; + M680?0:D-NIX:5.3:*) + echo m68k-diab-dnix + exit ;; + M68*:*:R3V[5678]*:*) + test -r /sysV68 && { echo 'm68k-motorola-sysv'; exit; } ;; + 3[345]??:*:4.0:3.0 | 3[34]??A:*:4.0:3.0 | 3[34]??,*:*:4.0:3.0 | 3[34]??/*:*:4.0:3.0 | 4400:*:4.0:3.0 | 4850:*:4.0:3.0 | SKA40:*:4.0:3.0 | SDS2:*:4.0:3.0 | SHG2:*:4.0:3.0 | S7501*:*:4.0:3.0) + OS_REL='' + test -r /etc/.relid \ + && OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid` + /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ + && { echo i486-ncr-sysv4.3${OS_REL}; exit; } + /bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \ + && { echo i586-ncr-sysv4.3${OS_REL}; exit; } ;; + 3[34]??:*:4.0:* | 3[34]??,*:*:4.0:*) + /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ + && { echo i486-ncr-sysv4; exit; } ;; + m68*:LynxOS:2.*:* | m68*:LynxOS:3.0*:*) + echo m68k-unknown-lynxos${UNAME_RELEASE} + exit ;; + mc68030:UNIX_System_V:4.*:*) + echo m68k-atari-sysv4 + exit ;; + TSUNAMI:LynxOS:2.*:*) + echo sparc-unknown-lynxos${UNAME_RELEASE} + exit ;; + rs6000:LynxOS:2.*:*) + echo rs6000-unknown-lynxos${UNAME_RELEASE} + exit ;; + PowerPC:LynxOS:2.*:* | PowerPC:LynxOS:3.[01]*:* | PowerPC:LynxOS:4.0*:*) + echo powerpc-unknown-lynxos${UNAME_RELEASE} + exit ;; + SM[BE]S:UNIX_SV:*:*) + echo mips-dde-sysv${UNAME_RELEASE} + exit ;; + RM*:ReliantUNIX-*:*:*) + echo mips-sni-sysv4 + exit ;; + RM*:SINIX-*:*:*) + echo mips-sni-sysv4 + exit ;; + *:SINIX-*:*:*) + if uname -p 2>/dev/null >/dev/null ; then + UNAME_MACHINE=`(uname -p) 2>/dev/null` + echo ${UNAME_MACHINE}-sni-sysv4 + else + echo ns32k-sni-sysv + fi + exit ;; + PENTIUM:*:4.0*:*) # Unisys `ClearPath HMP IX 4000' SVR4/MP effort + # says + echo i586-unisys-sysv4 + exit ;; + *:UNIX_System_V:4*:FTX*) + # From Gerald Hewes . + # How about differentiating between stratus architectures? -djm + echo hppa1.1-stratus-sysv4 + exit ;; + *:*:*:FTX*) + # From seanf@swdc.stratus.com. + echo i860-stratus-sysv4 + exit ;; + i*86:VOS:*:*) + # From Paul.Green@stratus.com. + echo ${UNAME_MACHINE}-stratus-vos + exit ;; + *:VOS:*:*) + # From Paul.Green@stratus.com. + echo hppa1.1-stratus-vos + exit ;; + mc68*:A/UX:*:*) + echo m68k-apple-aux${UNAME_RELEASE} + exit ;; + news*:NEWS-OS:6*:*) + echo mips-sony-newsos6 + exit ;; + R[34]000:*System_V*:*:* | R4000:UNIX_SYSV:*:* | R*000:UNIX_SV:*:*) + if [ -d /usr/nec ]; then + echo mips-nec-sysv${UNAME_RELEASE} + else + echo mips-unknown-sysv${UNAME_RELEASE} + fi + exit ;; + BeBox:BeOS:*:*) # BeOS running on hardware made by Be, PPC only. + echo powerpc-be-beos + exit ;; + BeMac:BeOS:*:*) # BeOS running on Mac or Mac clone, PPC only. + echo powerpc-apple-beos + exit ;; + BePC:BeOS:*:*) # BeOS running on Intel PC compatible. + echo i586-pc-beos + exit ;; + SX-4:SUPER-UX:*:*) + echo sx4-nec-superux${UNAME_RELEASE} + exit ;; + SX-5:SUPER-UX:*:*) + echo sx5-nec-superux${UNAME_RELEASE} + exit ;; + SX-6:SUPER-UX:*:*) + echo sx6-nec-superux${UNAME_RELEASE} + exit ;; + Power*:Rhapsody:*:*) + echo powerpc-apple-rhapsody${UNAME_RELEASE} + exit ;; + *:Rhapsody:*:*) + echo ${UNAME_MACHINE}-apple-rhapsody${UNAME_RELEASE} + exit ;; + *:Darwin:*:*) + UNAME_PROCESSOR=`uname -p` || UNAME_PROCESSOR=unknown + case $UNAME_PROCESSOR in + unknown) UNAME_PROCESSOR=powerpc ;; + esac + echo ${UNAME_PROCESSOR}-apple-darwin${UNAME_RELEASE} + exit ;; + *:procnto*:*:* | *:QNX:[0123456789]*:*) + UNAME_PROCESSOR=`uname -p` + if test "$UNAME_PROCESSOR" = "x86"; then + UNAME_PROCESSOR=i386 + UNAME_MACHINE=pc + fi + echo ${UNAME_PROCESSOR}-${UNAME_MACHINE}-nto-qnx${UNAME_RELEASE} + exit ;; + *:QNX:*:4*) + echo i386-pc-qnx + exit ;; + NSE-?:NONSTOP_KERNEL:*:*) + echo nse-tandem-nsk${UNAME_RELEASE} + exit ;; + NSR-?:NONSTOP_KERNEL:*:*) + echo nsr-tandem-nsk${UNAME_RELEASE} + exit ;; + *:NonStop-UX:*:*) + echo mips-compaq-nonstopux + exit ;; + BS2000:POSIX*:*:*) + echo bs2000-siemens-sysv + exit ;; + DS/*:UNIX_System_V:*:*) + echo ${UNAME_MACHINE}-${UNAME_SYSTEM}-${UNAME_RELEASE} + exit ;; + *:Plan9:*:*) + # "uname -m" is not consistent, so use $cputype instead. 386 + # is converted to i386 for consistency with other x86 + # operating systems. + if test "$cputype" = "386"; then + UNAME_MACHINE=i386 + else + UNAME_MACHINE="$cputype" + fi + echo ${UNAME_MACHINE}-unknown-plan9 + exit ;; + *:TOPS-10:*:*) + echo pdp10-unknown-tops10 + exit ;; + *:TENEX:*:*) + echo pdp10-unknown-tenex + exit ;; + KS10:TOPS-20:*:* | KL10:TOPS-20:*:* | TYPE4:TOPS-20:*:*) + echo pdp10-dec-tops20 + exit ;; + XKL-1:TOPS-20:*:* | TYPE5:TOPS-20:*:*) + echo pdp10-xkl-tops20 + exit ;; + *:TOPS-20:*:*) + echo pdp10-unknown-tops20 + exit ;; + *:ITS:*:*) + echo pdp10-unknown-its + exit ;; + SEI:*:*:SEIUX) + echo mips-sei-seiux${UNAME_RELEASE} + exit ;; + *:DragonFly:*:*) + echo ${UNAME_MACHINE}-unknown-dragonfly`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` + exit ;; + *:*VMS:*:*) + UNAME_MACHINE=`(uname -p) 2>/dev/null` + case "${UNAME_MACHINE}" in + A*) echo alpha-dec-vms ; exit ;; + I*) echo ia64-dec-vms ; exit ;; + V*) echo vax-dec-vms ; exit ;; + esac ;; + *:XENIX:*:SysV) + echo i386-pc-xenix + exit ;; + i*86:skyos:*:*) + echo ${UNAME_MACHINE}-pc-skyos`echo ${UNAME_RELEASE}` | sed -e 's/ .*$//' + exit ;; + i*86:rdos:*:*) + echo ${UNAME_MACHINE}-pc-rdos + exit ;; +esac + +#echo '(No uname command or uname output not recognized.)' 1>&2 +#echo "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" 1>&2 + +eval $set_cc_for_build +cat >$dummy.c < +# include +#endif +main () +{ +#if defined (sony) +#if defined (MIPSEB) + /* BFD wants "bsd" instead of "newsos". Perhaps BFD should be changed, + I don't know.... */ + printf ("mips-sony-bsd\n"); exit (0); +#else +#include + printf ("m68k-sony-newsos%s\n", +#ifdef NEWSOS4 + "4" +#else + "" +#endif + ); exit (0); +#endif +#endif + +#if defined (__arm) && defined (__acorn) && defined (__unix) + printf ("arm-acorn-riscix\n"); exit (0); +#endif + +#if defined (hp300) && !defined (hpux) + printf ("m68k-hp-bsd\n"); exit (0); +#endif + +#if defined (NeXT) +#if !defined (__ARCHITECTURE__) +#define __ARCHITECTURE__ "m68k" +#endif + int version; + version=`(hostinfo | sed -n 's/.*NeXT Mach \([0-9]*\).*/\1/p') 2>/dev/null`; + if (version < 4) + printf ("%s-next-nextstep%d\n", __ARCHITECTURE__, version); + else + printf ("%s-next-openstep%d\n", __ARCHITECTURE__, version); + exit (0); +#endif + +#if defined (MULTIMAX) || defined (n16) +#if defined (UMAXV) + printf ("ns32k-encore-sysv\n"); exit (0); +#else +#if defined (CMU) + printf ("ns32k-encore-mach\n"); exit (0); +#else + printf ("ns32k-encore-bsd\n"); exit (0); +#endif +#endif +#endif + +#if defined (__386BSD__) + printf ("i386-pc-bsd\n"); exit (0); +#endif + +#if defined (sequent) +#if defined (i386) + printf ("i386-sequent-dynix\n"); exit (0); +#endif +#if defined (ns32000) + printf ("ns32k-sequent-dynix\n"); exit (0); +#endif +#endif + +#if defined (_SEQUENT_) + struct utsname un; + + uname(&un); + + if (strncmp(un.version, "V2", 2) == 0) { + printf ("i386-sequent-ptx2\n"); exit (0); + } + if (strncmp(un.version, "V1", 2) == 0) { /* XXX is V1 correct? */ + printf ("i386-sequent-ptx1\n"); exit (0); + } + printf ("i386-sequent-ptx\n"); exit (0); + +#endif + +#if defined (vax) +# if !defined (ultrix) +# include +# if defined (BSD) +# if BSD == 43 + printf ("vax-dec-bsd4.3\n"); exit (0); +# else +# if BSD == 199006 + printf ("vax-dec-bsd4.3reno\n"); exit (0); +# else + printf ("vax-dec-bsd\n"); exit (0); +# endif +# endif +# else + printf ("vax-dec-bsd\n"); exit (0); +# endif +# else + printf ("vax-dec-ultrix\n"); exit (0); +# endif +#endif + +#if defined (alliant) && defined (i860) + printf ("i860-alliant-bsd\n"); exit (0); +#endif + + exit (1); +} +EOF + +$CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null && SYSTEM_NAME=`$dummy` && + { echo "$SYSTEM_NAME"; exit; } + +# Apollos put the system type in the environment. + +test -d /usr/apollo && { echo ${ISP}-apollo-${SYSTYPE}; exit; } + +# Convex versions that predate uname can use getsysinfo(1) + +if [ -x /usr/convex/getsysinfo ] +then + case `getsysinfo -f cpu_type` in + c1*) + echo c1-convex-bsd + exit ;; + c2*) + if getsysinfo -f scalar_acc + then echo c32-convex-bsd + else echo c2-convex-bsd + fi + exit ;; + c34*) + echo c34-convex-bsd + exit ;; + c38*) + echo c38-convex-bsd + exit ;; + c4*) + echo c4-convex-bsd + exit ;; + esac +fi + +cat >&2 < in order to provide the needed +information to handle your system. + +config.guess timestamp = $timestamp + +uname -m = `(uname -m) 2>/dev/null || echo unknown` +uname -r = `(uname -r) 2>/dev/null || echo unknown` +uname -s = `(uname -s) 2>/dev/null || echo unknown` +uname -v = `(uname -v) 2>/dev/null || echo unknown` + +/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null` +/bin/uname -X = `(/bin/uname -X) 2>/dev/null` + +hostinfo = `(hostinfo) 2>/dev/null` +/bin/universe = `(/bin/universe) 2>/dev/null` +/usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null` +/bin/arch = `(/bin/arch) 2>/dev/null` +/usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null` +/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null` + +UNAME_MACHINE = ${UNAME_MACHINE} +UNAME_RELEASE = ${UNAME_RELEASE} +UNAME_SYSTEM = ${UNAME_SYSTEM} +UNAME_VERSION = ${UNAME_VERSION} +EOF + +exit 1 + +# Local variables: +# eval: (add-hook 'write-file-hooks 'time-stamp) +# time-stamp-start: "timestamp='" +# time-stamp-format: "%:y-%02m-%02d" +# time-stamp-end: "'" +# End: diff --git a/autoconf/config.sub b/autoconf/config.sub new file mode 100755 index 0000000..387c18d --- /dev/null +++ b/autoconf/config.sub @@ -0,0 +1,1608 @@ +#! /bin/sh +# Configuration validation subroutine script. +# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, +# 2000, 2001, 2002, 2003, 2004, 2005, 2006 Free Software Foundation, +# Inc. + +timestamp='2006-07-02' + +# This file is (in principle) common to ALL GNU software. +# The presence of a machine in this file suggests that SOME GNU software +# can handle that machine. It does not imply ALL GNU software can. +# +# This file is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA +# 02110-1301, USA. +# +# As a special exception to the GNU General Public License, if you +# distribute this file as part of a program that contains a +# configuration script generated by Autoconf, you may include it under +# the same distribution terms that you use for the rest of that program. + + +# Please send patches to . Submit a context +# diff and a properly formatted ChangeLog entry. +# +# Configuration subroutine to validate and canonicalize a configuration type. +# Supply the specified configuration type as an argument. +# If it is invalid, we print an error message on stderr and exit with code 1. +# Otherwise, we print the canonical config type on stdout and succeed. + +# This file is supposed to be the same for all GNU packages +# and recognize all the CPU types, system types and aliases +# that are meaningful with *any* GNU software. +# Each package is responsible for reporting which valid configurations +# it does not support. The user should be able to distinguish +# a failure to support a valid configuration from a meaningless +# configuration. + +# The goal of this file is to map all the various variations of a given +# machine specification into a single specification in the form: +# CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM +# or in some cases, the newer four-part form: +# CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM +# It is wrong to echo any other type of specification. + +me=`echo "$0" | sed -e 's,.*/,,'` + +usage="\ +Usage: $0 [OPTION] CPU-MFR-OPSYS + $0 [OPTION] ALIAS + +Canonicalize a configuration name. + +Operation modes: + -h, --help print this help, then exit + -t, --time-stamp print date of last modification, then exit + -v, --version print version number, then exit + +Report bugs and patches to ." + +version="\ +GNU config.sub ($timestamp) + +Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005 +Free Software Foundation, Inc. + +This is free software; see the source for copying conditions. There is NO +warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." + +help=" +Try \`$me --help' for more information." + +# Parse command line +while test $# -gt 0 ; do + case $1 in + --time-stamp | --time* | -t ) + echo "$timestamp" ; exit ;; + --version | -v ) + echo "$version" ; exit ;; + --help | --h* | -h ) + echo "$usage"; exit ;; + -- ) # Stop option processing + shift; break ;; + - ) # Use stdin as input. + break ;; + -* ) + echo "$me: invalid option $1$help" + exit 1 ;; + + *local*) + # First pass through any local machine types. + echo $1 + exit ;; + + * ) + break ;; + esac +done + +case $# in + 0) echo "$me: missing argument$help" >&2 + exit 1;; + 1) ;; + *) echo "$me: too many arguments$help" >&2 + exit 1;; +esac + +# Separate what the user gave into CPU-COMPANY and OS or KERNEL-OS (if any). +# Here we must recognize all the valid KERNEL-OS combinations. +maybe_os=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\2/'` +case $maybe_os in + nto-qnx* | linux-gnu* | linux-dietlibc | linux-newlib* | linux-uclibc* | \ + uclinux-uclibc* | uclinux-gnu* | kfreebsd*-gnu* | knetbsd*-gnu* | netbsd*-gnu* | \ + storm-chaos* | os2-emx* | rtmk-nova*) + os=-$maybe_os + basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'` + ;; + *) + basic_machine=`echo $1 | sed 's/-[^-]*$//'` + if [ $basic_machine != $1 ] + then os=`echo $1 | sed 's/.*-/-/'` + else os=; fi + ;; +esac + +### Let's recognize common machines as not being operating systems so +### that things like config.sub decstation-3100 work. We also +### recognize some manufacturers as not being operating systems, so we +### can provide default operating systems below. +case $os in + -sun*os*) + # Prevent following clause from handling this invalid input. + ;; + -dec* | -mips* | -sequent* | -encore* | -pc532* | -sgi* | -sony* | \ + -att* | -7300* | -3300* | -delta* | -motorola* | -sun[234]* | \ + -unicom* | -ibm* | -next | -hp | -isi* | -apollo | -altos* | \ + -convergent* | -ncr* | -news | -32* | -3600* | -3100* | -hitachi* |\ + -c[123]* | -convex* | -sun | -crds | -omron* | -dg | -ultra | -tti* | \ + -harris | -dolphin | -highlevel | -gould | -cbm | -ns | -masscomp | \ + -apple | -axis | -knuth | -cray) + os= + basic_machine=$1 + ;; + -sim | -cisco | -oki | -wec | -winbond) + os= + basic_machine=$1 + ;; + -scout) + ;; + -wrs) + os=-vxworks + basic_machine=$1 + ;; + -chorusos*) + os=-chorusos + basic_machine=$1 + ;; + -chorusrdb) + os=-chorusrdb + basic_machine=$1 + ;; + -hiux*) + os=-hiuxwe2 + ;; + -sco6) + os=-sco5v6 + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -sco5) + os=-sco3.2v5 + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -sco4) + os=-sco3.2v4 + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -sco3.2.[4-9]*) + os=`echo $os | sed -e 's/sco3.2./sco3.2v/'` + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -sco3.2v[4-9]*) + # Don't forget version if it is 3.2v4 or newer. + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -sco5v6*) + # Don't forget version if it is 3.2v4 or newer. + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -sco*) + os=-sco3.2v2 + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -udk*) + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -isc) + os=-isc2.2 + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -clix*) + basic_machine=clipper-intergraph + ;; + -isc*) + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -lynx*) + os=-lynxos + ;; + -ptx*) + basic_machine=`echo $1 | sed -e 's/86-.*/86-sequent/'` + ;; + -windowsnt*) + os=`echo $os | sed -e 's/windowsnt/winnt/'` + ;; + -psos*) + os=-psos + ;; + -mint | -mint[0-9]*) + basic_machine=m68k-atari + os=-mint + ;; +esac + +# Decode aliases for certain CPU-COMPANY combinations. +case $basic_machine in + # Recognize the basic CPU types without company name. + # Some are omitted here because they have special meanings below. + 1750a | 580 \ + | a29k \ + | alpha | alphaev[4-8] | alphaev56 | alphaev6[78] | alphapca5[67] \ + | alpha64 | alpha64ev[4-8] | alpha64ev56 | alpha64ev6[78] | alpha64pca5[67] \ + | am33_2.0 \ + | arc | arm | arm[bl]e | arme[lb] | armv[2345] | armv[345][lb] | avr | avr32 \ + | bfin \ + | c4x | clipper \ + | d10v | d30v | dlx | dsp16xx \ + | fr30 | frv \ + | h8300 | h8500 | hppa | hppa1.[01] | hppa2.0 | hppa2.0[nw] | hppa64 \ + | i370 | i860 | i960 | ia64 \ + | ip2k | iq2000 \ + | m32c | m32r | m32rle | m68000 | m68k | m88k \ + | maxq | mb | microblaze | mcore \ + | mips | mipsbe | mipseb | mipsel | mipsle \ + | mips16 \ + | mips64 | mips64el \ + | mips64vr | mips64vrel \ + | mips64orion | mips64orionel \ + | mips64vr4100 | mips64vr4100el \ + | mips64vr4300 | mips64vr4300el \ + | mips64vr5000 | mips64vr5000el \ + | mips64vr5900 | mips64vr5900el \ + | mipsisa32 | mipsisa32el \ + | mipsisa32r2 | mipsisa32r2el \ + | mipsisa64 | mipsisa64el \ + | mipsisa64r2 | mipsisa64r2el \ + | mipsisa64sb1 | mipsisa64sb1el \ + | mipsisa64sr71k | mipsisa64sr71kel \ + | mipstx39 | mipstx39el \ + | mn10200 | mn10300 \ + | mt \ + | msp430 \ + | nios | nios2 \ + | ns16k | ns32k \ + | or32 \ + | pdp10 | pdp11 | pj | pjl \ + | powerpc | powerpc64 | powerpc64le | powerpcle | ppcbe \ + | pyramid \ + | sh | sh[1234] | sh[24]a | sh[23]e | sh[34]eb | sheb | shbe | shle | sh[1234]le | sh3ele \ + | sh64 | sh64le \ + | sparc | sparc64 | sparc64b | sparc64v | sparc86x | sparclet | sparclite \ + | sparcv8 | sparcv9 | sparcv9b | sparcv9v \ + | spu | strongarm \ + | tahoe | thumb | tic4x | tic80 | tron \ + | v850 | v850e \ + | we32k \ + | x86 | xscale | xscalee[bl] | xstormy16 | xtensa \ + | z8k) + basic_machine=$basic_machine-unknown + ;; + m6811 | m68hc11 | m6812 | m68hc12) + # Motorola 68HC11/12. + basic_machine=$basic_machine-unknown + os=-none + ;; + m88110 | m680[12346]0 | m683?2 | m68360 | m5200 | v70 | w65 | z8k) + ;; + ms1) + basic_machine=mt-unknown + ;; + + # We use `pc' rather than `unknown' + # because (1) that's what they normally are, and + # (2) the word "unknown" tends to confuse beginning users. + i*86 | x86_64) + basic_machine=$basic_machine-pc + ;; + # Object if more than one company name word. + *-*-*) + echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2 + exit 1 + ;; + # Recognize the basic CPU types with company name. + 580-* \ + | a29k-* \ + | alpha-* | alphaev[4-8]-* | alphaev56-* | alphaev6[78]-* \ + | alpha64-* | alpha64ev[4-8]-* | alpha64ev56-* | alpha64ev6[78]-* \ + | alphapca5[67]-* | alpha64pca5[67]-* | arc-* \ + | arm-* | armbe-* | armle-* | armeb-* | armv*-* \ + | avr-* | avr32-* \ + | bfin-* | bs2000-* \ + | c[123]* | c30-* | [cjt]90-* | c4x-* | c54x-* | c55x-* | c6x-* \ + | clipper-* | craynv-* | cydra-* \ + | d10v-* | d30v-* | dlx-* \ + | elxsi-* \ + | f30[01]-* | f700-* | fr30-* | frv-* | fx80-* \ + | h8300-* | h8500-* \ + | hppa-* | hppa1.[01]-* | hppa2.0-* | hppa2.0[nw]-* | hppa64-* \ + | i*86-* | i860-* | i960-* | ia64-* \ + | ip2k-* | iq2000-* \ + | m32c-* | m32r-* | m32rle-* \ + | m68000-* | m680[012346]0-* | m68360-* | m683?2-* | m68k-* \ + | m88110-* | m88k-* | maxq-* | mcore-* \ + | mips-* | mipsbe-* | mipseb-* | mipsel-* | mipsle-* \ + | mips16-* \ + | mips64-* | mips64el-* \ + | mips64vr-* | mips64vrel-* \ + | mips64orion-* | mips64orionel-* \ + | mips64vr4100-* | mips64vr4100el-* \ + | mips64vr4300-* | mips64vr4300el-* \ + | mips64vr5000-* | mips64vr5000el-* \ + | mips64vr5900-* | mips64vr5900el-* \ + | mipsisa32-* | mipsisa32el-* \ + | mipsisa32r2-* | mipsisa32r2el-* \ + | mipsisa64-* | mipsisa64el-* \ + | mipsisa64r2-* | mipsisa64r2el-* \ + | mipsisa64sb1-* | mipsisa64sb1el-* \ + | mipsisa64sr71k-* | mipsisa64sr71kel-* \ + | mipstx39-* | mipstx39el-* \ + | mmix-* \ + | mt-* \ + | msp430-* \ + | nios-* | nios2-* \ + | none-* | np1-* | ns16k-* | ns32k-* \ + | orion-* \ + | pdp10-* | pdp11-* | pj-* | pjl-* | pn-* | power-* \ + | powerpc-* | powerpc64-* | powerpc64le-* | powerpcle-* | ppcbe-* \ + | pyramid-* \ + | romp-* | rs6000-* \ + | sh-* | sh[1234]-* | sh[24]a-* | sh[23]e-* | sh[34]eb-* | sheb-* | shbe-* \ + | shle-* | sh[1234]le-* | sh3ele-* | sh64-* | sh64le-* \ + | sparc-* | sparc64-* | sparc64b-* | sparc64v-* | sparc86x-* | sparclet-* \ + | sparclite-* \ + | sparcv8-* | sparcv9-* | sparcv9b-* | sparcv9v-* | strongarm-* | sv1-* | sx?-* \ + | tahoe-* | thumb-* \ + | tic30-* | tic4x-* | tic54x-* | tic55x-* | tic6x-* | tic80-* \ + | tron-* \ + | v850-* | v850e-* | vax-* \ + | we32k-* \ + | x86-* | x86_64-* | xps100-* | xscale-* | xscalee[bl]-* \ + | xstormy16-* | xtensa-* \ + | ymp-* \ + | z8k-*) + ;; + # Recognize the various machine names and aliases which stand + # for a CPU type and a company and sometimes even an OS. + 386bsd) + basic_machine=i386-unknown + os=-bsd + ;; + 3b1 | 7300 | 7300-att | att-7300 | pc7300 | safari | unixpc) + basic_machine=m68000-att + ;; + 3b*) + basic_machine=we32k-att + ;; + a29khif) + basic_machine=a29k-amd + os=-udi + ;; + abacus) + basic_machine=abacus-unknown + ;; + adobe68k) + basic_machine=m68010-adobe + os=-scout + ;; + alliant | fx80) + basic_machine=fx80-alliant + ;; + altos | altos3068) + basic_machine=m68k-altos + ;; + am29k) + basic_machine=a29k-none + os=-bsd + ;; + amd64) + basic_machine=x86_64-pc + ;; + amd64-*) + basic_machine=x86_64-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + amdahl) + basic_machine=580-amdahl + os=-sysv + ;; + amiga | amiga-*) + basic_machine=m68k-unknown + ;; + amigaos | amigados) + basic_machine=m68k-unknown + os=-amigaos + ;; + amigaunix | amix) + basic_machine=m68k-unknown + os=-sysv4 + ;; + apollo68) + basic_machine=m68k-apollo + os=-sysv + ;; + apollo68bsd) + basic_machine=m68k-apollo + os=-bsd + ;; + aux) + basic_machine=m68k-apple + os=-aux + ;; + balance) + basic_machine=ns32k-sequent + os=-dynix + ;; + c90) + basic_machine=c90-cray + os=-unicos + ;; + convex-c1) + basic_machine=c1-convex + os=-bsd + ;; + convex-c2) + basic_machine=c2-convex + os=-bsd + ;; + convex-c32) + basic_machine=c32-convex + os=-bsd + ;; + convex-c34) + basic_machine=c34-convex + os=-bsd + ;; + convex-c38) + basic_machine=c38-convex + os=-bsd + ;; + cray | j90) + basic_machine=j90-cray + os=-unicos + ;; + craynv) + basic_machine=craynv-cray + os=-unicosmp + ;; + cr16c) + basic_machine=cr16c-unknown + os=-elf + ;; + crds | unos) + basic_machine=m68k-crds + ;; + crisv32 | crisv32-* | etraxfs*) + basic_machine=crisv32-axis + ;; + cris | cris-* | etrax*) + basic_machine=cris-axis + ;; + crx) + basic_machine=crx-unknown + os=-elf + ;; + da30 | da30-*) + basic_machine=m68k-da30 + ;; + decstation | decstation-3100 | pmax | pmax-* | pmin | dec3100 | decstatn) + basic_machine=mips-dec + ;; + decsystem10* | dec10*) + basic_machine=pdp10-dec + os=-tops10 + ;; + decsystem20* | dec20*) + basic_machine=pdp10-dec + os=-tops20 + ;; + delta | 3300 | motorola-3300 | motorola-delta \ + | 3300-motorola | delta-motorola) + basic_machine=m68k-motorola + ;; + delta88) + basic_machine=m88k-motorola + os=-sysv3 + ;; + djgpp) + basic_machine=i586-pc + os=-msdosdjgpp + ;; + dpx20 | dpx20-*) + basic_machine=rs6000-bull + os=-bosx + ;; + dpx2* | dpx2*-bull) + basic_machine=m68k-bull + os=-sysv3 + ;; + ebmon29k) + basic_machine=a29k-amd + os=-ebmon + ;; + elxsi) + basic_machine=elxsi-elxsi + os=-bsd + ;; + encore | umax | mmax) + basic_machine=ns32k-encore + ;; + es1800 | OSE68k | ose68k | ose | OSE) + basic_machine=m68k-ericsson + os=-ose + ;; + fx2800) + basic_machine=i860-alliant + ;; + genix) + basic_machine=ns32k-ns + ;; + gmicro) + basic_machine=tron-gmicro + os=-sysv + ;; + go32) + basic_machine=i386-pc + os=-go32 + ;; + h3050r* | hiux*) + basic_machine=hppa1.1-hitachi + os=-hiuxwe2 + ;; + h8300hms) + basic_machine=h8300-hitachi + os=-hms + ;; + h8300xray) + basic_machine=h8300-hitachi + os=-xray + ;; + h8500hms) + basic_machine=h8500-hitachi + os=-hms + ;; + harris) + basic_machine=m88k-harris + os=-sysv3 + ;; + hp300-*) + basic_machine=m68k-hp + ;; + hp300bsd) + basic_machine=m68k-hp + os=-bsd + ;; + hp300hpux) + basic_machine=m68k-hp + os=-hpux + ;; + hp3k9[0-9][0-9] | hp9[0-9][0-9]) + basic_machine=hppa1.0-hp + ;; + hp9k2[0-9][0-9] | hp9k31[0-9]) + basic_machine=m68000-hp + ;; + hp9k3[2-9][0-9]) + basic_machine=m68k-hp + ;; + hp9k6[0-9][0-9] | hp6[0-9][0-9]) + basic_machine=hppa1.0-hp + ;; + hp9k7[0-79][0-9] | hp7[0-79][0-9]) + basic_machine=hppa1.1-hp + ;; + hp9k78[0-9] | hp78[0-9]) + # FIXME: really hppa2.0-hp + basic_machine=hppa1.1-hp + ;; + hp9k8[67]1 | hp8[67]1 | hp9k80[24] | hp80[24] | hp9k8[78]9 | hp8[78]9 | hp9k893 | hp893) + # FIXME: really hppa2.0-hp + basic_machine=hppa1.1-hp + ;; + hp9k8[0-9][13679] | hp8[0-9][13679]) + basic_machine=hppa1.1-hp + ;; + hp9k8[0-9][0-9] | hp8[0-9][0-9]) + basic_machine=hppa1.0-hp + ;; + hppa-next) + os=-nextstep3 + ;; + hppaosf) + basic_machine=hppa1.1-hp + os=-osf + ;; + hppro) + basic_machine=hppa1.1-hp + os=-proelf + ;; + i370-ibm* | ibm*) + basic_machine=i370-ibm + ;; +# I'm not sure what "Sysv32" means. Should this be sysv3.2? + i*86v32) + basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` + os=-sysv32 + ;; + i*86v4*) + basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` + os=-sysv4 + ;; + i*86v) + basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` + os=-sysv + ;; + i*86sol2) + basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` + os=-solaris2 + ;; + i386mach) + basic_machine=i386-mach + os=-mach + ;; + i386-vsta | vsta) + basic_machine=i386-unknown + os=-vsta + ;; + iris | iris4d) + basic_machine=mips-sgi + case $os in + -irix*) + ;; + *) + os=-irix4 + ;; + esac + ;; + isi68 | isi) + basic_machine=m68k-isi + os=-sysv + ;; + m88k-omron*) + basic_machine=m88k-omron + ;; + magnum | m3230) + basic_machine=mips-mips + os=-sysv + ;; + merlin) + basic_machine=ns32k-utek + os=-sysv + ;; + mingw32) + basic_machine=i386-pc + os=-mingw32 + ;; + miniframe) + basic_machine=m68000-convergent + ;; + *mint | -mint[0-9]* | *MiNT | *MiNT[0-9]*) + basic_machine=m68k-atari + os=-mint + ;; + mips3*-*) + basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'` + ;; + mips3*) + basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'`-unknown + ;; + monitor) + basic_machine=m68k-rom68k + os=-coff + ;; + morphos) + basic_machine=powerpc-unknown + os=-morphos + ;; + msdos) + basic_machine=i386-pc + os=-msdos + ;; + ms1-*) + basic_machine=`echo $basic_machine | sed -e 's/ms1-/mt-/'` + ;; + mvs) + basic_machine=i370-ibm + os=-mvs + ;; + ncr3000) + basic_machine=i486-ncr + os=-sysv4 + ;; + netbsd386) + basic_machine=i386-unknown + os=-netbsd + ;; + netwinder) + basic_machine=armv4l-rebel + os=-linux + ;; + news | news700 | news800 | news900) + basic_machine=m68k-sony + os=-newsos + ;; + news1000) + basic_machine=m68030-sony + os=-newsos + ;; + news-3600 | risc-news) + basic_machine=mips-sony + os=-newsos + ;; + necv70) + basic_machine=v70-nec + os=-sysv + ;; + next | m*-next ) + basic_machine=m68k-next + case $os in + -nextstep* ) + ;; + -ns2*) + os=-nextstep2 + ;; + *) + os=-nextstep3 + ;; + esac + ;; + nh3000) + basic_machine=m68k-harris + os=-cxux + ;; + nh[45]000) + basic_machine=m88k-harris + os=-cxux + ;; + nindy960) + basic_machine=i960-intel + os=-nindy + ;; + mon960) + basic_machine=i960-intel + os=-mon960 + ;; + nonstopux) + basic_machine=mips-compaq + os=-nonstopux + ;; + np1) + basic_machine=np1-gould + ;; + nsr-tandem) + basic_machine=nsr-tandem + ;; + op50n-* | op60c-*) + basic_machine=hppa1.1-oki + os=-proelf + ;; + openrisc | openrisc-*) + basic_machine=or32-unknown + ;; + os400) + basic_machine=powerpc-ibm + os=-os400 + ;; + OSE68000 | ose68000) + basic_machine=m68000-ericsson + os=-ose + ;; + os68k) + basic_machine=m68k-none + os=-os68k + ;; + pa-hitachi) + basic_machine=hppa1.1-hitachi + os=-hiuxwe2 + ;; + paragon) + basic_machine=i860-intel + os=-osf + ;; + pbd) + basic_machine=sparc-tti + ;; + pbb) + basic_machine=m68k-tti + ;; + pc532 | pc532-*) + basic_machine=ns32k-pc532 + ;; + pc98) + basic_machine=i386-pc + ;; + pc98-*) + basic_machine=i386-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + pentium | p5 | k5 | k6 | nexgen | viac3) + basic_machine=i586-pc + ;; + pentiumpro | p6 | 6x86 | athlon | athlon_*) + basic_machine=i686-pc + ;; + pentiumii | pentium2 | pentiumiii | pentium3) + basic_machine=i686-pc + ;; + pentium4) + basic_machine=i786-pc + ;; + pentium-* | p5-* | k5-* | k6-* | nexgen-* | viac3-*) + basic_machine=i586-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + pentiumpro-* | p6-* | 6x86-* | athlon-*) + basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + pentiumii-* | pentium2-* | pentiumiii-* | pentium3-*) + basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + pentium4-*) + basic_machine=i786-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + pn) + basic_machine=pn-gould + ;; + power) basic_machine=power-ibm + ;; + ppc) basic_machine=powerpc-unknown + ;; + ppc-*) basic_machine=powerpc-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + ppcle | powerpclittle | ppc-le | powerpc-little) + basic_machine=powerpcle-unknown + ;; + ppcle-* | powerpclittle-*) + basic_machine=powerpcle-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + ppc64) basic_machine=powerpc64-unknown + ;; + ppc64-*) basic_machine=powerpc64-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + ppc64le | powerpc64little | ppc64-le | powerpc64-little) + basic_machine=powerpc64le-unknown + ;; + ppc64le-* | powerpc64little-*) + basic_machine=powerpc64le-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + ps2) + basic_machine=i386-ibm + ;; + pw32) + basic_machine=i586-unknown + os=-pw32 + ;; + rdos) + basic_machine=i386-pc + os=-rdos + ;; + rom68k) + basic_machine=m68k-rom68k + os=-coff + ;; + rm[46]00) + basic_machine=mips-siemens + ;; + rtpc | rtpc-*) + basic_machine=romp-ibm + ;; + s390 | s390-*) + basic_machine=s390-ibm + ;; + s390x | s390x-*) + basic_machine=s390x-ibm + ;; + sa29200) + basic_machine=a29k-amd + os=-udi + ;; + sb1) + basic_machine=mipsisa64sb1-unknown + ;; + sb1el) + basic_machine=mipsisa64sb1el-unknown + ;; + sei) + basic_machine=mips-sei + os=-seiux + ;; + sequent) + basic_machine=i386-sequent + ;; + sh) + basic_machine=sh-hitachi + os=-hms + ;; + sh64) + basic_machine=sh64-unknown + ;; + sparclite-wrs | simso-wrs) + basic_machine=sparclite-wrs + os=-vxworks + ;; + sps7) + basic_machine=m68k-bull + os=-sysv2 + ;; + spur) + basic_machine=spur-unknown + ;; + st2000) + basic_machine=m68k-tandem + ;; + stratus) + basic_machine=i860-stratus + os=-sysv4 + ;; + sun2) + basic_machine=m68000-sun + ;; + sun2os3) + basic_machine=m68000-sun + os=-sunos3 + ;; + sun2os4) + basic_machine=m68000-sun + os=-sunos4 + ;; + sun3os3) + basic_machine=m68k-sun + os=-sunos3 + ;; + sun3os4) + basic_machine=m68k-sun + os=-sunos4 + ;; + sun4os3) + basic_machine=sparc-sun + os=-sunos3 + ;; + sun4os4) + basic_machine=sparc-sun + os=-sunos4 + ;; + sun4sol2) + basic_machine=sparc-sun + os=-solaris2 + ;; + sun3 | sun3-*) + basic_machine=m68k-sun + ;; + sun4) + basic_machine=sparc-sun + ;; + sun386 | sun386i | roadrunner) + basic_machine=i386-sun + ;; + sv1) + basic_machine=sv1-cray + os=-unicos + ;; + symmetry) + basic_machine=i386-sequent + os=-dynix + ;; + t3e) + basic_machine=alphaev5-cray + os=-unicos + ;; + t90) + basic_machine=t90-cray + os=-unicos + ;; + tic54x | c54x*) + basic_machine=tic54x-unknown + os=-coff + ;; + tic55x | c55x*) + basic_machine=tic55x-unknown + os=-coff + ;; + tic6x | c6x*) + basic_machine=tic6x-unknown + os=-coff + ;; + tx39) + basic_machine=mipstx39-unknown + ;; + tx39el) + basic_machine=mipstx39el-unknown + ;; + toad1) + basic_machine=pdp10-xkl + os=-tops20 + ;; + tower | tower-32) + basic_machine=m68k-ncr + ;; + tpf) + basic_machine=s390x-ibm + os=-tpf + ;; + udi29k) + basic_machine=a29k-amd + os=-udi + ;; + ultra3) + basic_machine=a29k-nyu + os=-sym1 + ;; + v810 | necv810) + basic_machine=v810-nec + os=-none + ;; + vaxv) + basic_machine=vax-dec + os=-sysv + ;; + vms) + basic_machine=vax-dec + os=-vms + ;; + vpp*|vx|vx-*) + basic_machine=f301-fujitsu + ;; + vxworks960) + basic_machine=i960-wrs + os=-vxworks + ;; + vxworks68) + basic_machine=m68k-wrs + os=-vxworks + ;; + vxworks29k) + basic_machine=a29k-wrs + os=-vxworks + ;; + w65*) + basic_machine=w65-wdc + os=-none + ;; + w89k-*) + basic_machine=hppa1.1-winbond + os=-proelf + ;; + xbox) + basic_machine=i686-pc + os=-mingw32 + ;; + xps | xps100) + basic_machine=xps100-honeywell + ;; + ymp) + basic_machine=ymp-cray + os=-unicos + ;; + z8k-*-coff) + basic_machine=z8k-unknown + os=-sim + ;; + none) + basic_machine=none-none + os=-none + ;; + +# Here we handle the default manufacturer of certain CPU types. It is in +# some cases the only manufacturer, in others, it is the most popular. + w89k) + basic_machine=hppa1.1-winbond + ;; + op50n) + basic_machine=hppa1.1-oki + ;; + op60c) + basic_machine=hppa1.1-oki + ;; + romp) + basic_machine=romp-ibm + ;; + mmix) + basic_machine=mmix-knuth + ;; + rs6000) + basic_machine=rs6000-ibm + ;; + vax) + basic_machine=vax-dec + ;; + pdp10) + # there are many clones, so DEC is not a safe bet + basic_machine=pdp10-unknown + ;; + pdp11) + basic_machine=pdp11-dec + ;; + we32k) + basic_machine=we32k-att + ;; + sh[1234] | sh[24]a | sh[34]eb | sh[1234]le | sh[23]ele) + basic_machine=sh-unknown + ;; + sparc | sparcv8 | sparcv9 | sparcv9b | sparcv9v) + basic_machine=sparc-sun + ;; + cydra) + basic_machine=cydra-cydrome + ;; + orion) + basic_machine=orion-highlevel + ;; + orion105) + basic_machine=clipper-highlevel + ;; + mac | mpw | mac-mpw) + basic_machine=m68k-apple + ;; + pmac | pmac-mpw) + basic_machine=powerpc-apple + ;; + *-unknown) + # Make sure to match an already-canonicalized machine name. + ;; + *) + echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2 + exit 1 + ;; +esac + +# Here we canonicalize certain aliases for manufacturers. +case $basic_machine in + *-digital*) + basic_machine=`echo $basic_machine | sed 's/digital.*/dec/'` + ;; + *-commodore*) + basic_machine=`echo $basic_machine | sed 's/commodore.*/cbm/'` + ;; + *) + ;; +esac + +# Decode manufacturer-specific aliases for certain operating systems. + +if [ x"$os" != x"" ] +then +case $os in + # First match some system type aliases + # that might get confused with valid system types. + # -solaris* is a basic system type, with this one exception. + -solaris1 | -solaris1.*) + os=`echo $os | sed -e 's|solaris1|sunos4|'` + ;; + -solaris) + os=-solaris2 + ;; + -svr4*) + os=-sysv4 + ;; + -unixware*) + os=-sysv4.2uw + ;; + -gnu/linux*) + os=`echo $os | sed -e 's|gnu/linux|linux-gnu|'` + ;; + # First accept the basic system types. + # The portable systems comes first. + # Each alternative MUST END IN A *, to match a version number. + # -sysv* is not here because it comes later, after sysvr4. + -gnu* | -bsd* | -mach* | -minix* | -genix* | -ultrix* | -irix* \ + | -*vms* | -sco* | -esix* | -isc* | -aix* | -sunos | -sunos[34]*\ + | -hpux* | -unos* | -osf* | -luna* | -dgux* | -solaris* | -sym* \ + | -amigaos* | -amigados* | -msdos* | -newsos* | -unicos* | -aof* \ + | -aos* \ + | -nindy* | -vxsim* | -vxworks* | -ebmon* | -hms* | -mvs* \ + | -clix* | -riscos* | -uniplus* | -iris* | -rtu* | -xenix* \ + | -hiux* | -386bsd* | -knetbsd* | -mirbsd* | -netbsd* \ + | -openbsd* | -solidbsd* \ + | -ekkobsd* | -kfreebsd* | -freebsd* | -riscix* | -lynxos* \ + | -bosx* | -nextstep* | -cxux* | -aout* | -elf* | -oabi* \ + | -ptx* | -coff* | -ecoff* | -winnt* | -domain* | -vsta* \ + | -udi* | -eabi* | -lites* | -ieee* | -go32* | -aux* \ + | -chorusos* | -chorusrdb* \ + | -cygwin* | -pe* | -psos* | -moss* | -proelf* | -rtems* \ + | -mingw32* | -linux-gnu* | -linux-newlib* | -linux-uclibc* \ + | -uxpv* | -beos* | -mpeix* | -udk* \ + | -interix* | -uwin* | -mks* | -rhapsody* | -darwin* | -opened* \ + | -openstep* | -oskit* | -conix* | -pw32* | -nonstopux* \ + | -storm-chaos* | -tops10* | -tenex* | -tops20* | -its* \ + | -os2* | -vos* | -palmos* | -uclinux* | -nucleus* \ + | -morphos* | -superux* | -rtmk* | -rtmk-nova* | -windiss* \ + | -powermax* | -dnix* | -nx6 | -nx7 | -sei* | -dragonfly* \ + | -skyos* | -haiku* | -rdos* | -toppers*) + # Remember, each alternative MUST END IN *, to match a version number. + ;; + -qnx*) + case $basic_machine in + x86-* | i*86-*) + ;; + *) + os=-nto$os + ;; + esac + ;; + -nto-qnx*) + ;; + -nto*) + os=`echo $os | sed -e 's|nto|nto-qnx|'` + ;; + -sim | -es1800* | -hms* | -xray | -os68k* | -none* | -v88r* \ + | -windows* | -osx | -abug | -netware* | -os9* | -beos* | -haiku* \ + | -macos* | -mpw* | -magic* | -mmixware* | -mon960* | -lnews*) + ;; + -mac*) + os=`echo $os | sed -e 's|mac|macos|'` + ;; + -linux-dietlibc) + os=-linux-dietlibc + ;; + -linux*) + os=`echo $os | sed -e 's|linux|linux-gnu|'` + ;; + -sunos5*) + os=`echo $os | sed -e 's|sunos5|solaris2|'` + ;; + -sunos6*) + os=`echo $os | sed -e 's|sunos6|solaris3|'` + ;; + -opened*) + os=-openedition + ;; + -os400*) + os=-os400 + ;; + -wince*) + os=-wince + ;; + -osfrose*) + os=-osfrose + ;; + -osf*) + os=-osf + ;; + -utek*) + os=-bsd + ;; + -dynix*) + os=-bsd + ;; + -acis*) + os=-aos + ;; + -atheos*) + os=-atheos + ;; + -syllable*) + os=-syllable + ;; + -386bsd) + os=-bsd + ;; + -ctix* | -uts*) + os=-sysv + ;; + -nova*) + os=-rtmk-nova + ;; + -ns2 ) + os=-nextstep2 + ;; + -nsk*) + os=-nsk + ;; + # Preserve the version number of sinix5. + -sinix5.*) + os=`echo $os | sed -e 's|sinix|sysv|'` + ;; + -sinix*) + os=-sysv4 + ;; + -tpf*) + os=-tpf + ;; + -triton*) + os=-sysv3 + ;; + -oss*) + os=-sysv3 + ;; + -svr4) + os=-sysv4 + ;; + -svr3) + os=-sysv3 + ;; + -sysvr4) + os=-sysv4 + ;; + # This must come after -sysvr4. + -sysv*) + ;; + -ose*) + os=-ose + ;; + -es1800*) + os=-ose + ;; + -xenix) + os=-xenix + ;; + -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*) + os=-mint + ;; + -aros*) + os=-aros + ;; + -kaos*) + os=-kaos + ;; + -zvmoe) + os=-zvmoe + ;; + -none) + ;; + *) + # Get rid of the `-' at the beginning of $os. + os=`echo $os | sed 's/[^-]*-//'` + echo Invalid configuration \`$1\': system \`$os\' not recognized 1>&2 + exit 1 + ;; +esac +else + +# Here we handle the default operating systems that come with various machines. +# The value should be what the vendor currently ships out the door with their +# machine or put another way, the most popular os provided with the machine. + +# Note that if you're going to try to match "-MANUFACTURER" here (say, +# "-sun"), then you have to tell the case statement up towards the top +# that MANUFACTURER isn't an operating system. Otherwise, code above +# will signal an error saying that MANUFACTURER isn't an operating +# system, and we'll never get to this point. + +case $basic_machine in + spu-*) + os=-elf + ;; + *-acorn) + os=-riscix1.2 + ;; + arm*-rebel) + os=-linux + ;; + arm*-semi) + os=-aout + ;; + c4x-* | tic4x-*) + os=-coff + ;; + # This must come before the *-dec entry. + pdp10-*) + os=-tops20 + ;; + pdp11-*) + os=-none + ;; + *-dec | vax-*) + os=-ultrix4.2 + ;; + m68*-apollo) + os=-domain + ;; + i386-sun) + os=-sunos4.0.2 + ;; + m68000-sun) + os=-sunos3 + # This also exists in the configure program, but was not the + # default. + # os=-sunos4 + ;; + m68*-cisco) + os=-aout + ;; + mips*-cisco) + os=-elf + ;; + mips*-*) + os=-elf + ;; + or32-*) + os=-coff + ;; + *-tti) # must be before sparc entry or we get the wrong os. + os=-sysv3 + ;; + sparc-* | *-sun) + os=-sunos4.1.1 + ;; + *-be) + os=-beos + ;; + *-haiku) + os=-haiku + ;; + *-ibm) + os=-aix + ;; + *-knuth) + os=-mmixware + ;; + *-wec) + os=-proelf + ;; + *-winbond) + os=-proelf + ;; + *-oki) + os=-proelf + ;; + *-hp) + os=-hpux + ;; + *-hitachi) + os=-hiux + ;; + i860-* | *-att | *-ncr | *-altos | *-motorola | *-convergent) + os=-sysv + ;; + *-cbm) + os=-amigaos + ;; + *-dg) + os=-dgux + ;; + *-dolphin) + os=-sysv3 + ;; + m68k-ccur) + os=-rtu + ;; + m88k-omron*) + os=-luna + ;; + *-next ) + os=-nextstep + ;; + *-sequent) + os=-ptx + ;; + *-crds) + os=-unos + ;; + *-ns) + os=-genix + ;; + i370-*) + os=-mvs + ;; + *-next) + os=-nextstep3 + ;; + *-gould) + os=-sysv + ;; + *-highlevel) + os=-bsd + ;; + *-encore) + os=-bsd + ;; + *-sgi) + os=-irix + ;; + *-siemens) + os=-sysv4 + ;; + *-masscomp) + os=-rtu + ;; + f30[01]-fujitsu | f700-fujitsu) + os=-uxpv + ;; + *-rom68k) + os=-coff + ;; + *-*bug) + os=-coff + ;; + *-apple) + os=-macos + ;; + *-atari*) + os=-mint + ;; + *) + os=-none + ;; +esac +fi + +# Here we handle the case where we know the os, and the CPU type, but not the +# manufacturer. We pick the logical manufacturer. +vendor=unknown +case $basic_machine in + *-unknown) + case $os in + -riscix*) + vendor=acorn + ;; + -sunos*) + vendor=sun + ;; + -aix*) + vendor=ibm + ;; + -beos*) + vendor=be + ;; + -hpux*) + vendor=hp + ;; + -mpeix*) + vendor=hp + ;; + -hiux*) + vendor=hitachi + ;; + -unos*) + vendor=crds + ;; + -dgux*) + vendor=dg + ;; + -luna*) + vendor=omron + ;; + -genix*) + vendor=ns + ;; + -mvs* | -opened*) + vendor=ibm + ;; + -os400*) + vendor=ibm + ;; + -ptx*) + vendor=sequent + ;; + -tpf*) + vendor=ibm + ;; + -vxsim* | -vxworks* | -windiss*) + vendor=wrs + ;; + -aux*) + vendor=apple + ;; + -hms*) + vendor=hitachi + ;; + -mpw* | -macos*) + vendor=apple + ;; + -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*) + vendor=atari + ;; + -vos*) + vendor=stratus + ;; + esac + basic_machine=`echo $basic_machine | sed "s/unknown/$vendor/"` + ;; +esac + +echo $basic_machine$os +exit + +# Local variables: +# eval: (add-hook 'write-file-hooks 'time-stamp) +# time-stamp-start: "timestamp='" +# time-stamp-format: "%:y-%02m-%02d" +# time-stamp-end: "'" +# End: diff --git a/autoconf/configure.ac b/autoconf/configure.ac new file mode 100644 index 0000000..1ef8cf5 --- /dev/null +++ b/autoconf/configure.ac @@ -0,0 +1,230 @@ +AC_INIT(src/isis.c) +AC_PREFIX_DEFAULT(/usr/local) +JH_CONFIG_DIR_SANS_AMD +JD_INIT + +JH_WITH_SUBDIR + +AC_CONFIG_HEADER(\ + src/config.h:src/config.hin \ + test/config.h:test/config.hin \ + modules/xspec/src/config.h:modules/xspec/src/config.hin\ + modules/cfitsio/src/config.h:modules/cfitsio/src/config.hin\ + modules/pgplot/src/config.h:modules/pgplot/src/config.hin\ + modules/maplib/src/config.h:modules/maplib/src/config.hin\ +) + +AC_CONFIG_AUX_DIR(autoconf) +AC_PROG_MAKE_SET +AC_PROG_RANLIB +AC_PROG_INSTALL +AC_CANONICAL_HOST + +AC_PROG_FC + +JD_ANSI_CC +JD_ELF_COMPILER +JD_IEEE_CFLAGS +ELF_CFLAGS="$ELF_CFLAGS $IEEE_CFLAGS" +CFLAGS="$CFLAGS $IEEE_CFLAGS" + +AC_FC_LIBRARY_LDFLAGS +AC_FC_DUMMY_MAIN(, + AC_DEFINE(FC_DUMMY_MAIN,MAIN__) +) +JH_FC_DEFS +dnl JH_FORCE_UNDEFINED_SYMBOLS + +AC_ARG_WITH(fclibs, + [ --with-fclibs=libs Provide extra Fortran libraries, e.g. "-lg2c" ], + [jh_fclibs_extra=$withval], [jh_fclibs_extra=no]) +FC_EXTRA_LIBS="" +if test "x$jh_fclibs_extra" != "xno" +then + FC_EXTRA_LIBS="$jh_fclibs_extra" +fi +AC_SUBST(FC_EXTRA_LIBS) + +JD_LARGE_FILE_SUPPORT + +# Extra Headers for xlibs +AC_PATH_XTRA + +AC_CHECK_TYPES(unsigned long long) +AC_CHECK_SIZEOF(unsigned long long) + +AC_CHECK_SIZEOF(short, 2) +AC_CHECK_SIZEOF(int, 4) +AC_CHECK_SIZEOF(long, 4) +AC_CHECK_SIZEOF(float, 4) +AC_CHECK_SIZEOF(double, 8) + +JH_INIT_MODULE_LIST + +# initialization +SLANG_LIB=no +CFITSIO_LIB=no +PGPLOT_LIB=no + +# reasonable pgplot default +PGPLOT_LIBDIR=/usr/local/pgplot +if test -d $PGPLOT_LIBDIR +then + PGPLOT_LIB="-L$PGPLOT_LIBDIR" + PGPLOT_INC="-I$PGPLOT_LIBDIR" +fi + +ATOMDB_DIR="" +HEADAS_DIR="" + +dnl This must precede the JD_WITH_LIBRARY() macros +dnl for slang, cfitsio and pgplot +JH_HANDLE_PACKAGE_OPTIONS + +if test "x$PGPLOT_LIB" = "xno" \ + || test "${with_pgplot+set}" = set \ + || test "${with_pgplotlib+set}" = set \ + || test "${with_pgplotinc+set}" = set +then + JD_WITH_LIBRARY(pgplot, cpgplot.h) + JH_CHECK_PGPLOT_LIBNAME($jd_pgplot_library_dir) + PGPLOT_LIBDIR="$jh_pgplot_library_dir" + AC_SUBST(PGPLOT_LIBDIR) +fi + +if test "x$CFITSIO_LIB" = "xno" \ + || test "${with_cfitsio+set}" = set \ + || test "${with_cfitsiolib+set}" = set \ + || test "${with_cfitsioinc+set}" = set +then + JD_WITH_LIBRARY(cfitsio, fitsio.h) + JH_CHECK_CFITSIO_LIBNAME($jd_cfitsio_library_dir) +fi + +if test "x$SLANG_LIB" = "xno" +then + JD_WITH_LIBRARY(slang) + SLANG_LIBDIR="$jd_slang_library_dir" + AC_SUBST(SLANG_LIBDIR) +fi + +AC_ARG_WITH(atomdb, + [ --with-atomdb[=DIR] location of spectroscopy database (ATOMDB)], + [jd_use_atomdb=$withval], [jd_use_atomdb=no]) +if test "x$jd_use_atomdb" != "xno" +then + ATOMDB_DIR=$jd_use_atomdb +fi +AC_SUBST(ATOMDB_DIR) + +AC_ARG_WITH(djbfft, +[ --with-djbfft=DIR Use djbfft for pileup FFTs + (from DIR/lib and DIR/include)], + [ jh_use_djbfft=$withval ], [jh_use_djbfft=no]) +if test "x$jh_use_djbfft" != "xno" +then + EXTRA_LIB="$EXTRA_LIB $jh_use_djbfft/lib/djbfft.a" + EXTRA_INC="$EXTRA_INC -I$jh_use_djbfft/include" + AC_SUBST(EXTRA_LIB) + AC_SUBST(EXTRA_INC) + AC_DEFINE(HAVE_DJBFFT) +fi + +JH_TERMCAP_LIB +JH_WITH_READLINE + +JH_SYS_EXTRA_LIBS + +MODULE_INSTALL_DIR='${prefix}/lib/modules' +SL_FILES_INSTALL_DIR='${prefix}/share' +AC_SUBST(MODULE_INSTALL_DIR) +AC_SUBST(SL_FILES_INSTALL_DIR) + +dnl Check these header since they cause trouble +AC_CHECK_HEADERS( \ +stdlib.h \ +unistd.h \ +sys/stat.h \ +sys/wait.h \ +sys/types.h \ +dlfcn.h \ +ieeefp.h \ +) + +AC_CHECK_FUNCS(\ +stat \ +sigaction \ +sigemptyset \ +sigprocmask \ +sigaddset \ +vsnprintf \ +isinf \ +isnan \ +finite \ +) + +JD_SET_OBJ_SRC_DIR(src) +JD_GCC_WARNINGS +JH_PURIFY + +dnl AC_CONFIG_SUBDIRS(modules/xspec) +dnl AC_CONFIG_SUBDIRS(modules/cfitsio) +dnl AC_CONFIG_SUBDIRS(modules/pgplot) + +JD_GET_MODULES(src/modules.lis,src) +JH_GET_FC_MODULES(src/fc_modules.lis,src) +JH_GET_SHAREFILES(share/modules.lis) +JH_GET_ETCFILES(etc/modules.lis) + +AC_OUTPUT(\ + Makefile:autoconf/Makefile.in \ + src/Makefile \ + test/Makefile \ + test/uncon/Makefile \ + modules/Makefile \ + modules/cfitsio/Makefile:modules/cfitsio/autoconf/Makefile.in \ + modules/cfitsio/src/Makefile:modules/cfitsio/src/Makefile.in \ + modules/pgplot/Makefile:modules/pgplot/autoconf/Makefile.in \ + modules/pgplot/src/Makefile:modules/pgplot/src/Makefile.in \ + modules/xspec/Makefile:modules/xspec/autoconf/Makefile.in \ + modules/xspec/src/Makefile:modules/xspec/src/Makefile.in \ + modules/xspec/src/xspec_libs:modules/xspec/src/xspec_libs.in \ + modules/maplib/Makefile:modules/maplib/autoconf/Makefile.in \ + modules/maplib/src/Makefile:modules/maplib/src/Makefile.in \ +) + +dnl JD_CREATE_EXEC_RULE(isis) +JD_CREATE_FLINK_EXEC_RULE(isis) +JD_CREATE_ELFORULE(isis) + +JD_CREATE_MODULE_ORULES(src) +JD_APPEND_RULES(src/Makefile) +JD_APPEND_ELFRULES(src/Makefile) + +JH_CREATE_FC_MODULE_ORULES(src) +JH_APPEND_FC_RULES(src/Makefile) +JH_APPEND_FC_ELFRULES(src/Makefile) + +echo "" +echo "You are compiling with this compiler configuration:" +echo " CC =" "$CC" +echo " CFLAGS =" "$CFLAGS" +echo " LDFLAGS =" "$LDFLAGS" "$DYNAMIC_LINK_FLAGS" +echo " FC =" "$FC" +echo " FCFLAGS =" "$FCFLAGS" +echo "" +if test "x$HEADAS_DIR" != "x" ; then + echo "XSPEC module configuration:" + echo " --with-xspec-version = ${with_xspec_version}" + echo " --with-headas = $HEADAS_DIR" +else + echo "The XSPEC module will not be compiled." +fi + echo "" +echo "isis will be installed in" "$prefix" +echo "" +echo "If $prefix_input/bin exists," +echo "a symbolic link to the isis executable will be placed there." +echo "" +echo "To see the list of configuration options:" +echo " ./configure --help" diff --git a/autoconf/install-sh b/autoconf/install-sh new file mode 100755 index 0000000..89fc9b0 --- /dev/null +++ b/autoconf/install-sh @@ -0,0 +1,238 @@ +#! /bin/sh +# +# install - install a program, script, or datafile +# This comes from X11R5. +# +# Calling this script install-sh is preferred over install.sh, to prevent +# `make' implicit rules from creating a file called install from it +# when there is no Makefile. +# +# This script is compatible with the BSD install script, but was written +# from scratch. +# + + +# set DOITPROG to echo to test this script + +# Don't use :- since 4.3BSD and earlier shells don't like it. +doit="${DOITPROG-}" + + +# put in absolute paths if you don't have them in your path; or use env. vars. + +mvprog="${MVPROG-mv}" +cpprog="${CPPROG-cp}" +chmodprog="${CHMODPROG-chmod}" +chownprog="${CHOWNPROG-chown}" +chgrpprog="${CHGRPPROG-chgrp}" +stripprog="${STRIPPROG-strip}" +rmprog="${RMPROG-rm}" +mkdirprog="${MKDIRPROG-mkdir}" + +tranformbasename="" +transform_arg="" +instcmd="$mvprog" +chmodcmd="$chmodprog 0755" +chowncmd="" +chgrpcmd="" +stripcmd="" +rmcmd="$rmprog -f" +mvcmd="$mvprog" +src="" +dst="" +dir_arg="" + +while [ x"$1" != x ]; do + case $1 in + -c) instcmd="$cpprog" + shift + continue;; + + -d) dir_arg=true + shift + continue;; + + -m) chmodcmd="$chmodprog $2" + shift + shift + continue;; + + -o) chowncmd="$chownprog $2" + shift + shift + continue;; + + -g) chgrpcmd="$chgrpprog $2" + shift + shift + continue;; + + -s) stripcmd="$stripprog" + shift + continue;; + + -t=*) transformarg=`echo $1 | sed 's/-t=//'` + shift + continue;; + + -b=*) transformbasename=`echo $1 | sed 's/-b=//'` + shift + continue;; + + *) if [ x"$src" = x ] + then + src=$1 + else + # this colon is to work around a 386BSD /bin/sh bug + : + dst=$1 + fi + shift + continue;; + esac +done + +if [ x"$src" = x ] +then + echo "install: no input file specified" + exit 1 +else + true +fi + +if [ x"$dir_arg" != x ]; then + dst=$src + src="" + + if [ -d $dst ]; then + instcmd=: + else + instcmd=mkdir + fi +else + +# Waiting for this to be detected by the "$instcmd $src $dsttmp" command +# might cause directories to be created, which would be especially bad +# if $src (and thus $dsttmp) contains '*'. + + if [ -f $src -o -d $src ] + then + true + else + echo "install: $src does not exist" + exit 1 + fi + + if [ x"$dst" = x ] + then + echo "install: no destination specified" + exit 1 + else + true + fi + +# If destination is a directory, append the input filename; if your system +# does not like double slashes in filenames, you may need to add some logic + + if [ -d $dst ] + then + dst="$dst"/`basename $src` + else + true + fi +fi + +## this sed command emulates the dirname command +dstdir=`echo $dst | sed -e 's,[^/]*$,,;s,/$,,;s,^$,.,'` + +# Make sure that the destination directory exists. +# this part is taken from Noah Friedman's mkinstalldirs script + +# Skip lots of stat calls in the usual case. +if [ ! -d "$dstdir" ]; then +defaultIFS=' +' +IFS="${IFS-${defaultIFS}}" + +oIFS="${IFS}" +# Some sh's can't handle IFS=/ for some reason. +IFS='%' +set - `echo ${dstdir} | sed -e 's@/@%@g' -e 's@^%@/@'` +IFS="${oIFS}" + +pathcomp='' + +while [ $# -ne 0 ] ; do + pathcomp="${pathcomp}${1}" + shift + + if [ ! -d "${pathcomp}" ] ; + then + $mkdirprog "${pathcomp}" + else + true + fi + + pathcomp="${pathcomp}/" +done +fi + +if [ x"$dir_arg" != x ] +then + $doit $instcmd $dst && + + if [ x"$chowncmd" != x ]; then $doit $chowncmd $dst; else true ; fi && + if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dst; else true ; fi && + if [ x"$stripcmd" != x ]; then $doit $stripcmd $dst; else true ; fi && + if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dst; else true ; fi +else + +# If we're going to rename the final executable, determine the name now. + + if [ x"$transformarg" = x ] + then + dstfile=`basename $dst` + else + dstfile=`basename $dst $transformbasename | + sed $transformarg`$transformbasename + fi + +# don't allow the sed command to completely eliminate the filename + + if [ x"$dstfile" = x ] + then + dstfile=`basename $dst` + else + true + fi + +# Make a temp file name in the proper directory. + + dsttmp=$dstdir/#inst.$$# + +# Move or copy the file name to the temp name + + $doit $instcmd $src $dsttmp && + + trap "rm -f ${dsttmp}" 0 && + +# and set any options; do chmod last to preserve setuid bits + +# If any of these fail, we abort the whole thing. If we want to +# ignore errors from any of these, just make sure not to ignore +# errors from the above "$doit $instcmd $src $dsttmp" command. + + if [ x"$chowncmd" != x ]; then $doit $chowncmd $dsttmp; else true;fi && + if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dsttmp; else true;fi && + if [ x"$stripcmd" != x ]; then $doit $stripcmd $dsttmp; else true;fi && + if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dsttmp; else true;fi && + +# Now rename the file to the real destination. + + $doit $rmcmd -f $dstdir/$dstfile && + $doit $mvcmd $dsttmp $dstdir/$dstfile + +fi && + + +exit 0 diff --git a/autoconf/isis.binary b/autoconf/isis.binary new file mode 100755 index 0000000..53648ca --- /dev/null +++ b/autoconf/isis.binary @@ -0,0 +1,102 @@ +#! /bin/sh + +# ISIS binary distribution auto-run script +# +# Usage: +# +# setenv ISIS_SRCDIR /path/to/installed/isis-1.1.0 +# $ISIS_SRCDIR/isis +# + +if [ ! "$ISIS_SRCDIR" ]; then + root=`dirname $0` + if [ "`basename $root`"="bin" ]; then + root=`dirname $root` + fi + case "$root" in + "." ) + root=`pwd` + ;; + ".." ) + root=`pwd` + root=`dirname $root` + ;; + * ) + ;; + esac + + if [ ! -f "$root/isis-version" ]; then + echo "ISIS_SRCDIR environment variable is not set" + exit 1 + else + ISIS_SRCDIR=$root + export ISIS_SRCDIR + fi +fi + +ISIS_LOAD_PATH=$ISIS_SRCDIR/share +ISIS_MODULE_PATH=$ISIS_SRCDIR/lib/modules +export ISIS_LOAD_PATH +export ISIS_MODULE_PATH + +if [ ! "$PGPLOT_DIR" ]; then + PGPLOT_DIR=$ISIS_SRCDIR/opt/etc + export PGPLOT_DIR +fi + +# so pgxwin_server is available +PATH="${PATH}:${ISIS_SRCDIR}/opt/bin" +export PATH + +# set LD_LIBRARY_PATH + +LIB_SO=${ISIS_SRCDIR}/opt/lib +host_os=`uname -s` + +case "$host_os" in + *Darwin* ) + if [ ! "$DYLD_LIBRARY_PATH" ]; then + DYLD_LIBRARY_PATH=$LIB_SO + else + case "$DYLD_LIBRARY_PATH" in + *"$LIB_SO"* ) + ;; + * ) + DYLD_LIBRARY_PATH="${LIB_SO}:${DYLD_LIBRARY_PATH}" + ;; + esac + fi + export DYLD_LIBRARY_PATH + ;; + + * ) + if [ ! "$LD_LIBRARY_PATH" ]; then + LD_LIBRARY_PATH=$LIB_SO + else + case "$LD_LIBRARY_PATH" in + *"$LIB_SO"* ) + ;; + * ) + LD_LIBRARY_PATH="${LIB_SO}:${LD_LIBRARY_PATH}" + ;; + esac + fi + export LD_LIBRARY_PATH + ;; +esac + +# support invocation as isis-script +# and pass on any command line arguments +base=`basename $0` +case "$base" in + *"script"* ) + script_option="--script" + ;; + * ) + script_option="" + ;; +esac + +exec $ISIS_SRCDIR/bin/isis.exe $script_option ${@+"$@"} + +#eof diff --git a/autoconf/isis.cdrom b/autoconf/isis.cdrom new file mode 100755 index 0000000..1417253 --- /dev/null +++ b/autoconf/isis.cdrom @@ -0,0 +1,114 @@ +#! /bin/sh + +# ISIS CD auto-run script +# +# Since the locations of the spectroscopy database +# and the lheasoft libraries are known, its easy to +# run ISIS off the CD: + +root=`dirname $0` + +case "$root" in + "." ) + root=`pwd` + ;; + ".." ) + root=`pwd` + root=`dirname $root` + ;; + * ) + ;; +esac + +ATOMDB=$root/atomdb +export ATOMDB + +OS=`uname -a | cut -d' ' -f1` +case "$OS" in + "Linux" ) + HEADAS=$root/headas/i686-pc-linux-gnu-libc2.2.4 + ARCH=i686 + ;; + "SunOS" ) + HEADAS=$root/headas/sparc-sun-solaris2.6 + ARCH=solaris + ;; + "Darwin" ) + CPU=`uname -p` + case "$CPU" in + "powerpc" ) + HEADAS=$root/headas/powerpc-apple-darwin7.9.0 + ARCH=darwin_ppc + ;; + "i386" ) + HEADAS=$root/headas/i686-apple-darwin8.8.1 + ARCH=darwin_intel + ;; + * ) + echo "*** init failed: unrecognized CPU type: $CPU" + exit 0 + ;; + esac + ;; + * ) + echo "*** init failed: unrecognized OS type: $OS" + exit 0 + ;; +esac +export HEADAS + +ISIS_SRCDIR="$root/build/$ARCH" +export ISIS_SRCDIR + +ISIS_LOAD_PATH=$ISIS_SRCDIR/share +ISIS_MODULE_PATH=$ISIS_SRCDIR/lib/modules +export ISIS_LOAD_PATH +export ISIS_MODULE_PATH + +. $HEADAS/headas-init.sh > /dev/null 2>&1 + +XANADU=`dirname $HEADAS` +export XANADU + +PGPLOT_DIR="${ISIS_SRCDIR}/opt/lib" +PGPLOT_FONT="${ISIS_SRCDIR}/opt/etc/grfont.dat" +export PGPLOT_DIR +export PGPLOT_FONT + +# Make certain LD_LIBRARY_PATH got set. + +case "$OS" in + "Darwin" ) + LIB_SO="${ISIS_SRCDIR}/opt/lib:${HEADAS}/lib" + if [ ! "$DYLD_LIBRARY_PATH" ]; then + DYLD_LIBRARY_PATH=$LIB_SO + else + case "$DYLD_LIBRARY_PATH" in + *"$LIB_SO"* ) + ;; + * ) + DYLD_LIBRARY_PATH="${LIB_SO}:${DYLD_LIBRARY_PATH}" + ;; + esac + fi + export DYLD_LIBRARY_PATH + ;; + * ) + LIB_SO="${ISIS_SRCDIR}/opt/lib:${HEADAS}/lib" + if [ ! "$LD_LIBRARY_PATH" ]; then + LD_LIBRARY_PATH=$LIB_SO + else + case "$LD_LIBRARY_PATH" in + *"$LIB_SO"* ) + ;; + * ) + LD_LIBRARY_PATH="${LIB_SO}:${LD_LIBRARY_PATH}" + ;; + esac + fi + export LD_LIBRARY_PATH + ;; +esac + +# pass on all the command line arguments +$ISIS_SRCDIR/bin/isis ${@+"$@"} diff --git a/autoconf/isis_wrap.sh.in b/autoconf/isis_wrap.sh.in new file mode 100644 index 0000000..9f7dc67 --- /dev/null +++ b/autoconf/isis_wrap.sh.in @@ -0,0 +1,29 @@ +#! /bin/sh + +HEADAS=@HEADAS_DIR@ +export HEADAS + +if [ -f "$HEADAS/headas-init.sh" ] ; then + . $HEADAS/headas-init.sh +fi + +if [ ! "$ATOMDB" ]; then + ATOMDB=@ATOMDB_DIR@ + export ATOMDB +fi + +ISIS=@prefix@/bin/isis.exe + +# support invocation as isis-script +# and pass on any command line arguments +base=`basename $0` +case "$base" in + *"script"* ) + script_option="--script" + ;; + * ) + script_option="" + ;; +esac + +exec $ISIS $script_option ${@+"$@"} diff --git a/autoconf/mkinsdir.sh b/autoconf/mkinsdir.sh new file mode 100755 index 0000000..cd1fe0a --- /dev/null +++ b/autoconf/mkinsdir.sh @@ -0,0 +1,32 @@ +#! /bin/sh +# mkinstalldirs --- make directory hierarchy +# Author: Noah Friedman +# Created: 1993-05-16 +# Public domain + +errstatus=0 + +for file +do + set fnord `echo ":$file" | sed -ne 's/^:\//#/;s/^://;s/\// /g;s/^#/\//;p'` + shift + + pathcomp= + for d in ${1+"$@"} ; do + pathcomp="$pathcomp$d" + case "$pathcomp" in + -* ) pathcomp=./$pathcomp ;; + esac + + if test ! -d "$pathcomp"; then + echo "mkdir $pathcomp" 1>&2 + mkdir "$pathcomp" || errstatus=$? + fi + + pathcomp="$pathcomp/" + done +done + +exit $errstatus + +# mkinstalldirs ends here diff --git a/contrib/README b/contrib/README new file mode 100644 index 0000000..3814143 --- /dev/null +++ b/contrib/README @@ -0,0 +1,64 @@ +These scripts were contributed by various users and have +appeared as examples on the ISIS web page at + http://space.mit.edu/cxc/isis/ + +Note: These scripts are included here in the hope that they may + provide useful examples. However, they are not maintained + and may even be incompatible with the current version of + ISIS. + +aped_contin.sl + Define an apec model which computes the apec continuum + spectrum for 1 temperature component. Does not support + continuua by ion or for variable abundances + [** also the ISIS function 'create_aped_fun'] + +aped_fit_models.sl + Define isis user models for aped thermal plasmas. + [** also the ISIS function 'create_aped_fun'] + +ascii.sl + Read and write simple ASCII tables [note that the + isis built-in functions readcol/writecol already + do this] + +bestfit.sl + Generate N random initial parameter values to search + for the best fit. Very useful for exploring a complicated + chi-square space with numerous local minima. + +clear_bits* + Clear STATUS bits in an Chandra event file + +cspec_summary.sl + Generate summary plots for a grating spectrum [counts] + +fshift.sl + Shift an array by a fractional pixel amount (FFT phase + shift) + +fspec_summary.sl + Generate summary plots for a flux-corrected grating + spectrum. + +gsmooth.sl + Fourier smoothing by a Gaussian kernel. + +hanning.sl + Hanning filter + +marxflux* + Generate an input spectrum for a MARX simulation + +max_like.sl + Maximum Likelihood fit-statistic + +monte.sl + Monte Carlo search of a model fit-parameter space. + +pick_el.sl + Takes a line index list (as from "brightest()") and + allows you to sub-select elements and ions from it. + +splot_data.sl + Smoothed data plotting (counts or flux-corrected) diff --git a/contrib/aped_contin.sl b/contrib/aped_contin.sl new file mode 100644 index 0000000..76a6b79 --- /dev/null +++ b/contrib/aped_contin.sl @@ -0,0 +1,104 @@ +%; Time-stamp: <2001-10-23 15:18:39 dph> +%; MIT Directory: ~dph/libisis +%; File: apec_contin_fit.sl +%; Author: D. Huenemoerder +%; Original version: 2001.10.19 +%;==================================================================== +% version: 1.0 +% +% Name: aped_contin_fit( xlo, xhi, par ) +% +% Purpose: define an apec model which computes the apec continuum +% spectrum for 1 temperature component. Does not +% support continuua by ion or for variable abundances +% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% +% Name: fast_aped_contin_fit( xlo, xhi, par ) +% +% Purpose: Use a global continuum model variable for +% a re-normalizable continuum shape model. If the norm is +% frozen, then it is an absolute continuum model. +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% +% Name: fast_aped_contin_init(nhist) +% +% Purpose: Read a continuum model (from a fit) and store into a global +% variable for use by fast_aped_contin_fit(). +% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% +static variable Contin_X_lo, Contin_X_hi, Contin_Value; +% + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +define fast_aped_contin_init (nhist) +{ %+ define + % ASSUMES that a continuum model has been evaluated for histogram + % nhist. This should be called with an MEG histogram, in order to + % provide enough bandpass for both HEG and MEG. + % Resolution is not very important, since it is a continuum. + +% Setup is not done here. First, the equivalent of the following +% should be done: +%% fit_fun("aped_contin(1) + aped_contin(2) + ... + aped_contin(n)"); +%% set_par(...); +%% fit_counts; +%% % etc. +%% Prepare to grab the final continuum array: +%% ignore([lo:hi]); +%% notice(hist); +%% group_data(nhist,0); % undo any grouping or binning +%% rebin_data(nhist,0); +%% eval_flux; % re-evaluate flux, unbinned. + +% Here we get the continuum array and set global variables: + variable y; + y=get_model_flux(nhist); + Contin_Value = y.value; + Contin_X_lo = y.bin_lo; + Contin_X_hi = y.bin_hi; +% +} %- define + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% Now we simply rebin the Contin_Value to the specified grid, +%% allowing a re-normalization: +% +define fast_aped_contin_fit (xlo, xhi, par) +{ %+ define + variable y = + rebin (xlo, xhi, Contin_X_lo, Contin_X_hi, Contin_Value) * par[0]; + return y; +} %- define + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% Define an aped continuum function. +% Proper use of this requires ignoring line features. +% +define aped_contin_fit ( xlo, xhi, par ) +{ %+ define + % xlo, xhi = grid of wavelength bins; + % par[0] = norm; 10^{-14} * VEM/ (4piD^2) + % 10^{-14}~ int{dV n_e n_h} / (4piD^2) + % par[1] = electron temperature [K]; + + variable y; + variable KNORM=1.e14; + + y = (get_contin(xlo, xhi, par[1])).pseudo; + y = (y + (get_contin(xlo, xhi, par[1])).true) * par[0]*KNORM; + + return y; + +} %- define + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +add_slang_function("aped_contin", ["norm","T"]); +add_slang_function ("fast_aped_contin", ["norm"]); + + + + diff --git a/contrib/aped_fit_models.sl b/contrib/aped_fit_models.sl new file mode 100644 index 0000000..dc39ed7 --- /dev/null +++ b/contrib/aped_fit_models.sl @@ -0,0 +1,722 @@ +%; Time-stamp: <2002-05-15 10:53:37 dph> +%; MIT Directory: ~dph/libisis +%; File: aped_fit_models.sl +%; Author: D. Huenemoerder +%; Original version: 2001.10.23 +%;==================================================================== +% +% purpose: Define isis user models for aped thermal plasmas. +% + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% Example scenarios: +% + +% Single-temperature plasma, reduced iron: +% +% fit_fun("apedx(1)"); +% set_par("apedx(1).norm", 0.001, 0, 0.0, 1.0); +% set_par("apedx(1).temp", 10.^7.2, 0, 1.e5, 8.e8); +% list_par; +% eval_counts; + + +% Multi-thermal plasma: +% +% multi_Temps = 10.^[6.5:8.0:0.1]; % temperature grid +% multi_wgts = Float_Type[ length(multi_Temps) ] + 0.001 ; % weights grid +% elem_list = [Fe, O, Ne]; +% elem_abund = [0.1, 0.5, 3.0]; +% aped_set_abund( elem_list, elem_abund ); +% +% aped_multi_setup( multi_Temps, multi_wgts ); +% list_par; % a zillion.... +% eval_counts; % wait a while... +% plot_model_counts(n); + +%%%%%%%%% +% Implicit line and continuum models (modal behavior!) +% ... continuing w/ above multi-thermal... +% Aped_Filter.type = MODEL_LINES; +% Aped_Filter.lines = where(el_ion(Fe,17)); +% (x1, x2) = linear_grid (1, 1+8191*0.005, 8192); +% y_Fe17 = eval_fun( x1, x2 ); +% Aped_Filter.type = MODEL_CONTIN; +% y_cont = eval_fun( x1, x2 ); +% Aped_Filter.type = NULL; % RESET + + + +%%%%%%%%%% +% Explicit continuum models: +% +% Single temperature continuum, low oxygen abundance: +% +% fit_fun("aped_contin(1)"); +% set_par("aped_contin(1).norm", 0.001, 0, 0.0, 1.0); +% set_par("aped_contin(1).T", 10.^7.2, 0, 1.e5, 8.e8); +% aped_set_abund( O, 0.0 ); + +% Multi temperature continuum, normal abundances: +% +% fit_fun("aped_multi_contin(1)"); +% aped_set_abund(); +% aped_multi_contin_setup( 10.^[6.8, 7.2, 7.6], [1.0, 10.0, 5.0] ); +% eval_counts; +% +% Cache that and define the fast version w/ normalization parameter only: +% +% ignore(all_data) ; +% xnotice( n_MEG, 1.7, 25 ); % notice an MEG histogram +% group_data( n_MEG , 0 ) ; % highest resolution grid. +% eval_flux; % compute the model +% fast_aped_contin_init( n_MEG ); % cache it. +% fit_fun("fast_aped_contin(1) + gauss(1)"); % define line + continuum model + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% version 4.0 2002.05.15 Added revised continuum models. +% Unify parameter names: norm, temp +% +% version 3.2 2002.05 fixed aped_fit - collided w/ aped the +% structure; renamed apedx_fit. +% +% version 3.1 2002.04.03 added aped_fit - basic model, one component. +% +% version: 3.0 2002.01.06 add global variable and switch to support +% qualifier of model_spectrum, and use for +% evaluating a model for specific lines or +% contin. +% +% version: 2.0 2001.11.29 include rv version of model +% fixed bug in aped_multi_fit, w/ array counting/indexing. +% version: 1.1 2001.10.29 added is_a_norm flags to +% add_slang_function() call +% version: 1.0 +% +% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + + public variable Aped_Filter = struct {type, lines}; + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% +provide("apedx_fit"); +provide("aped_multi_fit"); +provide("aped_multi_init"); +provide("aped_multi_setup"); +provide("aped_set_abund"); + +provide("aped_rv_fit"); +provide("aped_multi_rv_fit"); +provide("aped_multi_rv_init"); +provide("aped_multi_rv_setup"); +provide("aped_multi_2rv_setup"); + +provide("aped_contin_fit"); +provide("aped_multi_contin_fit"); +provide("fast_aped_contin_fit"); +provide("fast_aped_contin_init"); +provide("aped_multi_contin_setup"); +provide("aped_multi_contin_init"); + + +% pre-define functions: +% +define aped_multi_fit(); % multple T isis model +define aped_multi_init(); % defines the model for given # components +define aped_multi_setup(); % establishes fit function, sets the + % default model parameters +define aped_set_abund(); % sets/resets local static abundance arrays. +% +% ditto, but w/ radial velocity as a parameter (single for all components.) +% +define aped_multi_rv_fit(); % multple T isis model +define aped_multi_rv_init(); % defines the model for given # components +define aped_multi_rv_setup(); % establishes fit function, sets the + % default model parameters + +define aped_contin_fit(); +define aped_multi_contin_fit(); +define fast_aped_contin_fit(); +define fast_aped_contin_init(); +define aped_multi_contin_setup(); +define aped_multi_contin_init(); + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +% +% define local variables for use in storing alternative abundance +% mixes for the plasma models. These are not used as parameters of a +% fit, but for ad hoc tweaks of abundances. See aped_set_abund(); +% +% +static variable Aped_Elem_List, % an array of Z values; e.g [Fe, Ne] or [26, 10] + Aped_Abund_List; % an array of factores relative to + % cosmic, e.g., [0.1, 2.0]; +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%+ +define apedx_fit ( xlo, xhi, par ) +{ +% +% PURPOSE: isis user model, APED thermal plasma; simple interface to +% the plasma state structure. +% +% xlo, xhi = grid of wavelength bins; +% +% params are +% +% norm = 1 +% temperature = 1e+07 +% vturb = 0 +% vrad = 0 +% + + variable ii, % loop counter + y; % return value + + variable mdl = default_plasma_state(); % plasma model definition + +% NOTE: density, absorption not currently supported.... + + mdl.norm = par[0]; + mdl.temperature = par[1]; + mdl.vturb = par[2]; % given in km/s? + mdl.redshift = par[3]/2.99792458e5; % param is in velocity, km/s. + + if ( __is_initialized( &Aped_Elem_List ) ) % apply different abundances, if set + { + mdl.elem = Aped_Elem_List; + mdl.elem_abund = Aped_Abund_List; + } + + define_model(mdl); % define the model (use list_model; to see). + + switch (Aped_Filter.type) + { + case MODEL_LINES: + if (Aped_Filter.lines == NULL) + y = model_spectrum (xlo, xhi, MODEL_LINES); + else + y = model_spectrum (xlo, xhi, MODEL_LINES, Aped_Filter.lines); + } + { + case MODEL_CONTIN: + y = model_spectrum (xlo, xhi, MODEL_CONTIN); + } + { + case NULL: + y = model_spectrum (xlo, xhi); + } + + return y; + +} +%- + +variable params = ["norm", "temp", "vturb", "vrad"]; +add_slang_function( "apedx", params ); + + + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%+ +define aped_multi_fit ( xlo, xhi, par ) +{ +% +% PURPOSE: isis user model, APED thermal plasma, multi-temperature, +% cosmic abundances, low density limit. + +% xlo, xhi = grid of wavelength bins; +% + + variable ii, % loop counter + y, % return value + ncomps = length(par)/2, % # model components + pstate = default_plasma_state(); % plasma model definition + + variable mdl = Struct_Type[ncomps]; + variable norms=par[ [0:ncomps-1] ]; + variable temps=par[ [ncomps:2*ncomps-1] ]; + + for (ii = 0; ii < ncomps; ii++ ) + { + mdl[ii] = @pstate; + mdl[ii].temperature = temps[ii]; + mdl[ii].norm = norms[ii]; + + if ( __is_initialized( &Aped_Elem_List ) ) % apply different abundances, if set + { + mdl[ii].elem = Aped_Elem_List; + mdl[ii].elem_abund = Aped_Abund_List; + } + + } + + define_model(mdl); % define the model (use list_model; to see). + + switch (Aped_Filter.type) + { + case MODEL_LINES: + if (Aped_Filter.lines == NULL) + y = model_spectrum (xlo, xhi, MODEL_LINES); + else + y = model_spectrum (xlo, xhi, MODEL_LINES, Aped_Filter.lines); + } + { + case MODEL_CONTIN: + y = model_spectrum (xlo, xhi, MODEL_CONTIN); + } + { + case NULL: + y = model_spectrum (xlo, xhi); + } + + return y; + +} +%- + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%+ +define aped_multi_init ( ncomps ) +{ +% Dynamically define a model w/ ncomps temperature compents. + + variable i, func_name, T_params, Norm_params, params; + + params = "norm_1"; + + for (i=2; i <= ncomps; i++) + params = [params, "norm_"+string(i)]; + + for (i=1; i <= ncomps; i++) + params = [params, "temp_"+string(i)]; + + add_slang_function( "aped_multi", params, [1:ncomps] ); + +} +%- + + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%+ + +define aped_multi_setup(Temps, Norms) +{ + variable i; + + aped_multi_init( length(Temps) ); + + fit_fun("aped_multi(1)"); + + for ( i = 0; i < length(Temps); i++) + { + set_par( i+1, Norms[i], 0, 0, 100*Norms[i] ); + set_par( i+length(Temps)+1, Temps[i], 0, 1.e4, 7.95e8 ); + } + +% list_par; +} + +%- + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%+ + +define aped_set_abund() % sets local static abundance arrays. +{ + variable elems; + +% example usage: +% aped_set_abund([Fe, Ne], [0.1, 2.0]); % change abunds of iron and neon +% aped_set_abund([Fe, Ne]); % reset abunds of iron and neon to cosmic +% aped_set_abund(); % reset current list to cosmic. + + switch (_NARGS) + { + case 0: % reset list to cosmic (1.0) + if (__is_initialized (&Aped_Abund_List) ) + Aped_Abund_List = Aped_Abund_List*0 + 1; % set to cosmic; + } + { + case 1: % have element list, so set them to cosmic. + elems=(); + variable i; + for ( i = 0; i < length(elems); i++) + Aped_Abund_List[where(Aped_Elem_List == elems[i])] = 1.; % reset list to 1 + } + { + case 2: + Aped_Abund_List = (); + Aped_Elem_List = (); + } + { + vmessage("Bad arguments. USAGE: aped_set_abund([elems [,abunds]]);"); + } +} +%- + + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%+ Version w/ radial velocity delta. +% + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%+ +define aped_multi_rv_fit ( xlo, xhi, par ) +{ +% +% PURPOSE: isis user model, APED thermal plasma, multi-temperature, +% cosmic abundances, low density limit, w/ velocity shift + +% xlo, xhi = grid of wavelength bins; +% + + variable ii, % loop counter + y, % return value + ncomps = (length(par)-1) / 2, % # model temperature components + pstate = default_plasma_state(); % plasma model definition + + variable rv = par[0]; % radial velocity, km/s + variable mdl = Struct_Type[ncomps]; + variable norms = par[ [1 : ncomps] ]; % normalizations, 1.e-14*EM/4piD^2 + variable temps=par[ [1+ncomps : 2*ncomps]]; % temperatures, K + + for (ii = 0; ii < ncomps; ii++ ) + { + mdl[ii] = @pstate; + mdl[ii].temperature = temps[ii]; + mdl[ii].norm = norms[ii]; + mdl[ii].redshift = rv / 2.99792458e5; + + if ( __is_initialized( &Aped_Elem_List ) ) % apply different abundances, if set + { + mdl[ii].elem = Aped_Elem_List; + mdl[ii].elem_abund = Aped_Abund_List; + } + + } + + define_model(mdl); % define the model (use list_model; to see). + + switch (Aped_Filter.type) + { + case MODEL_LINES: + if (Aped_Filter.lines == NULL) + y = model_spectrum (xlo, xhi, MODEL_LINES); + else + y = model_spectrum (xlo, xhi, MODEL_LINES, Aped_Filter.lines); + } + { + case MODEL_CONTIN: + y = model_spectrum (xlo, xhi, MODEL_CONTIN); + } + { + case NULL: + y = model_spectrum (xlo, xhi); + } + + return y; + +} +%- + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%+ +define aped_multi_rv_init ( ncomps ) +{ +% Dynamically define a model w/ ncomps temperature components. + + variable i, func_name, T_params, Norm_params, params; + + params = "vrad"; + + for (i=1; i <= ncomps; i++) + params = [params, "norm_"+string(i)]; + + for (i=1; i <= ncomps; i++) + params = [params, "temp_"+string(i)]; + + add_slang_function( "aped_multi_rv", params, [2:ncomps+1] ); + +} +%- + + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%+ + +define aped_multi_rv_setup(Vrad, Temps, Norms) +{ + variable i; + + aped_multi_rv_init( length(Temps) ); + + fit_fun("aped_multi_rv(1)"); + + set_par( 1, Vrad, 0, Vrad-600, Vrad+600); + + for ( i = 0; i < length(Temps); i++) + { + set_par( i+2, Norms[i], 0, 0, 100*Norms[i] ); + set_par( i+length(Temps)+2, Temps[i], 0, 1.e4, 7.95e8 ); + } + +% list_par; +} + +%- + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%+ + +define aped_multi_2rv_setup(Vrads, Temps, Norms1, Norms2) +{ + variable i, ncomps; + + ncomps = length(Temps); + + aped_multi_rv_init( ncomps ); + + fit_fun("aped_multi_rv(1)+aped_multi_rv(2)"); + + set_par( 1, Vrads[0], 0, Vrads[0]-600, Vrads[0]+600); + + for ( i = 0; i < ncomps; i++) + { + set_par( i+2, Norms1[i], 0, 0, 100*Norms1[i] ); + set_par( i+ncomps+2, Temps[i], 0, 1.e4, 7.95e8 ); + } + + + set_par( ncomps*2+2, Vrads[1], 0, Vrads[1]-600, Vrads[1]+600); + + for ( i = 0; i < ncomps; i++) + { + set_par( i+2+2*ncomps+1, Norms2[i], 0, 0, 100*Norms2[i] ); + set_par( i+ncomps+2+2*ncomps+1, Temps[i], 0, 1.e4, 7.95e8 ); + } + +% list_par; +} + +%- + +% added following to this file 2002.05.15... +% +%; File: apec_contin_fit.sl +%; Author: D. Huenemoerder +%; Original version: 2001.10.19 +%;==================================================================== +%; version 3.0 2002.05.15; revise to use model_spectrum's line or +%; contin parameters, and merge into +%; aped_fit_models.sl. +%; +%; version 2.0 2002.03.12; fix regrid -> rebin +% version: 1.0 +%%%%%%%%%%%%%%%%%%%%%%%% +% +% Name: aped_contin_fit( xlo, xhi, par ) +% +% Purpose: define an apec model which computes the apec continuum +% spectrum for 1 temperature component. Does not +% support continuua by ion or for variable abundances +% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% +% Name: fast_aped_contin_fit( xlo, xhi, par ) +% +% Purpose: Use a global continuum model variable for +% a re-normalizable continuum shape model. If the norm is +% frozen, then it is an absolute continuum model. +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% +% Name: fast_aped_contin_init(nhist) +% +% Purpose: Read a continuum model (from a fit) and store into a global +% variable for use by fast_aped_contin_fit(). +% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% +static variable Contin_X_lo, Contin_X_hi, Contin_Value; +% + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +define fast_aped_contin_init (nhist) +{ %+ define + % ASSUMES that a continuum model has been evaluated for histogram + % nhist. This should be called with an MEG histogram, in order to + % provide enough bandpass for both HEG and MEG. + % Resolution is not very important, since it is a continuum. + +% Setup is not done here. First, the equivalent of the following +% should be done: +%% fit_fun("aped_contin(1) + aped_contin(2) + ... + aped_contin(n)"); +%% set_par(...); +%% fit_counts; +%% % etc. +%% Prepare to grab the final continuum array: +%% ignore([lo:hi]); +%% notice(hist); +%% group_data(nhist,0); % undo any grouping or binning +%% rebin_data(nhist,0); +%% eval_flux; % re-evaluate flux, unbinned. + +% Here we get the continuum array and set global variables: + variable y; + y=get_model_flux(nhist); + Contin_Value = y.value; + Contin_X_lo = y.bin_lo; + Contin_X_hi = y.bin_hi; +% +} %- define + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% Now we simply regrid the Contin_Value to the specified grid, +%% allowing a re-normalization: +% +define fast_aped_contin_fit (xlo, xhi, par) +{ %+ define + variable y = + rebin (xlo, xhi, Contin_X_lo, Contin_X_hi, Contin_Value) * par[0]; + return y; +} %- define + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% Define an aped continuum function. +% Proper use of this requires ignoring line features. +% +define aped_contin_fit ( xlo, xhi, par ) +{ %+ define + % xlo, xhi = grid of wavelength bins; + % par[0] = norm; 10^{-14} * VEM/ (4piD^2) + % 10^{-14}~ int{dV n_e n_h} / (4piD^2) + % par[1] = electron temperature [K]; + + variable y; + variable mdl = default_plasma_state(); + + mdl.norm = par[0]; + mdl.temperature = par[1]; + + if ( __is_initialized( &Aped_Elem_List ) ) % apply different abundances, if set + { + mdl.elem = Aped_Elem_List; + mdl.elem_abund = Aped_Abund_List; + } + + define_model(mdl); + y = model_spectrum (xlo, xhi, MODEL_CONTIN); + + return y; + +} %- define + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% Define an aped multi-T continuum function. +% Proper use of this requires ignoring line features. +% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%+ +define aped_multi_contin_init ( ncomps ) +{ +% Dynamically define a continuum model w/ ncomps temperature compents. + + variable i, func_name, T_params, Norm_params, params; + + params = "norm_1"; + + for (i=2; i <= ncomps; i++) + params = [params, sprintf("norm_%d",i)]; + + for (i=1; i <= ncomps; i++) + params = [params, sprintf("temp_%d", i)]; + + add_slang_function( "aped_multi_contin", params, [1:ncomps] ); + +} +%- + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%+ + +define aped_multi_contin_setup(Temps, Norms) +{ + variable i; + + aped_multi_contin_init( length(Temps) ); + + fit_fun("aped_multi_contin(1)"); + + for ( i = 0; i < length(Temps); i++) + { + set_par( i+1, Norms[i], 0, 0, 100*Norms[i] ); + set_par( i+length(Temps)+1, Temps[i], 0, 1.e4, 7.95e8 ); + } + +% list_par; +} + +%- + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%+ +define aped_multi_contin_fit ( xlo, xhi, par ) +{ +% +% PURPOSE: isis user model, APED thermal plasma continuum, multi-temperature, +% cosmic abundances, low density limit. + +% xlo, xhi = grid of wavelength bins; +% + variable ii, % loop counter + y, % return value + ncomps = length(par)/2, % # model components + pstate = default_plasma_state(); % plasma model definition + + variable mdl = Struct_Type[ncomps]; + variable norms=par[ [0:ncomps-1] ]; + variable temps=par[ [ncomps:2*ncomps-1] ]; + + for (ii = 0; ii < ncomps; ii++ ) + { + mdl[ii] = @pstate; + mdl[ii].temperature = temps[ii]; + mdl[ii].norm = norms[ii]; + + if ( __is_initialized( &Aped_Elem_List ) ) % apply different abundances, if set + { + mdl[ii].elem = Aped_Elem_List; + mdl[ii].elem_abund = Aped_Abund_List; + } + + } + + define_model(mdl); % define the model (use list_model; to see). + + y = model_spectrum (xlo, xhi, MODEL_CONTIN); + + return y; +} +%- +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + + +add_slang_function("aped_contin", ["norm","temp"]); +add_slang_function ("fast_aped_contin", ["norm"]); diff --git a/contrib/ascii.sl b/contrib/ascii.sl new file mode 100644 index 0000000..7c1162b --- /dev/null +++ b/contrib/ascii.sl @@ -0,0 +1,116 @@ + +% +% (Note that ISIS already has this functionality built-in) +% + +_debug_info = 1; + +define writecol () +{ + if (_NARGS < 2) + { + _pop_n (_NARGS); + vmessage ("Usage: %s (fp, a, b, ....);", _function_name); + return; + } + variable args = __pop_args (_NARGS - 1); + variable fp = (); + + if (String_Type == typeof (fp)) + { + variable _fp = fopen (fp, "w"); + if (_fp == NULL) + verror ("Unable to open %s", fp); + fp = _fp; + } + + variable fmt = ""; + loop (_NARGS-1) + fmt = strcat ("%S\t", fmt); + fmt = strcat (strtrim (fmt), "\n"); + + variable status = array_map (Int_Type, &fprintf, fp, fmt, __push_args (args)); + if (length (where (status == -1))) + verror ("Error writing to file"); +} + +private define chop (str) +{ + strchop (strcompress(str, "\t "), '\t', 0); +} + +define readcol () +{ + variable fp, cols =NULL; + + switch (_NARGS) + { + case 2: + (fp, cols) = (); + } + { + case 1: + fp = (); + } + { + % default: + + message ("% Usage: (a, b, c, ...) = readcol (fp, [cols] )"); + return; + } + + if (String_Type == typeof (fp)) + { + variable _fp = fopen (fp, "r"); + if (_fp == NULL) + verror ("Unable to open %s", fp); + fp = _fp; + } + + variable lines = fgetslines (fp); + + variable not_a_comment = array_map (Integer_Type, &strncmp, lines, "#", 1); + + lines = lines[where(not_a_comment)]; + variable nlines = length(lines); + + variable ncols; + + if (NULL != cols) + ncols = length(cols); + else + { + ncols = length(chop(lines[0])); + cols = [0:ncols-1]; + } + + variable values = Double_Type [nlines, ncols]; + + variable col, fields, nfields, k, line; + + line = 0; + _for (0, nlines-1, 1) + { + k = (); + + fields = chop (lines[k]); + nfields = length(fields); + + _for (0, ncols-1, 1) + { + col = (); + if (cols[col] >= nfields) + break; + values[line, col] = atof(fields[cols[col]]); + } + + line++; + } + + _for (0, ncols-1, 1) % return as 1-D arrays + { + col = (); + values [[0:line-1], col]; + } +} + diff --git a/contrib/bestfit.sl b/contrib/bestfit.sl new file mode 100644 index 0000000..510efc5 --- /dev/null +++ b/contrib/bestfit.sl @@ -0,0 +1,86 @@ +% bestfit.sl +% Author: John E. Davis +% Purpose: clear specified status bits in an event file. +% +% WARNING: THE EVENT FILE IS MODIFIED IN PLACE. +% If you want to keep the original file +% unmodified, make a copy! +% +% Examples: +% +% 1) To clear the afterglow bits, do: +% +% clear_bits event_file.fits afterglow +% +% 2) To clear streak bits _and_ afterglow bits, do: +% +% clear_bits event_file.fits afterglow streak +% +%-------------------------------------------------------- + +static variable Mask_Bits = Assoc_Type[];% bits +Mask_Bits["badpix"] = 0x3 shl 4; % 4:5 +Mask_Bits["badbias"] = 0x7 shl 6; % 6:8 +Mask_Bits["badoverclock"] = 0x3 shl 9; % 9:10 +Mask_Bits["badcorner"] = 0xf shl 11; % 11:14 +Mask_Bits["streak"] = 0x1 shl 15; % 15 +Mask_Bits["afterglow"] = 0xf shl 16; % 16:19 + +static define pgm_usage () +{ + vmessage ("Usage: clear_bits FILE mask_name [mask_name ...]"); + exit(0); +} + +if (__argc < 3) + pgm_usage (); + +static define clear_status_bits (fp, mask) +{ + variable col, flags, hs; + + () = _fits_get_colnum (fp, "status", &col); + flags = fits_read_col (fp, "status"); + + flags &= ~mask; + + () = _fits_write_col (fp, col, 1, 1, flags); + hs = sprintf ("clear_bits: mask = %x", mask); + () = _fits_write_history (fp, hs); +} + +static define get_mask (args) +{ + variable m, mask = 0; + + foreach (args) + { + m = strlow(); + mask |= Mask_Bits[m]; + } + + return mask; +} + +variable file = __argv[1]; +if (0 == is_substr (file, "[") + and 0 == is_substr (file, "+")) + file += "[1]"; + +variable fp, mask; + +fp = fits_open_file (file, "w"); +mask = get_mask (__argv[[2:]]); + +clear_status_bits (fp, mask); + +fp = 0; % close the file diff --git a/contrib/cspec_summary.sl b/contrib/cspec_summary.sl new file mode 100644 index 0000000..322a848 --- /dev/null +++ b/contrib/cspec_summary.sl @@ -0,0 +1,837 @@ +% Time-stamp: <2001-10-16 14:08:07 dph> +% MIT Directory: ~dph/libisis +% CfA Directory: ~dph/libisis +% File: cspec_summary.sl +% Author: D. Huenemoerder +% Original version: 2001.10.12 +%==================================================================== + +%_debug_info=1; % turn these on to debug. +%_traceback=1; + +% COMMENTARY + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% PROVIDES: +% +% hcspec_summary() : make counts summary spec plot; sum +-1, rebin MEG and/or HEG +% lcspec_summary() : make counts summary spec plot; sum +-1, rebin LEG +% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +% USAGE: + +% (mspec,hspec, mmspec, mhspec)=hcspec_summary( pha_files, outfile[, binfact[, mdl_temps[, mdl_wgts]]]);"); +% pha_files = string array of file names" +% outfile = filename for output ps file. +% binfact = optional rebinning factor, pixels +% (default=0 => no rebinning; HEG is binned by same amount.) +% mdl_temps = optional log10 temperatures of model components (for line labeling) +% mdl_wgts = optional weights of model components. +% Returns meg_counts, meg_model, heg_counts, heg_model + +% (lspec,mlspec)=lcspec_summary( pha_files, outfile[, binfact[, mdl_temps[, mdl_wgts]]]); +% pha_files = string array of file names +% outfile = filename for output ps file. +% binfact = optional rebinning factor, pixels +% (default=0 => no rebinning; HEG is binned by same amount.) +% mdl_temps = optional log10 temperatures of model components (for line labeling). +% mdl_wgts = optional weights of model components. +% Returns leg_counts, leg_model, writes a file. + + + +% EXAMPLES: + +% +% LETG spectrum summary; since it's not an emission line source, no model given. +% +% isis> (sl,ml)=lcspec_summary("Mrk_421/Pha/hrcf01715N001_pha2.fits", "Mrk_421_letgs.ps",12); +% isis> ! gv -noswap -noantialias Tst2_leg.ps # inspect ps file +% +% Plot the result in isis: +% isis> xrange(1.5,20); yrange(0); hplot(sl.bin_lo, sl.bin_hi, sl.value); + +% Sum +-1 for 6 HETG/ACIS-S observations, specify multi-temperature +% model. +% +% isis> fpha1 = "./AR_Lac/Pha/acis"; % root of the file names +% isis> fpha3 = "_pha2.fits"; % suffix of the names +% isis> fpha2 = ["f00007_005N001", % middles of the names +% isis> "f00008_005N001", +% isis> "f00009_003N001", +% isis> "f00010_003N001", +% isis> "f00011_003N001", +% isis> "m00006_004N000"]; +% isis> fphas = fpha1 + fpha2 + fpha3; % concat the strings. +% isis> temps= [6.5,6.8,7.0,7.5,7.8,8.0]; % 6 Temperature model +% isis> wgts= [1.0,2.0,10.0,10.0,5.0,1.0]; % weights 10.e-14 n_e n_H VEM/4piD^2 +% +% isis> plasma(aped); +% isis> (cm,mm,ch,mh)=hcspec_summary(fphas, "ARLac_hetgs_summary.ps",2, temps,wgts); +% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% +% + + +% Subsidiary functions: + +% +% spec_sum_add_hists() Add counts histograms +% pick_el() Given array of line indices return subset +% p_groups() Line label plotting utility +% + +% +% NOTE: lcspec_summary() might work for both LETG/HRC-S and +% LETG/ACIS-S. Hard-wired max wavelength limit might cause a burp. + +% +% RESTRICTIONS: Will not work for pha Type I files, because in this +% case, ISIS assumes that there is no wavelength array. +% +% If you specify a model, the plasma database must +% be loaded (e.g., isis> plasma(aped); ) +% The reason it isn't done by this program is because +% it takes many seconds to load, and would be a +% hindrance to interactive use. +% +% ISIS 0.9.50 or later for default_plasma_state(), +% define_model() functions. + + +% SIDE AFFECTS: Leaves the plot window unselected. +% Scribbles many "failed retrieving info for line" +% messages if a model is specified. These are harmless. +% They occur when some data, which isn't needed here, is +% missing from the plasma database (such as +% spectroscopic line labels). +% +% Writes a postscript file in the current directory. + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + + + +%+ utility functions : + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%+ +define spec_sum_add_hists(spec_nums) + { + variable d, c, ii, xlo, xhi; + + d = get_data_counts(spec_nums[0]); + c = d.value; + xlo = d.bin_lo; + xhi = d.bin_hi; + + for (ii=1; ii 1) + { + result = result[ [1:length(result)-1] ]; % truncate the -1 + } + return result; + } +%- + + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% + line label plotting utility; plot element groups in region; +% colorize, offset +define p_groups (xlo, xhi) + { + variable ii, nbright=50; + + % ISIS pre-defined colors: + % red=2, green=3, blue=4, purple=6, yellow=7, orange=8, grey=15 + % Define some additional colors (done by experiment) : + + variable light_blue=5, bluegreen=10, periwinkle=11, + violet=12, magenta=13, slategray=14; + variable p_elems = [Fe, Ar, O, Si, Mg, Ne, S, Ca, Ni, Al]; + variable p_color = + [green, light_blue, magenta, orange, purple, red, bluegreen, + periwinkle, violet, grey]; + variable p_top = [0.8, 0.75, 0.70, 0.65, 0.60, 0.55, 0.50, 0.45, 0.425, 0.40]; + variable p_bot = p_top - 0.1; + + variable grp = brightest(nbright, where( wl(xlo,xhi) ) ); + variable s = line_label_default_style(); + variable egrp; + + for (ii=0; ii no rebinning; HEG is binned by same amount.)"); + message(" mdl_temps = optional log10 temperatures of model components (for line labeling; defaul=6.8)"); + message(" mdl_wgts = optional weights of model components (default=1)."); + message(" Returns meg_counts, heg_counts, meg_model, heg_model"); + return 1; + } + + binfact = 1; % default - don't rebin. + +% mdl_temps = [6.8]; % default model temperature +% mdl_wgts = [1.0]; + +%+ pop arguments + + switch(_NARGS) + + { + case 5: + mdl_wgts = (); + mdl_temps = (); + binfact = (); + outfile = (); + pha_files = (); + HAVE_MODEL=1; + } + + { + case 4: + mdl_temps = (); + mdl_wgts = mdl_temps-mdl_temps + 1.0; + binfact = (); + outfile = (); + pha_files = (); + HAVE_MODEL=1; + } + + { + case 3: + binfact = (); + outfile = (); + pha_files = (); + HAVE_MODEL=0; + } + + { + case 2: + outfile = (); + pha_files = (); + HAVE_MODEL=0; + } +%- + + +%+ load the data + + if (length(pha_files) == 1) % if only one pha file... + { + pha_files = [pha_files]; % ...force to array. + } + + hists = -1; % initializa variable to dummy value + for (ii=0; ii 0) + { + HAVE_HEG = 1; + for (ii=0; ii 0) + { + HAVE_MEG = 1; + for (ii=0; ii xlo) and (xm2 < xhi))]) * 1.5; + else if (HAVE_HEG) + ymax = max( ch[where( (xh1 > xlo) and (xh2 < xhi))]) * 1.5; + + yrange(ymin,ymax); + + if (HAVE_MEG and HAVE_HEG) + { + hplot( xm1, xm2, cm, 2); + ohplot(xh1, xh2, ch, 3); + } + else if (HAVE_MEG) + { + hplot( xm1, xm2, cm, 2); + } + else if (HAVE_HEG) + { + hplot( xh1, xh2, ch, 2); + } + + if ( (HAVE_HEG or HAVE_MEG) and HAVE_MODEL) p_groups(xlo, xhi); +%- + + if (HAVE_MODEL) + { + %+ make plot of the model: + % + label("Wavelength [Angstroms]", + "Flux [photons/cm^2/s/bin] " + sbinsize, + "Model for " + pha_files[0]+" + ..."); + + if (HAVE_MEG) + ymax = max( fm[where( (xm1 > xlo) and (xm2 < xhi))]) * 1.5; + else if (HAVE_HEG) + ymax = max( fh[where( (xh1 > xlo) and (xh2 < xhi))]) * 1.5; + + yrange(ymin,ymax); + + if (HAVE_MEG and HAVE_HEG) + { + hplot( xm1, xm2, fm, 4); + ohplot(xh1, xh2, fh, 5); + } + else if (HAVE_MEG) + { + hplot( xm1, xm2, fm, 2); + } + else if (HAVE_HEG) + { + hplot( xh1, xh2, fh, 2); + } + + if (HAVE_HEG or HAVE_MEG) p_groups(xlo, xhi); + } + %- + } %- Plot the data: + + close_plot(pid); + + +%+ cleanup this histogram arrays. +% (this is important for interactive sessions, to leave the histograms +% as they were when this started) + + delete_data(hists); +% +%- + +%+ return structures w/ counts and model spectra: + +% counts model +% MEG HEG MEG HEG + variable mspec, hspec, mmspec, mhspec; + + mspec = struct % define structure + { + bin_lo, bin_hi, value + }; + + mmspec=@mspec; % initialize + hspec=@mspec; + mhspec=@mspec; + + if (HAVE_MEG) + { + mspec.bin_lo = xm1; % meg counts + mspec.bin_hi = xm2; + mspec.value = cm; + + if (HAVE_MODEL) + { + mmspec.bin_lo = xm1; + mmspec.bin_hi = xm2; + mmspec.value = fm; + } + } + + if (HAVE_HEG) + { + hspec.bin_lo = xh1; + hspec.bin_hi = xh2; + hspec.value = ch; + + if (HAVE_MODEL) + { + mhspec.bin_lo = xh1; + mhspec.bin_hi = xh2; + mhspec.value = fh; + } + } + + return mspec,mmspec, hspec, mhspec; + +%- + +} + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%+ LETG CASE +% +define lcspec_summary( ) + { %+ define + variable pha_files, outfile, binfact, mdl_temps, mdl_wgts; + variable ii ; % loop counter + variable hists ; % histogram indices array + variable d; % temp data struct + variable LEG=3; % TG_PART mapping + variable HAVE_MODEL=0; + + if (_NARGS < 2) + { + message(""); + message("Purpose: make counts summary spec plot; sum MEG and rebinned HEG"); + message("USAGE: (lspec,mlspec)=lcspec_summary( pha_files, outfile[, binfact[, mdl_temps[, mdl_wgts]]]);"); + message(" pha_files = string array of file names"); + message(" outfile = filename for output ps file."); + message(" binfact = optional rebinning factor, pixels;"); + message(" (default=0 => no rebinning; HEG is binned by same amount.)"); + message(" mdl_temps = optional log10 temperatures of model components (for line labeling; defaul=6.8)"); + message(" mdl_wgts = optional weights of model components (default=1)."); + message(" Returns leg_counts, leg_model"); + return 1; + } + + binfact = 1; % default - don't rebin. + + mdl_temps = [6.8]; % default model temperature + mdl_wgts = [1.0]; + +%+ pop arguments + + switch(_NARGS) + + { + case 5: + mdl_wgts = (); + mdl_temps = (); + binfact = (); + outfile = (); + pha_files = (); + HAVE_MODEL=1; + } + + { + case 4: + mdl_temps = (); + mdl_wgts = mdl_temps-mdl_temps + 1.0; + binfact = (); + outfile = (); + pha_files = (); + HAVE_MODEL=1; + } + + { + case 3: + binfact = (); + outfile = (); + pha_files = (); + HAVE_MODEL=0; + } + + { + case 2: + outfile = (); + pha_files = (); + HAVE_MODEL=0; + } +%- + + +%+ load the data + + if (length(pha_files) == 1) % if only one pha file... + { + pha_files = [pha_files]; % ...force to array. + } + + hists = -1; % initializa variable to dummy value + for (ii=0; ii 0) + { + for (ii=0; ii xlo) and (x2 <= xhi))]) * 1.5; + if (ymax > 0) yrange(ymin,ymax); + hplot( x1, x2, c, 2); + if (HAVE_MODEL) p_groups(xlo, xhi); + } +%- + + if (HAVE_MODEL) + { + %+ make plot of the model: + % + label("Wavelength [Angstroms]", + "Flux [photons/cm^2/s/bin] " + sbinsize, + "Model for " + pha_files[0]+" + ..."); + + if (HAVE_LEG) + { + ymax = max( f[where( (x1 > xlo) and (x2 < xhi))]) * 1.5; + yrange(ymin,ymax); + hplot( x1, x2, f, 4); + p_groups(xlo, xhi); + } + } + %- + } %- Plot the data + + close_plot(pid); + + +%+ cleanup this histogram arrays. +% (this is important for interactive sessions, to leave the histograms +% as they were when this started) + + delete_data(hists); +% +%- + +%+ return structures w/ counts and model spectra: + + variable lspec, mlspec; + + lspec = struct + { + bin_lo, bin_hi, value + }; + + mlspec = @lspec; + + if (HAVE_LEG) % leg counts + { + lspec.bin_lo = x1; + lspec.bin_hi = x2; + lspec.value = c; + + if (HAVE_MODEL) % leg model + { + mlspec.bin_lo = x1; + mlspec.bin_hi = x2; + mlspec.value = f; + } + } + + return lspec,mlspec; + +%- + +} %-define + + diff --git a/contrib/fshift.sl b/contrib/fshift.sl new file mode 100644 index 0000000..0787f87 --- /dev/null +++ b/contrib/fshift.sl @@ -0,0 +1,142 @@ +% Time-stamp: <2001-10-17 11:35:39 dph> +% MIT Directory: ~dph/libisis +% File: fshift.sl +% Author: D. Huenemoerder +% Original version: 2001.07.09 +%==================================================================== +% v.1 + +% shift an array by fractional bin amount, using phase shift in +% Fourier space. +% +% Use fft1d +% Assumes uniform grid. +% Does not worry about integral form of y. Should it? + +% NOTES: +% +% Empirical tests seem to indicate that the Hanning filter isn't +% needed. +% Tests also show that a high-frequency cutoff filter is probably +% needed. A narrow square feature rings for fractional bin shifts. A +% narrow gaussian is OK. + + + +% EXAMPLE use: +% > ()=evalfile("Sl/gsmooth.sl"); +% > ()=evalfile("Sl/hanning.sl"); +% > dpix=22.3; +% > % get your data into arrays... xlo, xhi, counts +% > scounts = fshift(xlo,xhi,counts, dx); +% > plot(xlo,xhi,counts,4); ohplot(xlo, xhi, scounts,2); + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% example test case. +% x1 must be defined. e.g., [0:8191:0.005]+1. % MEG xlo. +% +% evalfile(ilib+"/fshift.sl"); +% d=(sin(x1*PI*2/0.5)+5.) *exp(-x1/10); +% d[[4000:5000:1]]=2.0; +% d[[4500:4510:1]]=10.; +% d[[4100:4120:1]]= exp(-0.5*([4100:4120:1]-4110.)^2/2.^2)*10. + 2.; +% sd=fshift(x1,x2,d,1.3); +% xrange(0,45);hplot(x1,x2,d,4);ohplot(x1,x2,sd,3); +% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +require("hanning"); % window function + +define fshift() +{ + variable xlo, xhi, y, dx, npix; + variable rffty, iffty, cffty, sy, isy, nrm; + variable rfftf, ifftf, cfftf, sf, isf; + + if (_NARGS != 4) + { + message(""); + message("USAGE: shifted_y = fshift(x1, x2, y, dx);"); + message(""); + message("Shift bins of y by amount dx."); + message("METHOD: phase shift FFT, after applying Hanning filter."); + message("RESTRICTIONS: grid must be uniform."); + return 1; + } + +%+ pop arguments: + dx=(); + y=(); + xhi=(); + xlo=(); +%- + +%%+ apply Hanning window (cosine) + variable f; + f = hanning(length(y)); +% y = y*f; +%%- + +%+ determine number of pixels to shift: + npix = dx / (xhi[0]-xlo[0]); +%- + + +%%+ forward fft +% + (rffty, iffty) = fft1d(y, y*0., -1); % fft of data + cffty = rffty + iffty * 1i; % convert to Slang complex types. +%%- + +%%+ apply phase shift + variable phase_shift, freqs; + + % fft defn of frequency array: 1/N == 1 cycle per N bins. + % (N/2)/N == Nyquist; + % + % [DC, 1/N, 2/N..., +-(N/2)/N, ... -3/N, -2/N, -1/N] + + freqs = [0:length(y)/2:1]; % DC to Nyquist + freqs = 2.0*PI/length(y) * [freqs, -[length(y)/2-1:1:-1]]; + phase_shift = freqs*(-npix); + phase_shift = cos(phase_shift) + sin(phase_shift)*1i; + cffty = cffty*phase_shift; +%%- + +%+ reverse fft + (sy, isy) = fft1d(Real(cffty), Imag(cffty), 1); % inverse fft; +%%- + + +% shift filter +%%+ forward fft filter +% + (rfftf, ifftf) = fft1d(f, f*0., -1); % fft of data + cfftf = rfftf + ifftf * 1i; % convert to Slang complex types. +%%- + +%%+ apply phase shift to filter + cfftf = cfftf*phase_shift; +%%- + +%+ reverse fft filter + (sf, isf) = fft1d(Real(cfftf), Imag(cfftf), 1); % inverse fft; +%%- + + + +% + variable lz; % indices of where filter is != 0. + lz = where( sf != 0.0); + nrm = sum(y) / sum(sy[lz]); % ad hoc normalization; should be known a priori + sy = sy * nrm; +% sy[lz] = sy[lz] / sf[lz] ; % remove filter. + + return sy; + +} + + + + + diff --git a/contrib/fspec_summary.sl b/contrib/fspec_summary.sl new file mode 100644 index 0000000..f9a72f7 --- /dev/null +++ b/contrib/fspec_summary.sl @@ -0,0 +1,837 @@ +% Time-stamp: <2001-10-16 14:05:15 dph> +% MIT Directory: ~dph/libisis +% CfA Directory: ~dph/libisis +% File: fspec_summary.sl +% Author: D. Huenemoerder +% Original version: 2001.10.12 +%==================================================================== + +%_debug_info=1; % turn these on to debug. +%_traceback=1; + +% COMMENTARY + +% PURPOSE +% Make a summary plot of a spectrum from a pha II file. +% Plots photon flux vs wavelength to postscript file. +% If a model was specified, mark line positions. +% + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% PROVIDES: +% +% hfspec_summary() : make flux summary spec plot; +-1, rebin MEG and/or HEG +% lfspec_summary() : make flux summary spec plot; +-1, rebin LEG +% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +% USAGE: + +% (mspec,mmspec, hspec,mhspec)=hfspec_summary( pha_file, order, outfile, harf, marf[, binfact[, mdl_temps[, mdl_wgts]]]);"); +% pha_file = file name" +% order = diffraction order (tg_m); integer; e.g., -1 +% outfile = filename for output ps file. +% binfact = optional rebinning factor, pixels +% (default=0 => no rebinning; HEG is binned by same amount.) +% harf = HEG arf filename corresponding to the order. +% marf = MEG arf filename corresponding to the order. +% mdl_temps = optional log10 temperatures of model components (for line labeling) +% mdl_wgts = optional weights of model components. +% Returns meg_flux, meg_model, heg_flux, heg_model + +% (lspec,mlspec)=lfspec_summary( pha_file, order, outfile, arf[, binfact[, mdl_temps[, mdl_wgts]]]); +% pha_file = file name +% order = diffraction order (tg_m); integer; only -1 or +1 for LETG/HRC-S +% outfile = filename for output ps file. +% arf = filename for arf corresponding to the order. +% binfact = optional rebinning factor, pixels +% (default=0 => no rebinning; HEG is binned by same amount.) +% mdl_temps = optional log10 temperatures of model components (for line labeling). +% mdl_wgts = optional weights of model components. +% Returns leg_flux, leg_model, writes a postscript file. + + + +% EXAMPLES: + +% +% LETG spectrum summary; since it's not an emission line source, no model given. +% +% isis> (sl,ml)=lfspec_summary("Mrk_421/Pha/hrcf01715N001_pha2.fits", +% isis> -1, "Mrk_421_letgs.ps", Arf/hrcf01715_002N001LEG_-1_garf.fits,12); +% isis> ! gv -noswap -noantialias Tst2_leg.ps # inspect ps file +% +% Plot the result in isis: +% isis> xrange(1.5,20); yrange(0); hplot(sl.bin_lo, sl.bin_hi, sl.value); + +% +1 for HETG/ACIS-S observation, specify multi-temperature model. +% +% isis> fpha1 = "./AR_Lac/Pha/acism00006_004N000_pha2.fits"; % file name +% isis> temps= [6.5,6.8,7.0,7.5,7.8,8.0]; % 6 Temperature model +% isis> wgts= [1.0,2.0,10.0,10.0,5.0,1.0]; % weights 10.e-14 n_e n_H VEM/4piD^2 +% isis> harf= "acism00006_004N000HEG_1_garf.fits" +% isis> marf= "acism00006_004N000MEG_1_garf.fits" +% +% isis> plasma(aped); +% isis> (cm,mm,ch,mh)=hfspec_summary(fpha, 1, "ARLac_hetgs_summary.ps",harf,marf, 2, temps,wgts); +% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% +% + + +% Subsidiary functions: + +% +% pick_el() Given array of line indices return subset +% p_groups() Line label plotting utility +% + +% +% NOTE: lfspec_summary() might work for both LETG/HRC-S and +% LETG/ACIS-S. Hard-wired max wavelength limit might cause a burp. + +% +% RESTRICTIONS: Will not work for pha Type I files, because in this +% case, ISIS assumes that there is no wavelength array. +% +% If you specify a model, the plasma database must +% be loaded (e.g., isis> plasma(aped); ) +% The reason it isn't done by this program is because +% it takes many seconds to load, and would be a +% hindrance to interactive use. +% +% ISIS 0.9.50 or later for default_plasma_state(), +% define_model() functions. + + +% SIDE AFFECTS: Leaves the plot window unselected. +% Scribbles many "failed retrieving info for line" +% messages if a model is specified. These are harmless. +% They occur when some data, which isn't needed here, is +% missing from the plasma database (such as +% spectroscopic line labels). +% +% Writes a postscript file in the current directory. + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + + + +%+ utility functions : + +%%%%%%%%%%%%%%%%%%% pick ion from an index array %%%%%%%%%%%%%%%%%%%%%% +%+ +define pick_el() + { + % given array of line indices, a, return the subset of the array + % which are lines of element, el, and ion, ion. + % example: + % a = brightest(30, where(wl(10,12))); % brightest in a region + % a_Fe = pick_el(a,Fe); % pick the iron lines in the list + % If there aren't any, returns the array, [-1] + + variable a, ion, el; + + switch (_NARGS) + + { + case 3: + ion = (); + el = (); + a = (); + } + + { + case 2: + el = (); + a = (); + ion = NULL; + } + + { + message("USAGE: g = pick_el(array, elem[, ion]);"); + } + + variable ii, s, n = length(a); + variable result = -1; % dummy value + + for (ii=0; ii 1) + { + result = result[ [1:length(result)-1] ]; % truncate the -1 + } + return result; + } +%- + + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% + line label plotting utility; plot element groups in region; +% colorize, offset +define p_groups (xlo, xhi) + { + variable ii, nbright=50; + + % ISIS pre-defined colors: + % red=2, green=3, blue=4, purple=6, yellow=7, orange=8, grey=15 + % Define some additional colors (done by experiment) : + + variable light_blue=5, bluegreen=10, periwinkle=11, + violet=12, magenta=13, slategray=14; + variable p_elems = [Fe, Ar, O, Si, Mg, Ne, S, Ca, Ni, Al]; + variable p_color = + [green, light_blue, magenta, orange, purple, red, bluegreen, + periwinkle, violet, grey]; + variable p_top = [0.8, 0.75, 0.70, 0.65, 0.60, 0.55, 0.50, 0.45, 0.425, 0.40]; + variable p_bot = p_top - 0.1; + + variable grp = brightest(nbright, where( wl(xlo,xhi) ) ); + variable s = line_label_default_style(); + variable egrp; + + for (ii=0; ii no rebinning; HEG is binned by same amount.)"); + message(" mdl_temps = optional log10 temperatures of model components (for line labeling; defaul=6.8)"); + message(" mdl_wgts = optional weights of model components (default=1)."); + message(" Returns meg_flux, meg_model, heg_flux, heg_model"); + return 1; + } + + binfact = 1; % default - don't rebin. + +%+ pop arguments + + switch(_NARGS) + + { + case 8: + mdl_wgts = (); + mdl_temps = (); + binfact = (); + marf = (); + harf = (); + outfile = (); + order = (); + pha_file = (); + HAVE_MODEL=1; + } + + { + case 7: + mdl_temps = (); + mdl_wgts = mdl_temps-mdl_temps + 1.0; + binfact = (); + marf = (); + harf = (); + outfile = (); + order = (); + pha_file = (); + HAVE_MODEL=1; + } + + { + case 6: + binfact = (); + marf = (); + harf = (); + outfile = (); + order = (); + pha_file = (); + HAVE_MODEL=0; + } + + { + case 5: + marf = (); + harf = (); + outfile = (); + order = (); + pha_file = (); + HAVE_MODEL=0; + } +%- + + +%+ load the data + + hists = load_data(pha_file); + variable n_harf = load_arf(harf); + variable n_marf = load_arf(marf); + variable hists_info = get_data_info(hists); % get info on histograms. + +%- + +%+ find order; rebin + + variable h_idx; + variable xm1, xm2, cm, HAVE_MEG=0; % histogram bin coordinates and counts for MEG... + variable xh1, xh2, ch, HAVE_HEG=0; % ... and HEG. + + plot_bin_density; + + % find the HEG order from the histogram lists: + % + h_idx = where( (hists_info.part == HEG) and (hists_info.order == order) ); + h_idx=h_idx[0] ; % better be scalar! + if (length(h_idx) > 0) + { + HAVE_HEG = 1; + variable heg_idx = hists[h_idx]; + assign_arf(n_harf, heg_idx); + group_data(heg_idx, binfact); % rebin + flux_corr(heg_idx); + variable hfspec = get_data_flux(heg_idx); + xh1 = hfspec.bin_lo; + xh2 = hfspec.bin_hi; + ch = hfspec.value / (xh2-xh1); + } + + + % find the MEG 1st orders from the histogram lists: + % + h_idx = where( (hists_info.part == MEG) and (hists_info.order == order) ); + h_idx=h_idx[0] ; % better be scalar! + if (length(h_idx) > 0) + { + HAVE_MEG = 1; + variable meg_idx = hists[h_idx]; + assign_arf(n_marf, meg_idx); + group_data(meg_idx, binfact); % rebin + flux_corr(meg_idx); + variable mfspec = get_data_flux(meg_idx); + xm1 = mfspec.bin_lo; + xm2 = mfspec.bin_hi; + cm = mfspec.value / (xm2-xm1); + } + +%- + + if (_isis_version < 950) + { + message("ISIS version does not support type of model. Continuing without."); + HAVE_MODEL=0; % unset it. + } + if (HAVE_MODEL) + { %+ have model + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + % + %+ Construct model + % the following is for isis version 0.9.50 and higher only. + % for prev, need to load model from a table. + + mdl_temps = 10.0^mdl_temps; + variable mdl = Struct_Type[length(mdl_temps)]; + variable pstate = default_plasma_state(); + + % plasma(aped); % do externally? (it takes time to load) + + for (ii=0; ii xlo) and (xm2 < xhi))]) * 1.5; + else if (HAVE_HEG) + ymax = max( ch[where( (xh1 > xlo) and (xh2 < xhi))]) * 1.5; + + yrange(ymin,ymax); + + if (HAVE_MEG and HAVE_HEG) + { + plot_data_flux(heg_idx,2); + oplot_data_flux(meg_idx,3); + } + else if (HAVE_MEG) + { + plot_data_flux(meg_idx); + } + else if (HAVE_HEG) + { + plot_data_flux(heg_idx); + } + + if ( (HAVE_HEG or HAVE_MEG) and HAVE_MODEL) p_groups(xlo, xhi); +%- + + if (HAVE_MODEL) + { + %+ make plot of the model: + % + label("Wavelength [Angstroms]", + "Flux [photons/cm^2/s/A] " + sbinsize, + "Model for " + pha_file); + + if (HAVE_MEG) + ymax = max( fm[where( (xm1 > xlo) and (xm2 < xhi))]) * 1.5 /(xm2[0]-xm1[0]); + else if (HAVE_HEG) + ymax = max( fh[where( (xh1 > xlo) and (xh2 < xhi))]) * 1.5/(xh2[0]-xh1[0]); + + yrange(ymin,ymax); + + if (HAVE_MEG and HAVE_HEG) + { + hplot(xh1,xh2,fh,4); + ohplot(xm1,xm2,fm,5); + } + else if (HAVE_MEG) + { + hplot(xm1,xm2,fm,2); + } + else if (HAVE_HEG) + { + hplot(xh1,xh2,2); + } + + if (HAVE_HEG or HAVE_MEG) p_groups(xlo, xhi); + } + %- + } %- Plot the data: + + close_plot(pid); + + +%+ cleanup this histogram arrays. +% (this is important for interactive sessions, to leave the histograms +% as they were when this started) + + delete_data(hists); + delete_arf(n_marf); + delete_arf(n_harf); +% +%- + +%+ return structures w/ flux and model spectra: + +% flux model +% MEG HEG MEG HEG + variable mspec, hspec, mmspec, mhspec; + + mspec = struct % define structure + { + bin_lo, bin_hi, value + }; + + mmspec=@mspec; % initialize + hspec=@mspec; + mhspec=@mspec; + + if (HAVE_MEG) + { + mspec.bin_lo = xm1; % meg flux + mspec.bin_hi = xm2; + mspec.value = cm; + + if (HAVE_MODEL) + { + mmspec.bin_lo = xm1; + mmspec.bin_hi = xm2; + mmspec.value = fm; + } + } + + if (HAVE_HEG) + { + hspec.bin_lo = xh1; + hspec.bin_hi = xh2; + hspec.value = ch; + + if (HAVE_MODEL) + { + mhspec.bin_lo = xh1; + mhspec.bin_hi = xh2; + mhspec.value = fh; + } + } + + return mspec,mmspec, hspec, mhspec; + +%- + +} + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + + +% +define lfspec_summary( ) +{ %+define + variable pha_file, order, outfile, larf, binfact, mdl_temps, mdl_wgts; + variable ii ; % loop counter + variable hists ; % histogram indices array + variable d; % temp data struct + variable LEG=3; % TG_PART mapping + variable HAVE_MODEL=0; + + if (_NARGS < 4) + { + message(""); + message("Purpose: make flux summary spec plot; rebinned LEG"); + message("USAGE: (mspec,mmspec, hspec, mhspec, mhspec)=hfspec_summary( pha_file, order, outfile, harf, marf[, binfact[, mdl_temps[, mdl_wgts]]]);"); + message(" pha_file = file name"); + message(" order = diffraction order (tg_m); integer; -1 or +1 for LEG"); + message(" outfile = filename for output ps file."); + message(" larf = LEG arf filename corresponding to the order."); + message(" binfact = optional rebinning factor, pixels;"); + message(" (default=0 => no rebinning; HEG is binned by same amount.)"); + message(" mdl_temps = optional log10 temperatures of model components (for line labeling; defaul=6.8)"); + message(" mdl_wgts = optional weights of model components (default=1)."); + message(" Returns leg_flux, leg_model"); + return 1; + } + + binfact = 1; % default - don't rebin. + +%+ pop arguments + + switch(_NARGS) + + { + case 7: + mdl_wgts = (); + mdl_temps = (); + binfact = (); + larf = (); + outfile = (); + order = (); + pha_file = (); + HAVE_MODEL=1; + } + + { + case 6: + mdl_temps = (); + mdl_wgts = mdl_temps-mdl_temps + 1.0; + binfact = (); + larf = (); + outfile = (); + order = (); + pha_file = (); + HAVE_MODEL=1; + } + + { + case 5: + binfact = (); + larf = (); + outfile = (); + order = (); + pha_file = (); + HAVE_MODEL=0; + } + + { + case 4: + larf = (); + outfile = (); + order = (); + pha_file = (); + HAVE_MODEL=0; + } +%- + + +%+ load the data + + hists = load_data(pha_file); + variable n_larf = load_arf(larf); + variable hists_info = get_data_info(hists); % get info on histograms. + +%- + +%+ find order; rebin + + variable h_idx; + variable x1, x2, c, HAVE_LEG=0; % histogram bin coordinates and counts for LEG... + + plot_bin_density; + + % find the LEG order from the histogram lists: + % + h_idx = where( (hists_info.part == LEG) and (hists_info.order == order) ); + h_idx=h_idx[0] ; % better be scalar! + if (length(h_idx) > 0) + { + HAVE_LEG = 1; + variable leg_idx = hists[h_idx]; + assign_arf(n_larf, leg_idx); + group_data(leg_idx, binfact); % rebin + flux_corr(leg_idx); + variable lfspec = get_data_flux(leg_idx); + x1 = lfspec.bin_lo; + x2 = lfspec.bin_hi; + c = lfspec.value / (x2-x1); + } + +%- + + if (_isis_version < 950) + { + message("ISIS version does not support type of model. Continuing without."); + HAVE_MODEL=0; % unset it. + } + if (HAVE_MODEL) + { %+ have model + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + % + %+ Construct model + % the following is for isis version 0.9.50 and higher only. + % for prev, need to load model from a table. + + mdl_temps = 10.0^mdl_temps; + variable mdl = Struct_Type[length(mdl_temps)]; + variable pstate = default_plasma_state(); + + % plasma(aped); % do externally? (it takes time to load) + + for (ii=0; ii xlo) and (x2 < xhi))]) * 1.5; + if (ymax > 0) yrange(ymin,ymax); + plot_data_flux(leg_idx,2); + if (HAVE_MODEL) p_groups(xlo, xhi); + } +%- + + if (HAVE_MODEL and HAVE_LEG) + { + %+ make plot of the model: + % + label("Wavelength [Angstroms]", + "Flux [photons/cm^2/s/A] " + sbinsize, + "Model for " + pha_file); + + ymax = max( f[where( (x1 > xlo) and (x2 < xhi))]) * 1.5 /(x2[0]-x1[0]); + yrange(ymin,ymax); + hplot(x1,x2,f,4); + p_groups(xlo, xhi); + } + %- + } %- Plot the data: + + close_plot(pid); + + +%+ cleanup this histogram arrays. +% (this is important for interactive sessions, to leave the histograms +% as they were when this started) + + delete_data(hists); + delete_arf(n_larf); +% +%- + +%+ return structures w/ flux and model spectra: + +% flux model +% MEG HEG MEG HEG + variable lspec, mlspec; + + lspec = struct % define structure + { + bin_lo, bin_hi, value + }; + + mlspec=@lspec; % initialize + + if (HAVE_LEG) + { + lspec.bin_lo = x1; % leg flux + lspec.bin_hi = x2; + lspec.value = c; + + if (HAVE_MODEL) + { + mlspec.bin_lo = x1; + mlspec.bin_hi = x2; + mlspec.value = f; + } + } + + + return lspec,mlspec; +} +%- + diff --git a/contrib/gsmooth.sl b/contrib/gsmooth.sl new file mode 100644 index 0000000..b619bd4 --- /dev/null +++ b/contrib/gsmooth.sl @@ -0,0 +1,156 @@ +% Time-stamp: <2002-05-20 23:23:37 dph> +% MIT Directory: ~dph/libisis +% File: gsmooth.sl +% Author: D. Huenemoerder +% Original version: 2000.10.29 +%==================================================================== +% 2000.10.29 dph +% v.1 +% 2001.07.07 +% v.2 ------ apply hanning filter; re-align on input x array. +% NOTE: v.2 changed interface! +% v.2.1 fixed problem w/ shifting - had freq array wrong... +% v.2.2 fixed bug w/ odd-length arrays. + + +% gaussian smoothing +% +% convolve y by gaussian kernel, width sigma, in x's units +% Use fft1d +% Assumes uniform grid. +% Does not worry about integral form of y. Should it? + +% EXAMPLE use: +% > ()=evalfile("Sl/hanning.sl"); +% > ()=evalfile("Sl/gsmooth.sl"); +% > sigma=0.004; % approx HEG resolution +% > % get your data into arrays... xlo, xhi, counts +% > scounts=gsmooth(xlo, xhi, counts, sigma); +% > plot(xlo,xhi,counts,4); ohplot(xlo, xhi, scounts,2); + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% example test case. +% x1 must be defined. e.g., [0:8191:0.005]+1. % MEG xlo. +% +% evalfile(ilib+"/hanning.sl"); +% evalfile(ilib+"/gsmooth.sl"); +% d=(sin(x1*PI*2/0.5)+5.) *exp(-x1/10); +% d[[4000:5000:1]]=2.0; +% d[4500]=10.; +% sd=gsmooth(x1,x2,d,0.008); +% xrange(0,45);hplot(x1,x2,d,4);ohplot(sx1,sx2,sd,3); +% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +require("hanning"); + +define gsmooth() +{ + variable xlo, xhi, y, sigma; + + variable k, karray, dx, nsig; + variable nkbins; + variable rffty, iffty, rfftk, ifftk, cffty, cfftk, c, sy, isy, nrm; + variable xlo_out, xhi_out; + variable ymean; + + if (_NARGS != 4) + { + message(""); + message("USAGE: smoothed_y = gsmooth(x_lo, x_hi, y, sigma)"); + message(""); + message("Apply gaussian smoothing filter of width sigma to histogram array y."); + message(" x_lo, x_hi are histogram bin edge coordinate arrays."); + message(" y is histogram values array (x_lo,x_hi,y must have same lengths"); + message("METHOD: Convolution is performed via FFT, after applying Hanning filter."); + message("RESTRICTIONS: grid must be uniform."); + return 1; + } + +%+ pop arguments: + sigma=(); + y=(); + xhi=(); + xlo=(); +%- + + % make kernel + dx = xhi[0]-xlo[0]; + nsig = sigma/dx; % # bins in sigma. + nkbins = int(4.*nsig)+1; % # bins to use in the gaussian kernel; +-2sigma. + k=exp( -([0:nkbins-1:1]-nkbins/2.)^2/ nsig^2/2.) / (sqrt(2.*PI)*nsig); % eval kernel + +%+ + % if arrays have odd # points, make even; discard at end: + variable is_odd = 0; + variable n = length(y); + if (n mod 2) is_odd = 1; + if (is_odd) + { + y = [y,0]; + xlo = [xlo, xlo[n-1]+dx ]; + xhi = [xhi, xhi[n-1]+dx ]; + } +%- + +% make array of kernel, same length as y: +% + karray = y*0.0; + karray[ [0:nkbins-1:1] ] = k; + +%%+ apply Hanning window (cosine) + variable f; + f = hanning( length(y) ); + y = y*f; +%%- + +%%+ forward fft +% + (rffty, iffty) = fft1d(y, y*0., -1); % fft of data + (rfftk, ifftk) = fft1d(karray, karray*0., -1); % fft of kernel + + cffty = rffty + iffty * 1i; % convert to Slang complex types. + cfftk = rfftk + ifftk * 1i; + + c = cffty * cfftk ; % convolve: fft product. +%%- + +%%+ apply phase shift of half-kernel width in order to return +% +% smoothed array on same x array as input: +% shift by nkbins/2 +% + variable phase_shift, freqs; + + % fft defn of frequency array: 1/N == 1 cycle per N bins. + % (N/2)/N == Nyquist; + % + % [DC, 1/N, 2/N..., +-(N/2)/N, ... -3/N, -2/N, -1/N] + + freqs = [0:length(y)/2:1]; % DC to Nyquist + freqs = 2.0*PI/length(y) * [freqs, -[length(y)/2-1:1:-1]]; + + phase_shift = freqs*(nkbins/2.); + phase_shift = cos(phase_shift) + sin(phase_shift)*1i; + c = c*phase_shift; +%%- + +%+ reverse fft + (sy, isy) = fft1d(Real(c), Imag(c), 1); % inverse fft; +%%- + + +% + variable lz; % indices of where filter is != 0. + lz = where( f != 0.0); + nrm = sum(y) / sum(sy[lz]); % ad hoc normalization; should be known a priori + sy = sy * nrm; + sy[lz] = sy[lz] / f[lz] ; % remove filter. + + if (is_odd) % truncate 1 bin padding... + sy = sy[[0:n-1]]; + + return sy; + +} +provide("gsmooth"); diff --git a/contrib/hanning.sl b/contrib/hanning.sl new file mode 100644 index 0000000..5a265b6 --- /dev/null +++ b/contrib/hanning.sl @@ -0,0 +1,35 @@ +% Time-stamp: <2001-10-17 11:36:49 dph> +% MIT Directory: ~dph/libisis +% File: hanning.sl +% Author: D. Huenemoerder +% Original version: 2000.10.29 +%==================================================================== +% +% the Hanning window is: 1/2 * (1 - cos(2*PI*i/(N-1))), i=0..N-1 +% +define hanning(length) +{ + variable result; + + result = 0.5 * (1.0 - cos( 2*PI/(length-1) * [0:length-1:1]) ); + + return result; + +} + +% modified hanning - ramp up to 1.0 quicker. +% n_end is number <= length/2. +% length is length of array +% +define mhanning(n_end, length) +{ + variable f1, result; + + f1=hanning(n_end*2); + result = [0:length-1:1]*0.0 + 1.0; + result[ [0:n_end-1:1] ] = f1[ [0:n_end-1:1] ]; + result[ [length-n_end:length-1:1] ] = f1[ [n_end:n_end*2-1:1] ]; + + return result; +} +provide ("hanning"); diff --git a/contrib/marxflux b/contrib/marxflux new file mode 100755 index 0000000..d8539b4 --- /dev/null +++ b/contrib/marxflux @@ -0,0 +1,125 @@ +#! /usr/bin/env isis-script + +%-------------------------------------------------------- +% Program: marxflux +% Author: John Davis +% Purpose: Generate an input spectrum for MARX +% (see http://space.mit.edu/CXC/MARX) +% +% Note: Save this script in a file called +% 'marxflux' and make it executable: +% chmod +x marxflux +% +% *** ISIS must be on your command search path. *** +% +% Example: +% +% marxflux powerlaw.p flux.dat '12.3984/[1.0:40:0.005]' +% ==> a grid from 1A to 40A in steps of 0.005A +% (note the single quotes!) +% +%-------------------------------------------------------- + +static variable Pgm_Name = path_basename (__argv[0]); +static define usage () +{ + () = fprintf (stderr, "Usage: %s [-l script] isis-par-file output-file [energy-grid-expr]\n", Pgm_Name); + () = fprintf (stderr, "\n"); + () = fprintf (stderr, " The isis-par-file may be created using save_par in isis.\n"); + () = fprintf (stderr, " The optional script may define the model if needed.\n"); + () = fprintf (stderr, " If the energy grid is not specified, '[0.03:10:0.001]' will be used.\n"); + () = fprintf (stderr, "\nExample:\n"); + () = fprintf (stderr, "%s powerlaw.p flux.dat '12.3984/[1.0:40:0.005]'\n", Pgm_Name); + () = fprintf (stderr, " ==> a grid from 1A to 40A in steps of 0.005A (note also the single quotes!)\n"); + exit (1); +} + + +static variable Par_File, Output_File, Script_File = NULL; +static variable Energy_Grid = NULL; + +switch (__argc) +{ + case 6: + if (__argv[1] != "-l") + usage (); + Script_File = __argv[2]; + Par_File = __argv[3]; + Output_File = __argv[4]; + Energy_Grid = __argv[5]; +} +{ + case 5: + if (__argv[1] != "-l") + usage (); + Script_File = __argv[2]; + Par_File = __argv[3]; + Output_File = __argv[4]; +} +{ + case 4: + Par_File = __argv[1]; + Output_File = __argv[2]; + Energy_Grid = __argv[3]; +} +{ + case 3: + Par_File = __argv[1]; + Output_File = __argv[2]; +} +{ + % default + usage (); +} + +variable Const_keV_A = 12.3984185734; +if (Energy_Grid == NULL) + Energy_Grid = [0.1:10.0:0.001]; +else + Energy_Grid = eval (Energy_Grid); + +if (Script_File != NULL) + () = evalfile (Script_File); + +static define write_ascii (file, x, y) +{ + variable fp = fopen (file, "w"); + if (fp == NULL) + { + () = fprintf (stderr, "Unable to open %s: %s\n", file, errno_string (errno)); + exit (1); + } + variable status = array_map (Int_Type, &fprintf, fp, "%S\t%S\n", x, y); + if ((length (where (status == -1))) + or (-1 == fclose (fp))) + { + () = fprintf (stderr, "%s: write error: %s", file, errno_string (errno)); + exit (1); + } +} + +static define _A () +{ + variable n = _NARGS; + loop (n) + { + variable e = (); + reverse (Const_keV_A / e); + _stk_roll (n); + } + _stk_reverse (n); +} + +require ("xspec"); +load_par (Par_File); + +static variable lo = Energy_Grid [array_sort (Energy_Grid)]; +static variable hi = @lo; + +hi[[0:length(hi)-2]] = lo[[1:]]; +hi[-1] = lo[-1] + 0.001; + +static variable s = reverse (eval_fun (_A(lo, hi)))/(hi - lo); + +write_ascii (Output_File, lo, s); +exit (0); diff --git a/contrib/max_like.sl b/contrib/max_like.sl new file mode 100644 index 0000000..8f71a5d --- /dev/null +++ b/contrib/max_like.sl @@ -0,0 +1,50 @@ +% Maximum-Likelihood fit-statistic + +static variable Log_Factorial = Double_Type [100]; +static define setup_factorial () +{ + variable x = 1.0; + Log_Factorial[0] = 0; + _for (1, 99, 1) + { + variable i = (); + x = x * i; + Log_Factorial[i] = log(x); + } +} + +setup_factorial (); +define log_factorial (n) +{ + variable x = Double_Type [length(n)]; + variable i = where (n < 100); + x[i] = Log_Factorial[n[i]]; + i = where (n >= 100); + n = n[i]; + x[i] = n * log(n) - n; + return x; +} + + +static define like_ml_function (y, fx, w, npars) +{ + variable i = where (fx > 0); + y = y[i]; + fx = fx[i]; + + y = typecast (y+0.5, Int_Type); + + y = -sum (y * log(fx) - fx - log_factorial(y)); + + return y; +} + +static define like_ml_report (stat, npts, nvpars) +{ + variable s = sprintf (" Likelihood = %0.4g\n", exp(-stat/npts)); + return s; +} + +add_slang_statistic ("like", &like_ml_function, &like_ml_report); +set_fit_statistic ("like"); + diff --git a/contrib/monte.sl b/contrib/monte.sl new file mode 100644 index 0000000..38eb9ea --- /dev/null +++ b/contrib/monte.sl @@ -0,0 +1,117 @@ + +% Purpose: +% Carry out a Monte-Carlo search of the fit-function +% parameter space to find a good set of starting parameters. +% +% Notes: +% A Monte-Carlo search may be helpful when examining +% a complex chi-square space such as that associated +% with the pileup model. +% +% Each variable fit-parameter should be constrained +% to lie within some reasonable min/max range. +% If the allowed range is unconstrained, the Monte-Carlo +% search will sample parameter values over the entire +% range of representable double-precision numbers. +% +% Usage: +% +% e.g. to carry out 100 random trials with 'eval_counts': +% monte_carlo (100, &eval_counts); +% + +_debug_info = 1; +_traceback=1; + +private define get_params () +{ + variable i, n = get_num_pars (); + variable p = Struct_Type [n]; + + for (i = 1; i <= n; i++) + { + p[i-1] = get_par_info (i); + } + + return p; +} + +private define set_params (p) +{ + variable i, n = get_num_pars (); + + for (i = 0; i < n; i++) + { + set_par (i+1, p[i].value, p[i].freeze, p[i].min, p[i].max); + } +} + +private define linear_random (mn, mx) +{ + return mn + (mx - mn) * urand(); +} + +private define select_at_random (mn, mx) +{ + return linear_random (mn, mx); +} + +private define random_params (p) +{ + variable i, n = get_num_pars (); + + for (i = 0; i < n; i++) + { + if (p[i].freeze == 0 and p[i].tie == 0) + { + p[i].value = select_at_random (p[i].min, p[i].max); + } + } + + return p; +} + +private define test_params (p, evalfun) +{ + variable info; + + set_params (p); + () = @evalfun (&info); + + return info.statistic; +} + +public define monte_carlo (num, evalfun) +{ + variable bkp_verbose = Fit_Verbose; + Fit_Verbose = -1; + + variable p, best_p, stat, best_stat; + + p = get_params (); + best_stat = test_params (p, evalfun); + best_p = get_params (); + + variable i = 0; + + loop (num) + { + if (bkp_verbose >= 0 and Isis_Batch_Mode == 0) + () = fprintf (stderr, "monte_carlo: %3d/%3d\tbest=%7.3f\r", + i, num, best_stat); + + stat = test_params (random_params (p), evalfun); + + if (stat < best_stat) + { + best_stat = stat; + best_p = get_params (); + } + + i++; + } + + set_params (best_p); + + Fit_Verbose = bkp_verbose; +} diff --git a/contrib/pick_el.sl b/contrib/pick_el.sl new file mode 100644 index 0000000..16b6bc2 --- /dev/null +++ b/contrib/pick_el.sl @@ -0,0 +1,76 @@ +% Time-stamp: <2001-10-17 11:38:16 dph> +% MIT Directory: ~dph/libisis +% File: pick_el.sl +% Author: D. Huenemoerder +% Original version: 2001.10.12 +% +%%%%%%%%%%%%%%%%%%% pick ion from an index array %%%%%%%%%%%%%%%%%%%%%% +%+ +define pick_el() + { + % given array of line indices, a, return the subset of the array + % which are lines of element, el, and ion, ion. + % example: + % a = brightest(30, where(wl(6,7))); % brightest in a region + % a_Al = pick_el(a,Al); % pick the iron lines in the list + % If there aren't any, returns the array, [-1] + + % Note: this is different from: + % a = brightest(30, where( wl(6,7) and el_ion(Al) ) ); + % which returns the 30 brightest set from only Al. This would + % find any Al lines in the region, but they may not be among the + % brightest 30 features. + + variable a, ion, el; + + switch (_NARGS) + + { + case 3: + ion = (); + el = (); + a = (); + } + + { + case 2: + el = (); + a = (); + ion = NULL; + } + + { + message("USAGE: g = pick_el(array, elem[, ion]);"); + } + + variable ii, s, n = length(a); + variable result = -1; % dummy value + + for (ii=0; ii 1) + { + result = result[ [1:length(result)-1] ]; % truncate the -1 + } + return result; + } +%- diff --git a/contrib/splot_data.sl b/contrib/splot_data.sl new file mode 100644 index 0000000..b447568 --- /dev/null +++ b/contrib/splot_data.sl @@ -0,0 +1,180 @@ +%; Time-stamp: <2002-02-27 11:48:41 dph> +%; MIT Directory: ~dph/libisis +%; File: splot_data.sl +%; Author: D. Huenemoerder +%; Original version: 2001.10.26 +%;==================================================================== +% version: 0.1 +% +% purpose: smooth histogram via convolution w/ gaussian before plotting. +% +% History: +% 2002.05.29 jch minimize duplicate code, support auto-color + +require("gsmooth"); +provide("splot_data_counts"); +provide("osplot_data_counts"); +provide("splot_data_flux"); +provide("osplot_data_flux"); + +provide("splot_model_counts"); +provide("osplot_model_counts"); +provide("splot_model_flux"); +provide("osplot_model_flux"); + +provide("shplot"); +provide("oshplot"); + +% generic get-args and plot functions +private define get_splot_args (nargs, msg) +{ + variable id, sigma, color; + + switch (nargs) + { + case 2: + (id, sigma) = (); + color = NULL; + } + { + case 3: + (id, sigma, color) = (); + } + { + % default: + usage (msg); + } + + return (id, sigma, color); +} + +private define do_shplot (plot_ref, xlo, xhi, y, sigma, color) +{ + variable s = gsmooth (xlo, xhi, y, sigma); + + if (color != NULL) + @plot_ref (xlo, xhi, s, color); + else + @plot_ref (xlo, xhi, s); +} + +private define do_splot (id, sigma, color, get_ref, plot_ref) +{ + variable v = @get_ref (id); + do_shplot (plot_ref, v.bin_lo, v.bin_hi, v.value, sigma, color); +} + +% plot/oplot for data/model and counts/flux cases +define splot_data_counts () +{ + variable id, sigma, color; + variable msg = "splot_data_counts (id, sigma [, color])"; + + (id, sigma, color) = get_splot_args (_NARGS, msg); + do_splot (id, sigma, color, &get_data_counts, &hplot); +} + +define osplot_data_counts () +{ + variable id, sigma, color; + variable msg = "osplot_data_counts (id, sigma [, color])"; + + (id, sigma, color) = get_splot_args (_NARGS, msg); + do_splot (id, sigma, color, &get_data_counts, &ohplot); +} + +define splot_data_flux () +{ + variable id, sigma, color; + variable msg = "splot_data_flux (id, sigma [, color])"; + + (id, sigma, color) = get_splot_args (_NARGS, msg); + do_splot (id, sigma, color, &get_data_flux, &hplot); +} + +define osplot_data_flux () +{ + variable id, sigma, color; + variable msg = "osplot_data_flux (id, sigma [, color])"; + + (id, sigma, color) = get_splot_args (_NARGS, msg); + do_splot (id, sigma, color, &get_data_flux, &ohplot); +} + +define splot_model_counts () +{ + variable id, sigma, color; + variable msg = "splot_model_counts (id, sigma [, color])"; + + (id, sigma, color) = get_splot_args (_NARGS, msg); + do_splot (id, sigma, color, &get_model_counts, &hplot); +} + +define osplot_model_counts () +{ + variable id, sigma, color; + variable msg = "osplot_model_counts (id, sigma [, color])"; + + (id, sigma, color) = get_splot_args (_NARGS, msg); + do_splot (id, sigma, color, &get_model_counts, &ohplot); +} + +define splot_model_flux () +{ + variable id, sigma, color; + variable msg = "splot_model_flux (id, sigma [, color])"; + + (id, sigma, color) = get_splot_args (_NARGS, msg); + do_splot (id, sigma, color, &get_model_flux, &hplot); +} + +define osplot_model_flux () +{ + variable id, sigma, color; + variable msg = "osplot_model_flux (id, sigma [, color])"; + + (id, sigma, color) = get_splot_args (_NARGS, msg); + do_splot (id, sigma, color, &get_model_flux, &ohplot); +} + +% generic get-args +private define get_shplot_args (nargs, msg) +{ + variable xlo, xhi, y, sigma, color; + + switch (nargs) + { + case 4: + (xlo, xhi, y, sigma) = (); + color = NULL; + } + { + case 5: + (xlo, xhi, y, sigma, color) = (); + } + { + % default: + usage (msg); + } + + return (xlo, xhi, y, sigma, color); +} + +define shplot () +{ + variable xlo, xhi, y, sigma, color; + variable msg = "shplot( xlo, xhi, y, sigma[, color])"; + + (xlo, xhi, y, sigma, color) = get_shplot_args (_NARGS, msg); + do_shplot (&hplot, xlo, xhi, y, sigma, color); +} + +define oshplot () +{ + variable xlo, xhi, y, sigma, color; + variable msg = "oshplot( xlo, xhi, y, sigma[, color])"; + + (xlo, xhi, y, sigma, color) = get_shplot_args (_NARGS, msg); + do_shplot (&ohplot, xlo, xhi, y, sigma, color); +} + diff --git a/doc/Makefile b/doc/Makefile new file mode 100644 index 0000000..3a7681a --- /dev/null +++ b/doc/Makefile @@ -0,0 +1,80 @@ + +.PHONY: all postscript patch_index ascii figs pdffigs pdf tpdf clean veryclean world + +DOC = manual + +all: $(DOC).tex + make ascii postscript + +world: $(DOC).tex + make veryclean + make tpdf + make clean + make postscript + make clean + make ascii + +TOC=\\begin{theindex}\\label{chap:index}\\ifpdf\\pdfbookmark[-1]{Index}{chap:index}\\fi + +patch_index: + sed -e 's/\\begin{theindex}/$(TOC)/' $(DOC).ind > tmp.ind + mv -f tmp.ind $(DOC).ind + +postscript: $(DOC).tex + pdftops $(DOC).pdf + +old-postscript: $(DOC).tex + latex -output-format=dvi $(DOC).tex + latex -output-format=dvi $(DOC).tex + makeindex $(DOC).idx + make patch_index + latex -output-format=dvi $(DOC).tex + latex -output-format=dvi $(DOC).tex + dvips -o $(DOC).ps $(DOC) + +ascii: $(DOC).tex + jed -batch -l ./extract_help.sl + +scripts = contin.sl crude_dem.sl custom1.sl data.sl elev.sl \ + ion_curves.sl line_id.sl profile_fit.sl xspec.sl \ + residuals.sl contour.sl + +figs: + -mkdir figures + cd figures; for s in $(scripts) ; do \ + echo "Doing $$s"; ../../bin/$(ARCH)/isis --batch ../scripts/$$s; \ + done + +fignames = contin data_flx line_id crude_dem elev profile_fit \ + custom1 ion_bal residuals data_cts ion_frac xspec contour + +pdffigs: + cd figures; for s in $(fignames) ; do \ + ps2epsi $$s.ps ; epstopdf $$s.epsi ;\ + done + +pdf: + pdflatex $(DOC) + pdflatex $(DOC) + makeindex $(DOC).idx + make patch_index + pdflatex $(DOC) + pdflatex $(DOC) + +tpdf: $(DOC).pdf + thumbpdf $(DOC) + pdflatex $(DOC) + +$(DOC).pdf: + make pdf + +clean: + rm -f $(DOC).aux $(DOC).dvi $(DOC).idx $(DOC).ilg $(DOC).out \ + $(DOC).ind $(DOC).lof $(DOC).log $(DOC).lot $(DOC).toc \ + $(DOC).tpt thumb*.??? index.log + +veryclean: + make clean + rm -f $(DOC).ps $(DOC).pdf help.txt + + diff --git a/doc/extract_help.sl b/doc/extract_help.sl new file mode 100644 index 0000000..34bc7ab --- /dev/null +++ b/doc/extract_help.sl @@ -0,0 +1,319 @@ +% -*- mode: SLang; mode: fold -*- + +% Usage: jed -batch -l extract_help.sl + +CASE_SEARCH=1; +_debug_info = 1; +_traceback = 1; + +typedef struct +{ + beg, end +} +Region_Type; + +typedef struct +{ + name, purpose, usage, seealso, description +} +Entry_Fields; + +static define find_region (entry) %{{{ +{ + !if (bol_fsearch (entry.beg)) + return 0; + + push_mark (); + + !if (bol_fsearch (entry.end)) + return 0; + + go_down_1(); + + return 1; +} + +%}}} + +static define strip_bol_comments (sym) %{{{ +{ + bob(); + while (not(eobp())) + { + if (0 == bol_fsearch (sym)) + break; + del_eol(); + } + bob(); +} + +%}}} + +static define regex_replace (old, new) %{{{ +{ + bob (); + + forever + { + !if (re_fsearch (old)) + break; + !if (replace_match (new, 1)) + break; + } + + bob(); +} + +%}}} + +static define indent_buffer () %{{{ +{ + eob (); + variable num = what_line(); + bob (); + + loop (num) + { + insert_spaces (4); + go_down_1(); + } +} + +%}}} + +static define reflow_paragraphs () %{{{ +{ + bob(); + WRAP=65; + while (not(eobp())) + { + skip_chars ("\t \n"); + call ("format_paragraph"); + forward_paragraph (); + } + bob(); +} + +%}}} + +static define filter_text () %{{{ +{ + check_region (0); + narrow (); + bob(); + + replace ("\\isisx", "ISIS"); + replace ("\\slang", "S-Lang"); + replace ("\\cfitsio", "CFITSIO"); + replace ("\\pgplot", "PGPLOT"); + replace ("\\xspec", "XSPEC"); + replace ("\\HRMA", "HRMA"); + replace ("\\verb", ""); + replace ("\\left", ""); + replace ("\\right", ""); + replace ("\\leq", "<="); + replace ("\\times", " x "); + replace ("\\ldots", "..."); + replace ("\\tt", ""); + replace ("\\sc", ""); + replace ("\\bf", ""); + replace ("\\it", ""); + replace ("\\rm", ""); + replace ("|", ""); + replace ("$", ""); + replace ("~", ""); + replace ("{", ""); + replace ("}", ""); + replace ("``", "\""); + replace ("''", "\""); + replace ("\\AA", "A"); + replace ("\\S", "*section*"); + replace ("\\", ""); + + strip_bol_comments ("%"); + + reflow_paragraphs (); + + widen (); +} + +%}}} + +static define massage_value () %{{{ +{ + variable cbuf = whatbuf (); + check_region (0); + narrow (); + + setbuf ("tmp"); + erase_buffer (); + insbuf (cbuf); + + bob(); + + replace ("\\vspace*{\\baselineskip}", ""); + regex_replace ("\\\\index{[-0-9a-zA-Z _?\\\\]*[!@|]?[-0-9a-zA-Z (){},_?\\\\]*}", ""); + regex_replace ("\\\\ref{[-0-9a-zA-Z_:]*}", ""); + + while (not(eobp())) + { + push_mark (); + if (0 == bol_fsearch ("\\begin")) + { + eob(); + filter_text(); + break; + } + del_eol(); + insert_char ('\n'); + + filter_text(); + + () = bol_fsearch ("\\end"); + del_eol(); + } + + indent_buffer(); + trim_buffer(); + + bob (); + push_mark (); + eob (); + variable s = bufsubstr (); + + setbuf (cbuf); + widen (); + + return s; +} + +%}}} + +static define get_massaged_text (entry) %{{{ +{ + go_down_1(); + if (looking_at (entry.end)) + return ""; + + push_mark (); + () = bol_fsearch (entry.end); + go_up_1(); + + return massage_value (); +} + +%}}} + +static define get_delim_value () %{{{ +{ + bol (); + go_down_1 (); + + !if (fsearch_char ('{')) + return ""; + + push_mark (); + + if (1 != find_matching_delimiter ('{')) + { + pop_mark (1); + return ""; + } + + variable value = bufsubstr(); + pop_mark (0); + + if (value == NULL) + return ""; + + value = str_replace_all (value, "\\sc ", ""); + value = str_replace_all (value, "\\tt ", ""); + value = str_replace_all (value, "\\isisx", "ISIS"); + value = str_replace_all (value, "{", ""); + value = str_replace_all (value, "}", ""); + value = str_replace_all (value, "$", ""); + value = str_replace_all (value, "~", ""); + value = str_replace_all (value, "\\", ""); + + return strtrim (value); +} + +%}}} + +static define parse_region (entry) %{{{ +{ + bob(); + !if (looking_at (entry.beg)) + return; + + variable f = @Entry_Fields; + + f.name = get_delim_value (); + f.purpose = get_delim_value (); + f.usage = get_delim_value (); + f.seealso = get_delim_value (); + f.description = get_massaged_text (entry); + + return f; +} + +%}}} + +static define insert_fields (f, buf) %{{{ +{ + variable cbuf = whatbuf(); + setbuf (buf); + insert (sprintf ("%s\n\n SYNOPSIS\n %s\n\n USAGE\n %s\n\n", + f.name, + f.purpose, + f.usage)); + insert (sprintf (" DESCRIPTION\n%s\n\n", f.description)); + insert (sprintf (" SEE ALSO\n %s\n\n", f.seealso)); + insert ("------------------------------------------------------------------------\n"); + setbuf (cbuf); +} + +%}}} + +static define parse_file (entry, buf) %{{{ +{ + variable f; + + forever + { + !if (find_region (entry)) + return; + + check_region (0); + narrow (); + f = parse_region (entry); + insert_fields (f, buf); + widen (); + } +} + +%}}} + +variable Syn = "whatever"; +create_syntax_table (Syn); +define_syntax ("{", "}", '(', Syn); + +static define extract_help (entry, infile, outfile) %{{{ +{ + () = read_file (infile); + use_syntax_table (Syn); + + parse_file (entry, outfile); + setbuf (outfile); + write_buffer (outfile); +} + +%}}} + +variable entry = @Region_Type; +entry.beg = "\\begin{isisfunction}"; +entry.end = "\\end{isisfunction}"; + +extract_help (entry, "manual.tex", "help.txt"); + +exit_jed (0); diff --git a/doc/guide.sty b/doc/guide.sty new file mode 100644 index 0000000..fd55dba --- /dev/null +++ b/doc/guide.sty @@ -0,0 +1,198 @@ +% +% +% +\setcounter{tocdepth}{3} +\setcounter{secnumdepth}{3} +\oddsidemargin 0.5in +\evensidemargin 0.25in +\marginparwidth 0.25in +\topmargin .25in +\headheight 15pt % Height of box containing running head. +\footskip 29.5pt +\textheight = 41\baselineskip +\textwidth 5.75in +% +\def\@chapapp{Section} +\def\publisher#1{\gdef\@publisher{#1}} +\def\shorttitle#1{\gdef\@shorttitle{#1}} +\def\versionnumber#1{\gdef\@versionnumber{#1}} +\def\printingnumber#1{\gdef\@printingnumber{#1}} +\def\printingdate#1{\gdef\@printingdate{#1}} +\def\officename#1{\gdef\@officename{#1}} +% +\def\appendix{\par + \addtocontents{toc}{\protect\addvspace{13pt}} + \addtocontents{toc}{\protect\contentsline {chapter} + {\protect\Large \protect\bf Appendixes}{}} + \addtocontents{toc}{\protect\addvspace{5pt}} + \setcounter{chapter}{0} + \setcounter{section}{0} + \def\@chapapp{Appendix} + \def\thechapter{\Alph{chapter}}} +% +\def\startguide{\setcounter{page}{0}\pagenumbering{arabic}} + +% LIST OF FIGURES and LIST OF TABLES +\def\listoffigures{\@restonecolfalse\if@twocolumn\@restonecoltrue\onecolumn + \fi\section*{List of Figures\@mkboth + {List of Figures}{List of Figures}}\@starttoc{lof}\if@restonecol + \twocolumn\fi} +\def\l@figure{\@dottedtocline{1}{1.5em}{2.3em}} +\def\listoftables{\@restonecolfalse\if@twocolumn\@restonecoltrue\onecolumn + \fi\section*{List of Tables\@mkboth + {List of Tables}{List of Tables}}\@starttoc{lot}\if@restonecol + \twocolumn\fi} +\let\l@table\l@figure +% +\def\maketitle{\begin{titlepage} + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%%%% Not used now but kept for other possible use %%%%% +% +% \let\footnotesize\small % Local definitions to make \thanks produce +% \let\footnoterule\relax % \normalsize footnotes with no separating rule. +% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + + \setcounter{page}{0} + \null + \vfil + \vskip 10pt +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%\makebox[0pt][l]{\rule[ 18pt]{17pt}{1pt}\rule[ 17pt]{17pt}{3pt}% +%\rule[ 16pt]{17pt}{5pt}}% +%\makebox[0pt][l]{\rule[ 10pt]{17pt}{1pt}\rule[ 9pt]{17pt}{3pt}% +%\rule[ 8pt]{17pt}{5pt}}% +%\makebox[0pt][l]{\rule[ 0pt]{17pt}{1pt}\rule[ -1pt]{17pt}{3pt}% +%\rule[ -2pt]{17pt}{5pt}}% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%\hspace{60pt} {\Huge ADF \par} +% \begin{small} +% {\sf \@officename \par} +% \end{small} + \vskip 40pt % To adjust centering. + \begin{center} + {\LARGE \@title \par} % Set title in \LARGE size. + \vskip 3em % Vertical space after title. + {\large % Set author in \large size. + \lineskip .6em + \begin{tabular}[t]{c}\@author + \end{tabular}\par} + \vskip 1em % Vertical space after author. + {\large \@versionnumber \par} % Set standard number in \large size. + \vskip 30pt % To adjust centering. + {\large \@date \par} % Set date in \large size. + \vskip 1em + \vskip 30pt % To adjust centering. + {\large \@printingnumber \par} % Set printing number in \large size. + \vskip 30pt % To adjust centering. + {\large \@printingdate \par} % Set printing date in \large size. + \vskip 30pt % To adjust centering. +\end{center} \par +\vskip 6em \par +\begin{center} +\begin{tabular}[t]{l}\@publisher +\end{tabular} +\end{center}\par +\@thanks +\vfil +\null +\end{titlepage} +\setcounter{footnote}{0} % Footnotes start at zero again. +\let\thanks\relax +\gdef\@publisher{}\gdef\@versionnumber{} +\gdef\@printingnumber{}\gdef\@printingdate{} +\gdef\@thanks{}\gdef\@author{}\gdef\@title{}\let\maketitle\relax} +% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% fancyheadings.sty version 1.0 % +% Fancy headers and footers. % +% Piet van Oostrum, Dept of Computer Science, University of Utrecht % +% Padualaan 14, P.O. Box 80.089, 3508 TB Utrecht, The Netherlands % +% Telephone: +31-30-531806. piet@cs.ruu.nl (mcvax!hp4nl!ruuinf!piet) % +% March, 1989. % +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +\def\lhead{\@ifnextchar[{\@xlhead}{\@ylhead}} +\def\@xlhead[#1]#2{\gdef\@elhead{#1}\gdef\@olhead{#2}} +\def\@ylhead#1{\gdef\@elhead{#1}\gdef\@olhead{#1}} +\def\chead{\@ifnextchar[{\@xchead}{\@ychead}} +\def\@xchead[#1]#2{\gdef\@echead{#1}\gdef\@ochead{#2}} +\def\@ychead#1{\gdef\@echead{#1}\gdef\@ochead{#1}} +\def\rhead{\@ifnextchar[{\@xrhead}{\@yrhead}} +\def\@xrhead[#1]#2{\gdef\@erhead{#1}\gdef\@orhead{#2}} +\def\@yrhead#1{\gdef\@erhead{#1}\gdef\@orhead{#1}} +\def\lfoot{\@ifnextchar[{\@xlfoot}{\@ylfoot}} +\def\@xlfoot[#1]#2{\gdef\@elfoot{#1}\gdef\@olfoot{#2}} +\def\@ylfoot#1{\gdef\@elfoot{#1}\gdef\@olfoot{#1}} +\def\cfoot{\@ifnextchar[{\@xcfoot}{\@ycfoot}} +\def\@xcfoot[#1]#2{\gdef\@ecfoot{#1}\gdef\@ocfoot{#2}} +\def\@ycfoot#1{\gdef\@ecfoot{#1}\gdef\@ocfoot{#1}} +\def\rfoot{\@ifnextchar[{\@xrfoot}{\@yrfoot}} +\def\@xrfoot[#1]#2{\gdef\@erfoot{#1}\gdef\@orfoot{#2}} +\def\@yrfoot#1{\gdef\@erfoot{#1}\gdef\@orfoot{#1}} +\newdimen\headrulewidth +\newdimen\footrulewidth +\newdimen\plainheadrulewidth +\newdimen\plainfootrulewidth +\newdimen\headwidth +\newif\if@fancyplain \@fancyplainfalse +\def\fancyplain#1#2{\if@fancyplain#1\else#2\fi} +\lhead[\fancyplain{}{\sl\rightmark}]{\fancyplain{}{\sl\leftmark}} +\chead{} +\rhead[\fancyplain{}{\sl\leftmark}]{\fancyplain{}{\sl\rightmark}} +\lfoot{} +\cfoot{\rm\thepage} % page number +\rfoot{} +\def\@fancyhead#1#2#3#4#5{#1\hbox to\headwidth{\vbox{\hbox +{\rlap{\parbox[b]{\headwidth}{\raggedright#2\strut}}\hfill +\parbox[b]{\headwidth}{\centering#3\strut}\hfill +\llap{\parbox[b]{\headwidth}{\raggedleft#4\strut}}}\headrule}}#5} +\def\@fancyfoot#1#2#3#4#5{#1\hbox to\headwidth{\vbox{\footrule +\hbox{\rlap{\parbox[t]{\headwidth}{\raggedright#2\strut}}\hfill +\parbox[t]{\headwidth}{\centering#3\strut}\hfill +\llap{\parbox[t]{\headwidth}{\raggedleft#4\strut}}}}}#5} +\def\headrule{{\if@fancyplain\headrulewidth\plainheadrulewidth\fi +\hrule\@height\headrulewidth\@width\headwidth \vskip-\headrulewidth}} +\def\footrule{{\if@fancyplain\footrulewidth\plainfootrulewidth\fi +\vskip-0.3\normalbaselineskip\vskip-\footrulewidth +\hrule\@width\headwidth\@height\footrulewidth\vskip0.3\normalbaselineskip}} +\def\ps@fancy{ +\let\@mkboth\markboth +\@ifundefined{chapter}{\def\sectionmark##1{\markboth +{\uppercase{\ifnum \c@secnumdepth>\z@ + \thesection\hskip 1em\relax \fi ##1}}{}} +\def\subsectionmark##1{\markright {\ifnum \c@secnumdepth >\@ne + \thesubsection\hskip 1em\relax \fi ##1}}} +{\def\chaptermark##1{\markboth {\uppercase{\ifnum \c@secnumdepth>\m@ne + \@chapapp\ \thechapter. \ \fi ##1}}{}} +\def\sectionmark##1{\markright{\uppercase{\ifnum \c@secnumdepth >\z@ + \thesection. \ \fi ##1}}}} +\def\@oddhead{\@fancyhead\relax\@olhead\@ochead\@orhead\hss} +\def\@oddfoot{\@fancyfoot\relax\@olfoot\@ocfoot\@orfoot\hss} +\def\@evenhead{\@fancyhead\hss\@elhead\@echead\@erhead\relax} +\def\@evenfoot{\@fancyfoot\hss\@elfoot\@ecfoot\@erfoot\relax} +\headwidth\textwidth} +\def\ps@fancyplain{\ps@fancy \let\ps@plain\ps@plain@fancy} +\def\ps@plain@fancy{\@fancyplaintrue\ps@fancy} +% +\headrulewidth 0.4pt +\footrulewidth 0.4pt +\plainheadrulewidth 0.4pt +\plainfootrulewidth 0.4pt +\addtolength{\headwidth}{\marginparsep} +\addtolength{\headwidth}{\marginparwidth} +\renewcommand{\chaptermark}[1]{\markboth{#1}{#1}} % remember chapter title +\renewcommand{\sectionmark}[1]{\markright{\thesection\ #1}} % section number and title +\lhead[\fancyplain{\bf\thepage}{\bf\thepage}] +{\fancyplain{\bf\rightmark}{\bf\rightmark}} +\chead{} +\rhead[\fancyplain{\bf\leftmark}{\bf\leftmark}] +{\fancyplain{\bf\thepage}{\bf\thepage}} +\lfoot[\fancyplain{\footnotesize \@officename} +{\footnotesize \@officename}]{\fancyplain{}{}} +\cfoot{} +\rfoot[\fancyplain{}{}]{\fancyplain{\footnotesize \@shorttitle} +{\footnotesize \@shorttitle}} +% +\pagestyle{fancyplain} +\pagenumbering{roman} diff --git a/doc/isis.1 b/doc/isis.1 new file mode 100644 index 0000000..ad5324a --- /dev/null +++ b/doc/isis.1 @@ -0,0 +1,87 @@ +.\" Hey, EMACS: -*- nroff -*- +.\" ISIS +.\" 1 +.\" +.TH ISIS 1 "March 30, 2003" MIT/CSR "ISIS Reference Manual" +.\" +.\" +.\" Some roff macros, for reference: +.\" .nh disable hyphenation +.\" .hy enable hyphenation +.\" .ad l left justify +.\" .ad b justify to both left and right margins +.\" .nf disable filling +.\" .fi enable filling +.\" .br insert line break +.\" .sp insert n+1 empty lines +.\" for manpage-specific macros, see man(7) +.SH NAME +ISIS \- Interactive Spectral Interpretation System +.SH SYNOPSIS +.B isis +[options] [FILE [args....]] +.SH DESCRIPTION +This manual page briefly documents the command-line options +recognized by +.B ISIS. +.B ISIS +is a scriptable, interactive S-Lang based system +designed for X-ray spectral analysis. For detailed +documentation, see the +.B ISIS +Reference Manual. +.PP +.\" TeX users may be more comfortable with the \fB\fP and +.\" \fI\fP escape sequences to invode bold face and italics, +.\" respectively. +.SH OPTIONS +This program follows the usual GNU command line syntax, with long +options starting with two dashes (`-'). +A summary of options is included below. +For a complete description, see the manual. +.TP +.B \-\-batch FILE +Process the S-Lang script FILE +in batch mode, returning to the Unix prompt on completion. +.TP +.B \-g +Compile S-Lang scripts with debugging information +.TP +.B \-\-help +Show summary of options. +.TP +.B \-i FILE +Load FILE at startup instead of $HOME/.isisrc +.TP +.B \-l FILE +Direct all output messages to FILE +.TP +.B \-n +Do not load $HOME/.isisrc at startup +.TP +.B \- | \-\-stdin +Take input from stdin; this is useful mainly for running +.B ISIS +from within an pseudo-terminal such as an emacs shell window. +.TP +.B \-q n +Set verbosity (n < 0 means quieter). +.TP +.B \-v +Show verbose loading messages +.TP +.B \-\-version +Show the +.B ISIS +version number. + +.SH BUGS +None that I know of. Please notify the author if you find any. + +.SH SEE ALSO +pgplot(3), +S-Lang, +cfitsio + +.SH AUTHOR +John Houck is the author of ISIS. diff --git a/doc/local_help.txt b/doc/local_help.txt new file mode 100644 index 0000000..5b5ba5b --- /dev/null +++ b/doc/local_help.txt @@ -0,0 +1,16 @@ +local_function_template + + SYNOPSIS + One sentence summary of this function's purpose + + USAGE + A sample function invocation, including optional arguments + + DESCRIPTION + More detailed discussion of what the function does and how + to use it, perhaps with a few usage examples. + + SEE ALSO + List of other related functions + +------------------------------------------------------------------------ diff --git a/doc/manual.tex b/doc/manual.tex new file mode 100644 index 0000000..c881fcb --- /dev/null +++ b/doc/manual.tex @@ -0,0 +1,13969 @@ +% +% $Id: manual.tex,v 1.356 2004/09/09 11:31:48 houck Exp $ +% +% ISIS Technical Manual +% +% Author: John C. Houck +% +% Last Revised: $Date: 2004/09/09 11:31:48 $ +% + +\documentclass{book} +\usepackage{guide} +\usepackage{amsmath} +\usepackage{makeidx} +\usepackage{verbatim} +\usepackage{tocbibind} +%\usepackage{html} + +\sloppy + +%begin{latexonly} +\newif\ifpdf +\ifx\pdfoutput\undefined + \pdffalse % we are not running pdflatex +\else + \pdfoutput=1 % we are running pdflatex + \pdftrue +\fi +%end{latexonly} + +%begin{latexonly} +\ifpdf + \usepackage{thumbpdf} + \usepackage{graphicx} + \usepackage[pdftex=true,bookmarks=true,hyperindex=true,plainpages=false]{hyperref} + %\newcommand{\putfig}[1]{\pdfximage{#1.pdf}} + \newcommand{\putfig}[1]{\includegraphics{#1.pdf}} + \pdfstringdefDisableCommands{\let\textsubscript\relax} + % >>> hyperref should be last included package +\else + \usepackage{epsf} + \usepackage{epsfig} + \newcommand{\putfig}[1]{\psfig{file=#1.ps}} +\fi +%end{latexonly} + +% Set margins and separation spaces + +\oddsidemargin=0.50in +\evensidemargin=0.00in +\baselineskip=12pt +\textwidth=5.75in + +%begin{latexonly} +\ifpdf + \topmargin=-0.25in +\else + \topmargin=0.5in +\fi +%end{latexonly} + +\textheight=8.75in +\topsep=2pt +\setlength{\parindent}{0 cm} +\setlength{\parskip}{\baselineskip} +\renewcommand{\baselinestretch}{0.95} + +% Add special commands + +\newcommand{\putdraft}{\special{!userdict begin /bop-hook{gsave 200 30 +translate 65 rotate /Times-Roman findfont 216 scalefont setfont 0 0 +moveto 0.9 setgray (DRAFT) show grestore}def end}} +\newcommand{\gtrsim}{\ ^{\displaystyle >}_{\displaystyle \sim}\ } +\newcommand{\lesssim}{\ ^{\displaystyle <}_{\displaystyle \sim}\ } +\newcommand{\st}{\rule[-2mm]{0mm}{6mm}} +\newcommand{\stt}{\rule[-3mm]{0mm}{8mm}} + +\newcommand{\D}{{\rm d}} + +\newcommand{\isisweb}{{\tt http://space.mit.edu/cxc/isis}} + +\newcommand{\HRMA}{{\sc HRMA}} +\newcommand{\isisx}{{\sc ISIS~}} +\newcommand{\isis}{{\sc ISIS}} +\newcommand{\isisversion}{1.0} +\newcommand{\cfitsio}{{\sc CFITSIO}} +\newcommand{\pgplot}{{\sc PGPLOT}} +\newcommand{\slang}{{\sc S-Lang}} +\newcommand{\xspec}{{\sc XSPEC}} + +% Environment for ISIS function descriptions + +%begin{latexonly} +\newenvironment{isisfunction}[4]% +{\index{{#1}@{\tt #1}}% + \ifpdf + % no pdf contents line + \else + \addcontentsline{toc}{subsection}{{#1} -- {#2}} + \fi + \vbox{ + \vspace*{\baselineskip} + {\LARGE\tt #1}\vspace*{\baselineskip}\\ + {{\it Purpose:}~~{#2}}\\ + {{\it Usage:}~~{\tt #3}}\\ + {{\it See Also:}~~{\tt #4}} + } +}% +{ } +%end{latexonly} + +% \begin{htmlonly} +% \newenvironment{isisfunction}[4]{{#1}\\{#2}\\{#3}\\{#4}\\}{ }% +% \end{htmlonly} + +% Create an index +\makeindex + +% Set title page information +\author{John C. Houck\\ + {\normalsize WWW: \isisweb} \\ + {\normalsize Mailing List: isis-users@space.mit.edu} \\ \\ \\ \\} + +\officename{Chandra X-Ray Observatory Center / MIT Center for Space Research} + +\shorttitle{ISIS \isisversion\ Technical Manual ~~$\cdot$~~ Revision 1.0} + +\title{\huge \isisx \isisversion \\ Technical Manual} + +\versionnumber{Revision 1.0} + +\date{\today} + +\printingnumber{} + +\printingdate{} + +\publisher{ {\large {\bf Chandra X-Ray Observatory Center}} \\ + MIT Center for Space Research \\ + One Hampshire St. \\ + Building NE80 \\ + Cambridge, MA 02139--4307 \\ + USA} + +% Add a background DRAFT to document if desired +%\putdraft + +\begin{document} + +%begin{latexonly} +\ifpdf +\DeclareGraphicsExtensions{.pdf} +\fi +%end{latexonly} + +\maketitle +\begin{titlepage} +\vspace*{7.6cm} +\vfill +\end{titlepage} + +\setcounter{page}{0} +\pagenumbering{roman} + +\newpage +\null\vspace*{3cm} +\begin{quote} +This document is part of ISIS, the Interactive Spectral Interpretation System \\ +Copyright (C) 1998-2008 Massachusetts Institute of Technology + +This software was developed by the MIT Center for Space Research under +contract SV1-61010 from the Smithsonian Institution. + +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., 675 Mass Ave, Cambridge, MA 02139, USA. +\end{quote} + +% Top Level Overview + +%\newpage +%\cleardoublepage +\setcounter{page}{0} +\pagenumbering{roman} + +\chapter*{Overview\markboth{}{Overview}} +\addcontentsline{toc}{chapter}{\numberline{}Overview} +\label{list:overview} +%begin{latexonly} +\ifpdf + \pdfbookmark[-1]{Overview}{list:overview} +\fi +%end{latexonly} + +{\Large + +{\bf Part~\ref{part:intro}: Introduction to ISIS \dotfill \pageref{part:intro}} + +\begin{quotation} +\normalsize +{\bf Section~\ref{chap:intro}: ISIS in Context \dotfill \pageref{chap:intro}} + +{\bf Section~\ref{chap:quick}: Quick Start \dotfill \pageref{chap:quick}} + +{\bf Section~\ref{chap:prog}: Programming ISIS \dotfill \pageref{chap:prog}} + +{\bf Section~\ref{chap:common-tasks}: Common ISIS Tasks \dotfill \pageref{chap:common-tasks}} + +\end{quotation} + +{\bf Part~\ref{part:refman}: ISIS Reference Manual \dotfill \pageref{part:refman}} + +\begin{quotation} +\normalsize +{\bf Section~\ref{chap:specdb}: The Spectroscopy Database \dotfill \pageref{chap:specdb}} + +{\bf Section~\ref{chap:interactive}: Interactive Mode Features \dotfill \pageref{chap:interactive}} + +{\bf Section~\ref{chap:funcref}: ISIS Function Reference \dotfill \pageref{chap:funcref}} + +{\bf Section~\ref{chap:xspec-module}: The XSPEC Module \dotfill \pageref{chap:xspec-module}} + +{\bf Section~\ref{chap:custom}: Customizing ISIS Configuration \dotfill \pageref{chap:custom}} + +\end{quotation} + +{\bf Index \dotfill \pageref{chap:index}} + +} + +% +% Set up table of contents +% +\newpage +\tableofcontents + +% +% Create a list of figures +% +\newpage +\listoffigures + +% +% Create a list of tables +% +\newpage +\listoftables + +% +% Preface +% +\newpage +\cleardoublepage +\chapter*{Preface\markboth{}{Preface}} +\addcontentsline{toc}{chapter}{\numberline{}Preface} + +%\begin{flushleft} + +This manual describes \isis, the MIT/CXC {\bf I}nteractive {\bf +S}pectral {\bf I}nterpretation {\bf S}ystem which is designed to +facilitate interpretation and analysis of high resolution X-ray +spectra. It is being developed as programmable, interactive tool +for studying the physics of X-ray spectrum formation, supporting +measurement and identification of spectral features, and +interaction with a database of atomic structure parameters and +plasma emission models. + +\isisx is written entirely in ANSI-C (with a few POSIX extensions) +and is intended to be portable across most Unix operating systems. +It has been used successfully on a variety of 32-bit and 64-bit +processors and under a variety of Unix operating systems including +Linux, FreeBSD, Solaris, SunOS, IBM/AIX, DEC/OSF1 and DEC/Ultrix systems. +\isisx requires subroutine libraries from \cfitsio, \pgplot\ and +\slang, all of which are widely available as free software. + +This manual is designed to serve as an introduction, user's guide, +and definitive reference manual to the \isisx package. Please +address any comments or suggestions to the \isisx user's mailing +list {\tt isis-users@space.mit.edu}. + +%\end{flushleft} + +\vspace{20mm} + +\hfill {\it- John Houck, \today} \hfill + +\vspace{20mm} + +{\it We are continuing to develop \isisx -- more current +information can be found at:} +\begin{center} +\isisweb +\end{center} + +\newpage +\cleardoublepage +\pagenumbering{arabic} + +\part{Introduction to ISIS \label{part:intro}} + +\chapter{Introduction} +\label{chap:intro} + +\section{ISIS in Context} + +High resolution X-ray spectra can contain a vast amount of information on +the physical conditions in an emitting plasma. The richness of these data +often lead the observer to examine plasma emission models and their +fundamental atomic data in some detail. Until recently, the voluminous +atomic data used to generate plasma emission models was often poorly +documented and nearly inaccessible to most X-ray observers. Recent efforts +by Smith, Brickhouse, Liedahl \& Raymond (2001) are helping to improve this +situation by making plasma emission models and atomic data available in a +form which is more portable and accessible to observers. + +\isisx is intended to support the analysis of high resolution +X-ray spectra by combining in one package tools to query a +database of atomic data and plasma emission models (e.g. that of +Smith et al. 2001) with tools to manipulate and measure high +resolution spectral data. These tools (called functions in the +rest of this document) simplify low level operations such as file +input, data plotting and database search and retrieval, allowing +users to concentrate on higher level analysis issues. \isisx is +also programmable and extensible, meaning that users can write +scripts to simplify repetitive analysis tasks and can extend the +\isisx command language by adding those scripts (or even +user-supplied C programs) as new commands. \slang, the +interpreted language which provides these features, also provides +IDL-like array-based mathematical functions which greatly simplify +common analysis operations.\footnote{\slang was created by John E. +Davis and has not been developed or maintained by contract +funding; it is free software, available under the GNU Public +License.} + +The primary purpose of \isisx is support of high resolution X-ray +spectroscopy, but an important secondary goal in the design was to +maximize the usefulness of the software by maximizing its +portability. For this reason, \isisx is written in ANSI C and +uses only widely available, free-software components. \cfitsio\ +and \pgplot\ have been widely used by the astronomy community for +a number of years and are thoroughly tested and known to run on a +wide range of computer systems. \slang\ is currently less well +known but is fast, portable and provides an easy-to-use C-like +syntax which we believe has a number of clear advantages over +other scripting languages such as Perl, Python and Tcl. + +\vfill + +\section{The Guilty Parties} + +The \isisx development team currently consists of the following individuals: + +\begin{center} +\begin{tabular}{lll} +John C. Houck \hspace{2.5cm} & MIT/CXC \hspace{2.0cm} & Lead Scientist and Software Engineer\\ +John E. Davis & MIT/CXC & Software Engineering Support \\ +David Huenemoerder & MIT/CXC & Science Support \\ +Dan Dewey & MIT/HETG & Science Support \\ +Mike Nowak & MIT/CXC & Science Support \\ +David S. Davis & MIT/CXC & Science Support \\ +\end{tabular} +\end{center} + +\section{Acknowledgements} + +We gratefully acknowledge the aid and support of various members of the +Chandra X-ray Observatory project including the Mission Support Team, the +Calibration group, and the Data Systems group. + +\chapter{Quick Start} +\label{chap:quick} + +\section{Obtaining ISIS Source Code, Documentation and Help} + +\isisx source code and documentation may be obtained from the \isisx web +page at +\begin{verbatim} + http://space.mit.edu/cxc/isis +\end{verbatim} + +Please send comments, questions and bug reports to the mailing list +{\tt isis-users@space.mit.edu}. + +\section{Installing ISIS} + +Once source code is obtained from the web, detailed instructions +on how to install the software may be found in the {\tt INSTALL} +file included with the distribution. Section \ref{chap:specdb} of +this manual describes how to set up the spectroscopy database. + +Note that only a single \isisx installation is required at a given site; +there is no need to install it for each individual user. This also +simplifies upgrades and minimizes use of disk space. + +\subsection{Spectroscopy Database Configuration} + +To access the spectroscopy database, \isisx must obtain the full +path to the database directory and the names of all relevant +database files (see \S \ref{chap:specdb}). The person who installs +\isisx should also ensure that a spectroscopy database is +installed and that at least one configuration script is edited to +accurately describe the database location and contents. See +\S\ref{chap:specdb} for a detailed discussion. + +\vfill + +\section{Running ISIS} +\label{sec:running} + +Assuming the \isisx executable exists somewhere on your the +command search path, you can run \isisx by simply typing {\bf isis} +at the Unix prompt. The interactive help system provides +documentation on \isisx intrinsic functions. Use {\tt apropos} to +find function names containing a certain substring: +\begin{verbatim} + isis> apropos("data"); +\end{verbatim} +and use {\tt help} to obtain more detailed documentation on +function usage: +\begin{verbatim} + isis> help("load_data"); +\end{verbatim} +Because these commands are used quite often, shortcuts are +available (see \S\ref{sec:shortcuts}). + +\index{line-separator!see {{\tt Isis\_Append\_Semicolon}}} +\index{semicolon!see {{\tt Isis\_Append\_Semicolon}}} +\index{{\tt Isis\_Append\_Semicolon}} +\label{about-semicolons} + +{\it About the semicolon (;) line-separator:}~~The \slang\ +scripting language requires lines to end with a semicolon (;). +However, for interactive use, some people find it annoying to +have to type a semicolon at the end of every line. Using the +intrinsic variable \verb|Isis_Append_Semicolon|, one can +indicate whether or not \isis\ should automatically supply this +semicolon in interactive mode. By default +\verb|Isis_Append_Semicolon=0|, meaning that, in interactive +mode, the user must end each line with a semicolon. To have +isis automatically append the semicolon to each command line in +interactive mode, set \verb|Isis_Append_Semicolon=1|. The best +way to make sure this value is automatically set every time you +start \isis\ is to set it in your \verb|~/.isisrc| file: +\begin{verbatim} + Isis_Append_Semicolon = 1; +\end{verbatim} +Although some users find it convenient to have isis +automatically append the semicolon in interactive mode, this +has the important drawback that one cannot reliably cut and +paste into the interactive command line scripts which have +multi-line S-Lang constructs such as loops or function +definitions. + +\subsection{A Simple Example: Measuring the Flux in an Emission Line} +\label{subsec:simpleexample} + +For this example, we will use the sample data available from the +\isisx web page. + +First, load the spectra: +\begin{verbatim} +isis> load_data ("acisf01318N003_pha2.fits.gz"); +Reading: ............ +Integer_Type[12] +isis> list_data; + +Current Spectrum List: + id instrument m prt src use/nbins A R totcts exp(ksec) clr target + 1 HETG-ACIS -3 1 1 8192/ 8192 - - 2.1000e+01 26.701 - CAPELLA + 2 HETG-ACIS -2 1 1 8192/ 8192 - - 2.7000e+02 26.701 - CAPELLA + 3 HETG-ACIS -1 1 1 8192/ 8192 - - 5.8410e+03 26.701 - CAPELLA + 4 HETG-ACIS 1 1 1 8192/ 8192 - - 5.0670e+03 26.701 - CAPELLA + 5 HETG-ACIS 2 1 1 8192/ 8192 - - 1.0300e+02 26.701 - CAPELLA + 6 HETG-ACIS 3 1 1 8192/ 8192 - - 8.0000e+00 26.701 - CAPELLA + 7 HETG-ACIS -3 2 1 8192/ 8192 - - 9.0000e+02 26.701 - CAPELLA + 8 HETG-ACIS -2 2 1 8192/ 8192 - - 8.6200e+02 26.701 - CAPELLA + 9 HETG-ACIS -1 2 1 8192/ 8192 - - 2.5683e+04 26.701 - CAPELLA + 10 HETG-ACIS 1 2 1 8192/ 8192 - - 2.0369e+04 26.701 - CAPELLA + 11 HETG-ACIS 2 2 1 8192/ 8192 - - 6.3900e+02 26.701 - CAPELLA + 12 HETG-ACIS 3 2 1 8192/ 8192 - - 5.7000e+02 26.701 - CAPELLA + +isis> +\end{verbatim} +\isisx prints a dot (.) as each spectrum is read from the data +file. By default, \isisx loads all the data in the specified file. By +specifying the row index, it is also possible to load a single +spectrum from a Type II PHA file. Once the data is loaded, \verb|list_data| +shows a list of data sets. Each data set is identified by an index ({\bf +id}); as we will see below, this index is used to refer to an +individual data set. The columns labeled {\bf m}, {\bf prt} and +{\bf src} indicate the dispersion order ({\bf m}), the spectrum +"part" ({\bf prt}) (e.g. the HEG is {\tt prt=1} and the MEG is +{\tt prt=2}), and the source index ({\bf src}). The next two +columns show the number of bins in the data set ({\bf nbins}) and +the number currently noticed for fitting ({\bf nbins}). The +columns labeled {\bf A} and {\bf R} indicate the index of the +assigned ARF and RMF respectively; a dash (-) indicates that no +response function has been assigned. The last four columns give +the total number of counts in the spectrum ({\bf totcts}), the +exposure time ({\bf exp}), a plot color index ({\bf clr}) and the +target name. + +The line \verb|Integer_Type[12]| indicates that the {\bf +load\_data} function returned a 12 element integer array +(containing the indices of the data sets loaded). Because this +array was not stored in a variable and was not explicitly ignored, +\isisx handled the return value automatically. This is an +important and useful feature of \slang\ which will be discussed in +more detail later on. + +To plot the counts histogram from the minus first-order MEG +spectrum, use {\bf plot\_data\_counts}: +\begin{verbatim} +isis> plot_data_counts (9); + Graphics device/type (? to see list, default /NULL): /xw +isis> +\end{verbatim} +\pgplot\ prompts the user for a plot device, defaulting to +the {\tt /NULL} device if no default has been specified +using {\tt PGPLOT\_DEV} environment +variable variable. Here, we selected {\bf /xw} to plot to the +screen using the X-windows. + +Because the plot command {\tt plot\_data\_counts} is somewhat +cumbersome to type, you may wish to define a shorter alias: +\begin{verbatim} +isis> alias ("plot_data_counts", "pdc"); +\end{verbatim} +Now clear the plot and re-draw it using this new command alias: +\begin{verbatim} +isis> clear; +isis> pdc (9); +\end{verbatim} + +Next we load the ARF and assign it to the appropriate data set: +\begin{verbatim} +isis> () = load_arf ("acisf01318_000N001MEG_-1_garf.fits.gz"); +isis> list_arf; + +Current ARF List: + id grating detector m prt src nbins exp(ksec) target + 1 HETG ACIS -1 2 0 8192 28.12 CAPELLA + +isis> assign_arf(1,9); +isis> +\end{verbatim} +Note that here we have explicitly ignored the return value from the +{\bf load\_arf} function and that the {\bf assign\_arf} function did +not return anything; function return values are normally used +either to return requested information or to provide a way of testing +whether or not the function call succeeded. The latter values are +especially useful in scripts but may often be ignored in interactive mode. +Once the ARF is loaded into the internal list, the updated list of ARFs +is displayed showing information similar to that in the list of +data sets. + +Now load the RMF and assign it to the same data set: +\begin{verbatim} +isis> () = load_rmf ("acismeg1D1999-07-22rmfN0002.fits.gz"); +isis> list_rmf; + +Current RMF List: + id grating detector type file + 1 MEG ACIS-S file: ... acismeg1D1999-07-22rmfN0002.fits.gz + +isis> assign_rmf(1,9); +isis> +\end{verbatim} + +Now, let's focus on a single emission line and measure the flux in +the line. First, change the X-axis range to display the 12-13 \AA +region and re-draw the plot: +\begin{verbatim} +isis> xrange(12.0,13.0); +isis> pdc (9); +\end{verbatim} +When fitting models to data, \isisx fits all the currently loaded data sets +simultaneously. Because we want to fit only a single Gaussian to a single +spectrum, we must first ignore all the other data sets and notice only the +wavelength range we want to fit: +\begin{verbatim} +isis> ignore ([ [1:8], [10:12] ]); +isis> xnotice (9, 12.05, 12.2); +\end{verbatim} +The {\bf ignore} function takes an array of data-set indices to +ignore. This function can also take an optional wavelength range +which applies to all the indicated data sets; if no wavelength range is +specified, the entire data set is ignored. The {\bf xnotice} +function e{\bf x}clusively-{\bf notice}s the specified range +of dataset 9. + +To fit a single Gaussian, define the fit-function as +\begin{verbatim} +isis> fit_fun ("gauss(1)"); +\end{verbatim} +The integer index indicates which instance of the Gaussian is +used; one could fit three Gaussians using +\verb|fit_fun("gauss(1)+gauss(2)+gauss(3)");|. To list the fit +parameters, use {\bf list\_par} +\begin{verbatim} +isis> list_par; +gauss(1) + idx param tie-to freeze value min max + 1 gauss(1).area 0 0 0 0 0 + 2 gauss(1).center 0 0 0 0 0 + 3 gauss(1).sigma 0 0 0 0 0 +isis> +\end{verbatim} +This listing shows the function definition on the first line and +then lists the fit parameters, indicating which parameters are +linked or frozen, the parameter values and the allowed parameter +ranges. Setting the {\tt min} and {\tt max} values to zero +indicates that the corresponding parameter value is unconstrained. + +To set the parameter values from the command line, one could use +either {\bf set\_par} or {\bf edit\_par}. Although it is a matter +of personal preference, the {\bf set\_par} is generally more +useful in scripts and {\bf edit\_par} is often more useful in +interactive mode. The {\bf edit\_par} function loads the +parameter list into the editor specified by your {\tt EDITOR} +environment variable (or {\tt vi} by default). After using the +editor to enter the necessary information, save the file and exit +the editor. Here, so that we can show the screen interaction +explicitly, we use {\bf set\_par} to provide initial parameter +values: +\begin{verbatim} +isis> set_par(1,100); +isis> set_par(2,12.15); +isis> set_par(3,0.03); +\end{verbatim} +Several different versions of the syntax are supported; which +is most useful depends on the circumstance. + +For example, we could have used +\begin{verbatim} +isis> set_par ("gauss(1)", [100, 12.15, 0.03]); +\end{verbatim} +This form is useful because it takes only one line and doesn't +require knowing the parameter indices, but it requires you to +remember the order in which the parameters are defined. +Alternatively, we could have used this syntax: +\begin{verbatim} +isis> set_par ("gauss(1).area", 100); +isis> set_par ("gauss(1).center", 12.15); +isis> set_par ("gauss(1).sigma", 0.03); +\end{verbatim} +This doesn't require knowledge of the parameter indices, but it +requires more typing and requires correct spelling of the +parameter names. + +Once the parameters have been set, list the current values +using \verb|list_par|: +\begin{verbatim} +isis> list_par; +gauss(1) + idx param tie-to freeze value min max + 1 gauss(1).area 0 0 100 0 0 + 2 gauss(1).center 0 0 12.15 0 0 + 3 gauss(1).sigma 0 0 0.03 0 0 +\end{verbatim} +In interactive mode, one can do this in yet a different way +by using the function {\bf ifit\_fun} which reads +the plot cursor to initialize the fit parameters +(see \S\ref{chap:funcref}). + +Because the specified normalization is probably not even close to +the correct value, we'll use {\bf renorm\_counts} to obtain a better +initial value before doing the fit: +\begin{verbatim} +isis> renorm_counts; + Parameters[Variable] = 3[3] + Data bins = 30 + Chi-square = 1215 + Reduced chi-square = 45 +isis> +\end{verbatim} +The screen output shows how many parameters are being fit, how +many are variable, the number of data bins being fit and gives the +resulting $\chi^2$ fit-statistic. Now find the best fit, allowing +all the parameters to vary: +\begin{verbatim} +isis> fit_counts; + Parameters[Variable] = 3[3] + Data bins = 30 + Best fit chi-square = 28.86 + Reduced chi-square = 1.069 +isis> +\end{verbatim} +To overlay the best-fit model, use the {\bf oplot\_model\_counts} function. +As before, we can define an alias to save typing: +\begin{verbatim} +isis> alias ("oplot_model_counts", "opmc"); +isis> opmc (9); +\end{verbatim} + +To save the fit-results in a file one can either use the default +\isisx parameter file format or one can make use of the low-level +\slang\ functions to save the values of interest in a different, +user-defined format. To save using the default parameter file +format: +\begin{verbatim} +isis> save_par("gfit.p"); +\end{verbatim} +The default format is exactly the same as the screen listing +generated by {\tt list\_par}. The main advantage to saving the +fit-function and its parameters in this format, is that the values +can be restored using {\bf load\_par}. + +To show how to save the fit-results using a user-defined format, +suppose we want to save the best-fit flux along with 90\% +confidence limits and that we want the wavelengths listed in the +first column and the line width in the second column. Here's how +to do that: + +First, compute the necessary confidence limits using {\bf vconf}: +\begin{verbatim} +isis> (amin, amax) = vconf(1); +Finding best fit +Best fit par= 1.04961248e-03: chisqr= 2.88578026e+01 +Allowed parameter range is currently unrestricted. +Please specify finite min/max values for parameter confidence limit search. +\end{verbatim} +Oops -- we forgot to specify the range of parameter values for the +confidence limit search. Use the optional arguments of {\bf +set\_par} for that: +\begin{verbatim} +isis> a = get_par(1); +isis> set_par(1, a, 0, 0.9*a, 1.1*a); +\end{verbatim} +Here, we used the {\bf get\_par} function to get the exact parameter value rather +than typing it again from the screen or from the saved parameter file. We then +chose parameter value ranges of $\pm$10\%. Now compute the +confidence limits, saving the values in variables {\tt amin} and {\tt amax}: +\begin{verbatim} +isis> (amin, amax) = vconf(1); +Finding best fit +Best fit par= 1.04961248e-03: chisqr= 2.88578026e+01 +Minimizing for par= 9.97151856e-04 +par= 9.97151856e-04 chisqr= 3.0389e+01 dchisqr= 1.5316e+00 +Minimizing for par= 9.70921544e-04 +par= 9.70921544e-04 chisqr= 3.2304e+01 dchisqr= 3.4462e+00 +Minimizing for par= 9.87731365e-04 +par= 9.87731365e-04 chisqr= 3.0989e+01 dchisqr= 2.1311e+00 +Minimizing for par= 9.80331268e-04 +par= 9.80331268e-04 chisqr= 3.1529e+01 dchisqr= 2.6711e+00 +Minimizing for par= 9.79859377e-04 +par= 9.79859377e-04 chisqr= 3.1565e+01 dchisqr= 2.7076e+00 +limit found: 9.79859377e-04 dchisqr= 2.7076e+00 +Minimizing for par= 1.39913896e-03 +par= 1.39913896e-03 chisqr= 9.6803e+01 dchisqr= 6.7945e+01 +Minimizing for par= 1.11941726e-03 +par= 1.11941726e-03 chisqr= 3.1568e+01 dchisqr= 2.7104e+00 +limit found: 1.11941726e-03 dchisqr= 2.7104e+00 +isis> +\end{verbatim} +Note that the screen output from {\bf vconf} is verbose; +use {\bf conf} to do a ``quieter'' confidence limit search. + +Now that we have our confidence limits, we can save these values +in a custom file format: +\begin{verbatim} +isis> fp = fopen ("gfit.txt", "w"); +isis> () = fprintf (fp, "Center Sigma Flux (F_lower, F_upper)\n"); +isis> () = fprintf (fp, "%10.7f %12.4e %12.4e (%9.4e, %9.4e) \n", + get_par(2), get_par(3), get_par(1), amin, amax); +isis> fclose(fp); +\end{verbatim} +The first line opens the file {\tt "gfit.txt"} for writing (that's +what the {\tt "w"} is for). The second line prints some +informative column headers (not aligned with the data columns) and +the third prints the data values using a syntax which should be +very familiar to C programmers; e.g. \verb|"10.7"| indicates a +field of width 10 with 7 digits of precision and the {\tt f} and +{\tt e} format specifiers indicate decimal and scientific notation +formats respectively. Note that we have explicitly ignored the +status return values from the {\bf fprintf} function. Similarly, +one can write a short function to load values from ascii columns, +but it may be simpler to use the built-in functions \verb|readcol| +and \verb|writecol| to read and write ascii files with columns of +numbers. We could also have stored our fit results in a FITS +binary table using the \verb|cfitsio| module.\footnotemark + +\footnotetext{For information on the various modules available, +see {\tt http://space.mit.edu/cxc/software/slang/modules/}} + +Plots of 2D confidence contours may be generated using +\verb|conf_map_counts| or \verb|conf_map_flux| and +\verb|[o]plot_conf|. + +\chapter{Programming ISIS} +\label{chap:prog} + +\section{Interactive Scripting} + +A convenient way to use \isisx for spectral analysis is to write one or more +scripts, usually in the form of several useful functions, and to iteratively +edit and run these scripts to achieve the desired result. This may sound +cumbersome, but in practice often works quite efficiently, because the +\isisx intrinsic functions already handle a number of tedious tasks such as +manipulating complex data files and searching the spectroscopy database. + +For example, one might write one script to load several available data +sets and to set up the spectroscopy database. Once that script exists, +one can start off later analysis sessions by just running the setup +script. + +Similarly, one might write another script to carry out a few standardized +analysis steps, independent of which data set is loaded. Repeating those +analysis steps for several data sets might then be a matter of running the +analysis script several times. + +Some example scripts may be found on the \isisx web page; several +usage examples are discussed in \S\ref{chap:common-tasks}. + +In cases where a large, specialized task is currently unsupported in \isis, +it is possible for users to extend \isisx by linking in other subroutine +libraries, {\it without} editing {\it any} of the \isisx source code (see \S +\ref{sec:extending-isis}). This allows large specialized tasks to be handled +in compiled code, yet still take advantage of the existing \isisx functions. + +\section{Scripts} +\label{sec:scripts} + +To run an \isisx script from the Unix shell, supply the path to the +\isisx script on the Unix command line: +\begin{verbatim} + unix> isis path/script.sl +\end{verbatim} +when the script finishes, control will return to the +\isisx prompt. To have control return to the Unix shell when +the script finishes, use the {\tt --batch} option or use +{\tt exit(num)} or {\tt quit} as the last line of the script. + +It is also possible to create executable scripts similar to Unix +shell scripts. If the first line of the script contains +something like +\begin{verbatim} + #! /usr/bin/env isis +\end{verbatim} +and the script is made executable, e.g. +\begin{verbatim} + chmod +x path/script.sl +\end{verbatim} +then the script can be executed like any other unix command, +by simply typing the name of the script at the unix prompt: +\begin{verbatim} + unix> path/script.sl +\end{verbatim} +In this case, the operating system uses the program specified +on the first line of the script, namely \isis, to interpret +the rest of the file. + +To run a script during an interactive \isisx session, use +\begin{verbatim} + isis> .load path/script.sl +\end{verbatim} +When the script finishes, control will +return to the \isisx prompt (unless {\tt script.sl} contains the {\tt +quit} command). Note that this shortcut syntax works only in interactive +mode; in a script one must use +\begin{verbatim} + ()=evalfile("path/script.sl"); +\end{verbatim} +The {\tt .source} short-cut is similar to {\tt .load} except that +the script is executed exactly as though each line were entered in +interactive mode. This provides a useful mechanism for replaying +\isisx log-files. + +At startup, \isisx searches for the file {\tt \$HOME/.isisrc} (where +{\tt HOME} is the path to the user's home directory). If this file +exists, \isisx attempts to interpret it as a \slang\ script. Any +functions which should run at \isisx startup for, {\it e.g.} +initialization and user-customization should be invoked in this file. +For example, to have the spectroscopy database +loaded automatically, one could add this line to the {\tt .isisrc} file: +\begin{verbatim} + plasma(aped); +\end{verbatim} +As written, this example assumes the existence of the {\tt aped} +data structure. Alternatively, one may define convenient aliases for +often used functions (see {\tt alias()}). Site-wide \isisx +customizations may be added and documented using the files +{\tt etc/local.sl} and {\tt doc/local\_help.txt} in the \isisx source +code directory (see \S\ref{chap:quick}). + +If it exists, the configuration file {\tt \$HOME/.isisrc} is automatically +loaded before executing any scripts specified on the \isisx +command line. To prevent loading the configuration file, +use the {\tt -n} option on the command line: +\begin{verbatim} + unix> isis -n path/script.sl +\end{verbatim} +To load an alternate configuration file, use the \verb|-i| option: +\begin{verbatim} + unix> isis -i ~user/.isisrc +\end{verbatim} + +Scripts may also take command-line arguments using a mechanism +familiar to C programmers. This feature provides a convenient +way for a script to obtain needed parameters from the command +line (e.g. the names of input and output files), allowing +scripts to be run without ever entering the ISIS interactive +mode. The command-line is available as an array of strings +(\verb|__argv|) of length \verb|__argc|. The command line +arguments are most conveniently handled when the first line of +the script is +\begin{verbatim} + #! /usr/bin/env isis-script +\end{verbatim} +For example, consider this script: +\begin{verbatim} + #! /usr/bin/env isis-script + vmessage (" _debug_info = %d", _debug_info); + vmessage ("__argc = %d", __argc); + message ("__argv:"); + print (__argv); +\end{verbatim} +as command-line arguments (note that \verb|_debug_info| is a +\slang\ intrinsic variable). Invoking this script (named 'doit') +with two command-line arguments yields +\begin{verbatim} +unix> ./doit a.fits b.txt + _debug_info = 0 +__argc = 3 +__argv: +"/tmp/doit" +"a.fits" +"b.txt" +\end{verbatim} +As expected, the command-line array has size \verb|__argc=3|. + +\section{Extending ISIS} +\label{sec:extending-isis} + +It is possible to add functionality to \isisx without modifying the +\isisx source code. This can be accomplished in several ways: + +One way is to define new \slang\ functions using the existing \isisx +and \slang\ intrinsics. If these \slang\ function definitions +are placed in a file named e.g. {\tt myfunctions.sl}, they +can easily be made available at the \isisx prompt +\begin{verbatim} + isis> ()=evalfile("myfunctions.sl") + isis> .load myfunctions.sl % simpler equivalent +\end{verbatim} +In fact, much of the \isisx command line interface is implemented this way. + +Another way to add new functions is to define new intrinsics in C, +compile that code into a dynamically linked library (named e.g. {\tt +myfunctions-module.so}) and then import that library at \isisx +run-time using the \slang\ {\tt import} function: +\begin{verbatim} + import ("myfunctions") +\end{verbatim} +This method is necessarily restricted to machines which support +ELF standard dynamic linking (e.g. Solaris 2.x and Linux provide +support, but SunOS 4.x does not). Most \xspec\ functions +can already be imported in this way -- see +\verb|modules/xspec/src/xspec-module.c|. See the \slang\ +documentation for more information on dynamic linking. + +Finally, several parts of ISIS support user-defined +alternatives. In particular, in fitting models to data, ISIS +provides a number of user-definable operations including +user-defined fit-functions, fit-kernels, instrument responses +(ARFs and RMFs), fit-statistics and minimization algorithms. +Some of these may be implemented in both C (or other compiled +language) and S-lang while others support only +compiled-language or only S-Lang implementations. For details +on adding user-defined fit-functions, see +\verb|add_slang_function| or \verb|add_compiled_function|. To +add a user-defined fit-kernel, see \verb|load_kernel|. To add a +user-defined minimization algorithm or fit-statistic, see +\verb|load_fit_method| and \verb|load_fit_statistic|, +respectively. Although \slang\ is very efficient, +computationally-intensive extensions may be best implemented in +C or Fortran. + +The {\sc slirp} code generator makes it very easy to add +arbitrary compiled codes to \isis, including new models. It +can dramatically reduce the time and effort required to make C, +C++, or {\sc fortran} code callable directly from \isis, +automatically vectorize functions to take advantage of the +powerful numerical and array capabilities native to \slang, and +can even generate Makefiles to automate the build process. + +\section{Language Syntax} + +The \isisx command language syntax is the syntax of \slang, its +C-like embedded scripting language. Although \isisx can be used +without becoming an expert with \slang, it will be helpful to +understand something of how the scripting language works and, in +particular, how to use its array-manipulation syntax. + +All command lines must end with a semicolon (;) (but see the +discussion in \S\ref{about-semicolons} about their use in +interactive mode). Multiple commands are allowed on the same line +and command phrases may also extend over multiple lines. For +example, try: +\begin{verbatim} +isis> message("testing...." + + string(1 + 2 + 3)); +\end{verbatim} +In this example, the first line was ended with a carriage return. + +The comment character is the percent symbol (\%); all characters +following a percent symbol (\%) on a given line are ignored. + +Arrays and complex data structures may be defined and manipulated +(see the \slang\ documentation for details). +\slang\ array indexing syntax is similar to that used in {\sc IDL}. +Array elements are indexed starting at zero; +{\tt x = [ 1, 2, 3, 4 ]} defines {\tt x} as array of 4 values with indices +0, 1, 2, 3 so that, e.g. {\tt x[1] = 2}. The colon shorthand notation is +used to specify ranges, {\it e.g.} {\tt [ 2:7 ]} = {\tt [ 2, 3, 4, 5, 6, 7 +]}. This notation is quite powerful and allows many array manipulation +tasks be to be expressed simply and clearly. For example, to reverse the +order of elements in an array {\tt x}: +\begin{verbatim} + x = [2:7]; <---- this means x = [2, 3, 4, 5, 6, 7] + + n = length(x); <---- n=6 (because x has 6 elements) + + reversed_x = x[[n-1:0:-1]]; + + % result is ---> reversed_x = [x[n-1], x[n-2], .. x[0]] + % = [ 7, 6, .. 2 ] +\end{verbatim} +this order reversal arises e.g. when converting from a wavelength grid +in increasing order to an energy grid in increasing order. + +An unusual aspect of the syntax involves functions that return multiple +values. For example, if a function returns three values, the return values +can be assigned to specific variables using this syntax: +\begin{verbatim} + variable x,y,z; + (x,y,z) = some_function (); +\end{verbatim} +Functions may also return values through the function argument +list, using syntax which should be familiar to C programmers: +\begin{verbatim} + variable x,y,z; + a_function (&x, &y, &z); +\end{verbatim} +In scripts, variables must be declared before use as above, but in interactive +mode, variables are declared automatically. + +Return values may also be discarded. To save only the second +return value from the above function while discarding the first +and third, use this syntax: +\begin{verbatim} + (,y,) = some_function(); +\end{verbatim} +For functions which return only one value, the syntax is more familiar: +\begin{verbatim} + x = returns_one_value(); +\end{verbatim} +To explicitly discard the single return value, use +\begin{verbatim} + () = returns_one_value(); +\end{verbatim} + +In interactive mode, it rarely matters to the user that \slang\ is a stack-based +language. This is primarily because handling of function return values is +simplified in interactive mode: the stack is automatically emptied after +each function executes and any return values not explicitly handled are +simply popped off the stack and printed on the screen. +For example: +\begin{verbatim} + isis> x = [47, 12, 13, 92, 46, 12]; % define an array + isis> y = max(x); % now y = 92 + isis> max(x); % When the return value isn't "caught", + 92 % it is popped off the stack automatically. +\end{verbatim} +This is true {\it only} in interactive mode, however. + +When writing scripts, one must be more careful to explicitly handle all +function return values. When a function is invoked without explicitly +handling all of its return values in some way, the remaining return values +are placed on the stack. The next function call which pops arguments off +the stack will get those values as input. This feature can be exploited to +improve the efficiency of \slang\ scripts, but can also lead to unexpected +results if incorrect arguments are unintentionally passed to a function +because the return value from a previous function call was not handled +correctly. Using a somewhat pathological example, the operation of the +stack can be seen in interactive mode +\begin{verbatim} + isis> [47, 12, 13, 92, 46, 12]; max(); + 92 +\end{verbatim} +In this example, an array is first pushed onto the stack, then the {\tt +max() } function pops an array argument off the stack, finds the largest +array element, and pushes that value back onto the stack. Because this is an +interactive mode example, the value remaining on the stack is then +automatically printed on the screen. + +Don't be concerned if this sounds a little complicated. As stated above, in +interactive mode, the presence of the stack is usually an unimportant +detail. The main reason for mentioning it here is to provide a short +introduction to the language structure and suggest ways in which it can be +exploited. + +For full details, see the \slang\ documentation at +\begin{verbatim} + http://www.s-lang.org/~davis/slang.html +\end{verbatim} +or in the \slang\ source directory. + +\chapter{Common ISIS Tasks} +\label{chap:common-tasks} + +This section provides several examples to illustrate how to carry out common +analysis tasks using \isis. These examples are intended to provide a +starting point and to give the user an idea of how \isisx can be used. They +do not illustrate everything \isisx can do and do not provide a complete +description in any sense. For full details on all \isisx functions, see the +\isisx Function Reference in chapter \ref{chap:funcref}. + +The following examples use sample data files which are available +from the \isisx web page. +\begin{enumerate} + +\item a Type II pha file called \verb|acisf01318N003_pha2.fits| +which contains Chandra/HETG counts spectra for several plus and +minus diffraction orders of both HEG and MEG. + +\item an Effective Area function (ARF) called +\verb|acisf01318_000N001MEG_-1_garf.fits| + +\item a Redistribution Matrix function (RMF) called +\verb|acismeg1D1999-07-22rmfN0002.fits| + +\item a spectral model definition file called {\tt model.dat} (see {\tt +load\_model} for a description of the format). + +\item a \slang\ script ({\tt aped.sl}) describing the layout of the +spectroscopy database (see \S\ref{chap:specdb}). + +\item the spectroscopy database itself. +\end{enumerate} + +The \slang\ scripts used to generate the figures in this manual +are in the {\tt doc/scripts} directory. For instructions on +how to obtain and install the spectroscopy database, see \S +\ref{chap:specdb} + +\section{Reading and displaying spectral data} + +\isisx can read data in either FITS (Type II pha) or ASCII format. +To read a Type II pha file and display selected spectra (see Figures +\ref{fig:data_cts} and \ref{fig:data_flx}): + +\verbatiminput{scripts/data.sl} + +Data plots use a linear axis scale by default; to make a log plot, use {\tt +xlog} and/or {\tt ylog} -- {\tt xlin} and {\tt ylin} will restore the linear +axis scaling. + +\begin{verbatim} + () = open_plot("/xwin"); + xlog; ylog; + plot_data_counts (sp); % plot log-log +\end{verbatim} + +To change the axis ranges, use the {\tt xrange} and {\tt +yrange} commands. Continuing the example: + +\begin{verbatim} + erase; % clear the plot window + xlin; ylin; % use a linear scale + xrange (11,12); % set X-range to 11-12 angstrom + yrange; % take Y ranges from the data + plot_data_counts (sp); % plot data +\end{verbatim} + +The plot coordinates can be changed (e.g. to plot vs energy in keV +instead of wavelength in \AA) using the {\tt plot\_unit} command. + +\begin{verbatim} + erase; % clear the plot window + plot_unit ("kev"); % plot in energy units + plot_data_counts (sp); % plot data +\end{verbatim} + +\begin{figure}[ht] +\putfig{figures/data_cts} +\caption{Example plot of observed counts per bin vs. wavelength} +\label{fig:data_cts} +\end{figure} + +\begin{figure}[ht] +\putfig{figures/data_flx} +\caption{Example plot of a flux corrected spectrum} +\label{fig:data_flx} +\end{figure} + +Although the current version of \isisx supports analysis of a flux-corrected +spectrum, it does not automatically compute the flux-corrected spectrum from +the counts histogram. The flux-corrected spectrum may be provided in the +input data file or may be computed within \isisx after loading the +appropriate effective area (ARF) file: +\begin{verbatim} + % load one ARF, return value is arf=1 + arf = load_arf ("acisf01318_000N001MEG_-1_garf.fits.gz"); + + assign_arf (arf, sp); % assign the ARF to the current data set + flux_corr (sp, 2); % flux-correct, ignoring + % bins with S/N < 2 +\end{verbatim} +The flux-corrected result is stored separately and does not over-write +the counts histogram. Note that because the S/N threshold was set to a +non-zero value (the second argument to {\tt flux\_corr}), bins with +very few counts above 25 \AA~ are assigned a flux of zero in Figure +\ref{fig:data_flx}; see the +description of {\tt flux\_corr} in the reference section for more detail. + +\section{Initializing the spectroscopy database} +\label{specdb-init} + +To initialize the spectroscopy database, \isisx must first obtain +the location and contents of the database. The person who +installs \isisx should provide a S-Lang script (perhaps by editing +one of the included example files) which describes the local +version of the spectroscopy database. After installation, it is +not necessary for casual users to access this database +configuration script directly. + +See the {\tt etc/local.sl} file in the \isisx source distribution for +an example of how the necessary information can be provided by a +configuration script which is automatically loaded when an +associated initialization function is referenced. For example, to +load the spectroscopy database described by configuration script +{\tt etc/aped.sl}, calling the {\tt aped} function as an argument to +{\tt plasma}: + \begin{verbatim} + plasma (aped); + \end{verbatim} +causes the associated configuration script ({\tt aped.sl}) to load +and execute automatically, providing paths to +the atomic data and the emissivity tables (if available). +The {\tt plasma} function then loads these database tables into +\isis. +Similarly, one can load the atomic data tables only using the +{\tt atoms} function: +\begin{verbatim} + atoms (aped); + \end{verbatim} +If the atomic data tables are loaded first, loading the emissivity +tables will not unload them -- any ``new'' emission lines +encountered in the emissivity tables (ie not already listed in the +wavelength tables) will be merged into the internal wavelength +list. + +By default, when \isisx loads the database, it reads all the specified files +into memory, including tables of emission line wavelengths, atomic energy +levels, ionization balance and line emissivities. With a large +spectroscopy database (or a computer with a relatively small memory) this +behavior might tax the system memory resources. To encourage \isisx to use +less memory, the user can specify that it access large files by reading the +necessary pieces from disk as needed rather than reading the entire file +into memory at startup (see \verb|Use_Memory|). Because of its large size, +the continuum emissivity file is never loaded entirely; instead, the +structure of this file is ``mapped'' so that run-time access for specific +items in the file is as efficient as possible. + +Important technical note: Although \cfitsio\ is capable of reading +gzip-compressed FITS files transparently, the \cfitsio\ implementation first +uncompresses the {\it entire} FITS file into memory before the read operation +begins. This presents a severe problem if the {\it uncompressed} FITS file is +larger than the computer memory(!) To avoid problems of this nature, it is +best to uncompress the individual database files before reading them into +\isis. Reading uncompressed files has the added benefit that the files can +be read in more quickly and run-time memory usage is minimized. + +Note that even if the atomic database (wavelength tables, energy levels, +etc.) is unavailable, the line and continuum emissivity tables may still be +used to generate spectrum models. In this case, the \isisx functionality +which requires the atomic data tables will be unavailable. + +\section{Identifying emission lines using a spectral model} + +Emission line identification is simplified by the ability to plot the +locations of lines expected from a particular ion or lines which are +expected to be bright at a given temperature. This process may be +complicated by the fact that some database wavelengths may be incorrect -- +an important contribution of high-resolution observations will be in +providing improved measurements of many line wavelengths. \isisx provides a +mechanism to incorporate improved wavelength measurements without changing +the database files directly (see {\tt change\_wl}). + +The process of line identification might start by identifying the brightest +lines in the spectrum (since they are likely to have reasonably well +measured wavelength values). One approach is to compute a model +spectrum and try to match the brightest model lines to those that have +been observed. To do this, load a data set and then compute a model +spectrum on the same grid using the spectroscopy database: + + \begin{verbatim} + % reset global program state (unloads all data sets, etc.) + reset; + + % load the entire type II pha file + load_data ("acisf01318N003_pha2.fits"); + + plot_data_counts (9); % plot counts spectrum + + plasma (aped); + load_model ("model.dat"); % or use edit_model + use_thermal_profile; % thermal + turbulence + d = get_data_counts(9); % use the data grid (Angstroms) + + flux = model_spectrum (d.bin_lo, d.bin_hi); + \end{verbatim} + +Now, select the brightest 10 +lines in a particular wavelength range in the model spectrum and +over-plot those lines on the observed spectrum (e.g. Figure +\ref{fig:line_id}): + +\begin{figure}[ht] +\putfig{figures/line_id} +\caption{Example of emission line labeling} +\label{fig:line_id} +\end{figure} + +\begin{verbatim} + g = brightest(10, where (wl(10,12))); % get indices of bright lines + % between 10-12 Angstrom + + plot_group(g); % overlay lines on an existing plot + page_group(g); % browse the data on those lines. + save_group (g, "bright_10.out"); % save the list in a file +\end{verbatim} +In this case, note that the brightest lines in the model don't accurately +predict all of the brightest lines in this region of the spectrum. + +For a more direct comparison, the model intensities should be compared to +the flux-corrected spectrum so that the variation of effective area with +wavelength is removed from the observed spectrum (see {\tt flux\_corr}). +This is especially important when identifying fainter lines as is the effect +of contamination from higher-order features. Locations of features in other +diffraction orders can be plotted using {\tt lambda\_mth\_order}. + +Even if collisional ionization equilibrium is not an appropriate model for +the data, one may still make use of the wavelength tables in the +spectroscopy database. For example, to plot the locations of all the Fe XVI +and XVII lines between 10-10.5 \AA: + \begin{verbatim} + fe_lines = where (wl(10,10.5) and el_ion(26,[16,17])); + plot_group (fe_lines); + + OR + + plot_group(where (wl(10,10.5) and el_ion(26,[16,17]))); + \end{verbatim} +Note that the output of the {\tt where} command can be used directly without +first being stored in a \slang\ variable. + +By defining symbols like {\tt Fe = 26} in the {\tt .isisrc} file, one can +avoid having to remember the proton numbers of the various elements (a +sample {\tt .isisrc} file is included in the \isisx distribution): + \begin{verbatim} + fe_lines = where (wl(10,10.5) and el_ion (Fe,[16,17])); + \end{verbatim} + +\begin{figure}[ht] +\putfig{figures/elev} +\caption{Example energy level diagram with over-plotted line transitions} +\label{fig:elev} +\end{figure} + +Having identified lines of interest, one might want to look at an energy +level diagram to better understand how those lines are formed. Naturally, +this requires that the spectroscopy database contain energy level +information. If LS coupling energy level data are available, a simple energy +level diagram can be generated (e.g. Figure \ref{fig:elev}), over-plotting +lines transitions listed in a \slang\ array + \begin{verbatim} + plot_elev (Fe, 16); % Fe XVI + oplot_lines (Fe, 16, g); % using an array g as defined above + list_elev (Fe, 16); % list the energy level table + \end{verbatim} +When transition probabilities are available, the energy level listing also +includes the total downward spontaneous radiative transition rate for each +level, simplifying identification of meta-stable states. + +\section{Measuring line intensities} + +Observed line intensities may be measured using several different +techniques with varying accuracy and sophistication. + +The simplest measurement is a sum over the bins which make up a particular +feature; because this approach neglects the effect of the line response +function it probably should not be used to measure the intensities of +individual lines in a blend. + +To examine different methods of making line measurements, first load +a data set and plot a spectrum, perhaps zooming in to a region of interest. + + \begin{verbatim} + % load spectrum number 9 + % variable sp = 1 if this is the only data currently loaded + sp = load_data ("acisf01318N003_pha2.fits", 9); + + xrange(10,11); + yrange; + plot_data_counts (sp); % plot counts spectrum + \end{verbatim} + + \begin{enumerate} + \item Summing bin values: + + \begin{verbatim} + p = region_counts (sp, 10.2, 10.4); + print(p); % get struct field names + p.sum; % isis will echo the value + \end{verbatim} + OR + \begin{verbatim} + (xmin, xmax) = xinterval; % mark the interval using the + % plot cursor + p = region_counts (sp, xmin, xmax); + \end{verbatim} + OR + \begin{verbatim} + cursor_counts (sp); % another cursor-based option + \end{verbatim} + +Notice that the region of interest is defined by specifying a {\it +wavelength} range in Angstrom (\AA) regardless of the units in the input +data. Also, notice that the {\tt region\_counts} function returns a \slang\ +{\it structure} rather than a simple scalar or array value. The fields of +this structure are accessible using the dot notation which will be familiar +to C and IDL programmers. + + \item Fitting line profile functions: + +When measuring the intensities of blended lines, one may account for the +effect of the line response function by fitting the line blend with a sum of +suitably chosen line profile functions plus a continuum function. + +In interactive mode it may be most convenient to obtain initial estimates of +the fit parameters by marking data regions with the plot cursor. To do that, +start by plotting the data in appropriate bin-density units (e.g. counts/\AA~ +rather than counts/bin): + + \begin{verbatim} + open_plot; + plot_bin_density; % required for using ifit_fun() below + plot_data_flux (sp); % assumes flux_corr() has been run + \end{verbatim} + +Now, narrow the plot range and {\tt notice} the +bins to be fit: + + \begin{verbatim} + xrange(15.9,16.1); yrange; + errorbars (1); % turn on error-bars + + plot_data_flux (sp); + + xnotice(sp,15.9,16.1); + \end{verbatim} + +As above, the bin-coordinates are always specified in Angstrom (\AA) +units, regardless of the physical units in the input data file. + +One can initialize the fit parameters by clicking the mouse cursor on the +screen plot -- to do that, define the fit function using {\tt ifit\_fun}; +here the ``i'' is for ``interactive'': + +\begin{figure}[ht] +\putfig{figures/profile_fit} +\caption{Example of fitting a line-blend with over-plotted error-bars.} +\label{fig:profile_fit} +\end{figure} + +\begin{verbatim} + ifit_fun("Lorentz(1) + Lorentz(2) + poly(1)"); + \end{verbatim} + +The indices in the fit function components are used to label multiple +occurrences of a particular component type. Here, we have two Lorentzian +components labeled as number 1 ({\tt Lorentz(1)}) and number 2 {\tt +Lorentz(2)}. After interactively assigning fit parameters, check the +quality of the initial values, then do the fit and over-plot the result: + + \begin{verbatim} + renorm_flux; % automatically adjust normalization + oplot_convolved_model_flux (sp); % plot to check the initial params + fit_flux; + oplot_convolved_model_flux (sp); + \end{verbatim} + +It is important to remember that when fitting, all noticed bins in {\it all +currently loaded spectra} are fit simultaneously. To fit a few line profiles +to a small region of a single loaded spectrum, it is essential to first +ignore all other spectra and all bins outside the region of interest +\begin{verbatim} + % If 12 spectra are loaded, and you want + % to fit only spectrum #9: + ignore([[1:8], [10:12]]); % or ignore([1:8]); ignore([10:12]); + xnotice (9, 15.9, 16.1); +\end{verbatim} + +The unbinned fit function, if available for the +chosen model, may also be over-plotted as in Figure \ref{fig:profile_fit}: + + \begin{verbatim} + x = [15.95:16.1:7.5e-4]; % generate some X coordinates + y = get_cfun(x); % evaluate the function Y(X) + oplot(x,y); + \end{verbatim} + +For further comparison, one may wish to plot the bin residuals or the ratio +between model and data. The simplest way to do that is to use +the \verb|rplot_counts| function. Alternatively, +one can exercise more control over the plot by +manipulating the data and model values directly. +For example: + + \begin{verbatim} + d = get_data_flux (sp); + m = get_convolved_model_flux (sp); + + limits; + hplot (d.bin_lo, d.bin_hi, d.value - m.value); % residuals + + % avoid division by zero + i = where (m.value != 0) + + % plot the ratio + limits; + hplot (d.bin_lo[i], d.bin_hi[i], d.value[i]/m.value[i]); + \end{verbatim} + +Other common tasks are: + + \begin{verbatim} + list_par; % list the fit parameters + conf(2); % compute confidence limits + save_par("lorentz2.fit"); % save the fit parameters + value = get_par (idx); % get a fit parameter value + \end{verbatim} + +If a better fit is encountered while computing confidence limits, +try re-fitting the data until a stable minimum is found. + +\item Forward folding: + +In principle, the most accurate approach to measuring line intensities +requires explicitly accounting for the effect of the line response +function and for variations in the total effective area across the +line blend. The sequence of commands is identical to that required to +fit line profiles, except that additional information on the line +response function (the RMF) and the total effective area (the ARF) is +required. In addition to loading the spectral data, one must provide +the necessary RMF and ARF files and indicate which response goes with +which spectrum (see {\tt load\_rmf}, {\tt assign\_rmf}, {\tt +load\_arf} and {\tt assign\_arf}). A detailed example is given in +\S\ref{subsec:simpleexample}. + +By default, whenever response functions (ARF/RMF) are assigned to a +spectrum, they are applied when fitting a model to that data set (e.g. +forward-folding is the default). Alternatively, the {\tt fit\_*} and +{\tt renorm\_*} functions accept flags which may be used to apply an +ideal ARF and/or RMF even when a realistic instrument response has +been assigned. This mechanism provides an easy way to isolate the +effect of the instrument response. + +\end{enumerate} + +\section{Automatically finding, identifying and fitting emission lines} + +Although \isisx does not currently have intrinsic functions for +automatic spectrum processing of this sort, it is possible to do this +kind of automatic processing with a script. The advantage of this +approach is that users can modify the script without having to +recompile the code, thereby customizing the automatic processing for +particular cases. An extended example is given in the +examples tar file available from the \isisx web page; +see the files +\begin{verbatim} + scan/scan.sl + scan/scan-demo1.sl + scan/scan-demo2.sl +\end{verbatim} +The first of these files contains some useful and fairly generic \slang\ functions +whose usage is demonstrated in the other two files. + +Here is a simple example of how one might use the function {\tt find\_lines} +(defined in {\tt scan/scan.sl}) to quickly find and plot +the brightest lines in a spectrum. First, copy the contents of the +examples directory a working directory, then run \isis: +\begin{verbatim} + + % load and plot an example spectrum + isis> load_data("obsid_1103_Sky_MEGm1_isis.dat"); + isis> plot_data_counts (1); + + % load the scan functions + isis> .load scan.sl + + % read the Usage message + isis> find_lines; + + % find strong lines in spectrum 1 + isis> (flam, fbin) = find_lines (1, 10); + + % how many lines were found? + isis> n = length (flam); + + % label plot using data values + isis> d = get_data_counts(1); + isis> for (i=0; i < n; i++) { + xylabel(flam[i], d.value[fbin[i]], string(i)); + } +\end{verbatim} +Although the last line is rather long, there's no need to type it +every time. Instead, one could use it to define a \slang\ +function which could then be customized to suit a specific application. + +\section{Comparing line measurements with theory} + +Measurements of line intensity ratios are often used to infer physical +conditions in the emitting plasma. For example, the intensity ratio of +bright lines from different ions of the same element may be used to infer +the relative populations of the different ions, providing a measure of the +ionization balance. Similarly, pairs of lines which arise from the same +upper energy level in a single ion may be used to infer the optical depth; +if one of the lines is optically thick, the branching ratio should differ +from the value expected using the spontaneous transition rates (Einstein A +values) alone. Radiative transitions involving meta-stable states often +provide useful density diagnostics; such states may be identified using +the energy level listing (see {\tt list\_elev}) which includes the total +downward spontaneous radiative transition rate for each level. + +Bright, relatively unblended lines may be selected using the line grouping +functions discussed above (e.g. {\tt brightest}, {\tt unblended}). Lines +which have the same upper energy level may be identified +using the function {\tt list\_branch}; for example, +\begin{verbatim} + atoms(aped); % First load the atomic data + list_branch (Fe, 18); % Fe = 26 +\end{verbatim} +lists branching ratios for Fe XVIII: +\begin{verbatim} +Fe XVIII +upper level = 3 +lower lambda branch A index + 2 1.039370e+02 2.6669e-01 3.3400e+10 14751 + 1 9.392300e+01 7.3331e-01 9.1840e+10 14752 + .... +\end{verbatim} +This listing indicates that, of downward transitions from the third +excited state of Fe XVIII (see the corresponding energy level table), +73\% produce a line at 93.923 \AA~ and 27\% produce a line at 103.937 \AA. + +\begin{figure}[ht] +\putfig{figures/crude_dem} +\caption{Example of estimating the emission measure implied by the flux in a +single line.} +\label{fig:crude_dem} +\end{figure} + +Having identified line ratios which may be of interest, one can plot the +predicted ratio of two lines with indices {\tt n1} and {\tt n2} vs +temperature: + + \begin{verbatim} + plasma(aped); % first load the emissivity tables + t = 10.0^[6.0:7.4:0.05]; % define a log spaced temperature grid + r = ratio_em (n1, n2, t); % compute the ratio + plot(t,r); % plot the ratio vs. temperature + \end{verbatim} + +For a given {\it measured} line ratio, one could read off an estimate of the +plasma temperature. A thorough analysis of a spectrum would normally use +several, or even all, of the observed features to infer a distribution of +physical conditions; for obvious reasons, relying on a single line ratio is +not recommended. + +Alternatively, because the ratio of the measured flux ($F_\lambda$) to the +computed emissivity ($\eta_\lambda(T)$) may be expressed as +\begin{equation} +{ F_\lambda \over \eta_\lambda(T) } = \kappa(T) { \int n_e +n_H~\D V \over 4\pi D^2 }. +\end{equation} +one can generate a crude estimate of the differential emission measure near a +given temperature using the measured flux ({\tt flux\_obs}) in a single line +({\tt "k"}). To plot the measured flux divided by the theoretical emissivity +vs. temperature (Figure \ref{fig:crude_dem}): + \begin{verbatim} + t = 10.0^[6.0:7.9:0.01]; % define a Temperature grid + em = line_em (k,t); % get emissivity vs. temperature for + % line k + i = where(em > 0.0); + plot (t[i], flux_obs / em[i]); % plot the ratio + \end{verbatim} +From this curve, one can read off values proportional to the emission +measure at a given temperature. + +In general, the emitting plasma will occupy a range of temperatures. +To infer the temperature {\it distribution}, more sophisticated +analysis techniques may be required (e.g. differential emission +measure analysis). Although such algorithms are not currently +implemented in \isis, many of the required building blocks are +provided. + +\section{Computing a spectral model using the XSPEC module} + +On systems which have \xspec\ (Arnaud 1996) installed, the \xspec\ +module provides convenient access to selected functions in the +\xspec\ function library. On ELF systems, this module may be +accessible by dynamic linking at \isisx run-time using the \slang\ +\verb|import| function. On such systems, one can explicitly +\verb|import| the module, or it will be automatically imported +when any of the \xspec\ functions is used for the first time. +Alternatively, the \xspec\ module may be also be statically linked +to the \isisx executable so that calling \verb|import| is not +required at all. + +Using this module, most \xspec\ library routines are available +as fit-functions. Selected \xspec\ routines are also available +as S-Lang functions which take the spectrum grid and other +parameters directly as function arguments. Here is an example +showing one way to compute and plot an \xspec\ model spectrum +(Figure \ref{fig:xspec}): + +\verbatiminput{scripts/xspec.sl} + +\begin{figure}[ht] +\putfig{figures/xspec} +\caption{Example XSPEC model plot, illustrating the effect of an $N_H = 1.0 \times +10^{20}$ cm${}^{-2}$ absorbing column on a 5.0 keV "solar" abundance MEKAL +plasma model.} +\label{fig:xspec} +\end{figure} + +Some array-index manipulation was required in this example because the +\isisx convention for representing histograms differs from the +\xspec\ convention. If plotting the model flux vs. the low-edge of each bin would +have been good enough, typing + \begin{verbatim} + require ("xspec"); % (this is optional) + e = 10.0^[-1:1:0.005]; % make a log spaced energy grid + s = _mekal (5.0, e); % 5 keV, solar abundance + plot (e[[0:n-1]], s); + \end{verbatim} +would have produced a similar plot without introducing the +additional variables {\tt lo} and {\tt hi}. + +\section{Global fitting} + +In this section, the term {\it global fit} refers to fitting the +entire range of input data with a plasma model which has a +relatively small number of variable parameters (e.g. a one or two +temperature CIE plasma model). Although global fits to +high-resolution spectra are unlikely to accurately reproduce the +wealth of observed features, a global fit may e.g. provide a quick +estimate of the dominant plasma temperature(s) which are present. +The current version of \isisx supports global fitting with {\sc +XSPEC} models (Arnaud 1996) (see \S\ref{chap:xspec-module}), with +the \isisx built-in fit-functions and with user-supplied fit +functions. Global fits using spectral models generated using the +spectroscopy database are supported via the \verb|create_aped_fun| +function which can create a custom fit-function with +fit-parameters defined by relatively simple data structure +(see \verb|create_aped_fun| for further details). + +\index{background!options} +After loading the data and assigning the appropriate instrument +responses, a background component can be included from a file +(\verb|define_back|), from \slang\ variables (\verb|_define_back|) +or from a user-defined function (\verb|back_fun|). Background +subtraction may also be done ``by hand'' using a user-defined +function such as this: +\verbatiminput{scripts/bgd_subtract.sl} +Fitting is then carried out using the same sequence of steps +described in \S\ref{subsec:simpleexample}. + +\section{Examining ionization balance curves} + +Much of the temperature dependence of emission lines in collisional +ionization equilibrium comes from the temperature dependence of the +ion concentration. + +To examine ionization balance curves, first initialize the spectroscopy database +so that an ionization balance table is loaded + \begin{verbatim} + plasma (aped); + \end{verbatim} +Then plot the ionization fraction of Fe XVII vs. temperature (Figure +\ref{fig:ion_frac}): + +\begin{figure}[ht] +\putfig{figures/ion_frac} +\caption{Example plot of Fe XVII ion fraction vs. temperature.} +\label{fig:ion_frac} +\end{figure} + +\begin{verbatim} + t = 10.0^[6.0:7.2:0.05]; % define a log spaced temperature grid (K) + limits; % reset the plot limits + frac = ion_frac(Fe, 17, t); % assuming Fe = 26 defined in ~/.isisrc + plot (t,frac); + + label ("Temperature [K]", "Ion Fraction", ""); % label axes +\end{verbatim} + +The {\tt plot()} function used in this example allows plotting any set of +X-Y points held in \slang\ arrays; a similar function {\tt hplot()} is +provided for plotting arbitrary histograms. As a trivial example of the +usefulness of this feature, the above plot could be regenerated vs. +temperature in keV by typing +\begin{verbatim} + limits; + K_per_keV = 1.16e7; % conversion factor + plot ( t / K_per_keV, frac); +\end{verbatim} +to apply the conversion factor to the temperature array before plotting. + +In these example, the array of ion fractions returned by {\tt ion\_frac} is +first stored in a variable before being passed to the plot function; this +is especially useful if the array values will be used in further calculations. +The intermediate variable is not necessary however: +\begin{verbatim} + plot (t, ion_frac(Fe, 17, t)); +\end{verbatim} +produces the same result -- here, the array returned by {\tt ion\_frac} is +passed directly to the {\tt plot} function. + +To compare the relative concentrations of ions of different elements +as a function of temperature (Figure \ref{fig:ion_bal}): + +\begin{verbatim} + (i_fe, f_fe) = ion_bal (Fe, 1.e7); % Fe at T = 1.e7 K + (i_ca, f_ca) = ion_bal (Ca, 1.e7); % Ca at T = 1.e7 K + limits; % reset the plot limits + hplot (i_ca-0.5, i_ca+0.5, f_ca); % plot as histograms + ohplot (i_fe-0.5, i_fe+0.5, f_fe); % over-plot Fe on Ca + xrange(14,26); % pick a better plot range + hplot (i_ca-0.5, i_ca+0.5, f_ca); % re-plot + ohplot (i_fe-0.5, i_fe+0.5, f_fe); % +\end{verbatim} + +\begin{figure}[ht] +\putfig{figures/ion_bal} +\caption{Example plot comparing Fe and Ca ionization balance at $T = 10^7$ K.} +\label{fig:ion_bal} +\end{figure} + +If the current plot device supports it, over-plots are automatically done +in a different color to help simplify complex plots; this feature can be +disabled using {\tt plot\_auto\_color ()}. + +\section{Examining continuum emission components using the spectroscopy +database} + +First, initialize the spectroscopy database to scan the continuum +emissivity tables: + \begin{verbatim} + reset; % reset the global state + plasma (aped); + \end{verbatim} +then, generate a wavelength grid and retrieve the continuum components +for a particular temperature +\begin{verbatim} + (lo, hi) = linear_grid(1, 20, 3000); + p = get_contin (lo, hi, 3.e6); % use T = 3.e6 K + + who; % how many variables are defined? + print (p); % print struct components +\end{verbatim} +{\tt true} is the sum of true continuum components including +continua due to bremsstrahlung, radiative recombination, and +two-photon emission and {\tt pseudo} is the pseudo-continuum of weak +emission lines. + +Now, plot the components for comparison +\begin{verbatim} +ymax = max ([p.true, p.pseudo]); % set the plot range +yrange (ymax*1.e-4, ymax); % so all components fit +ylog; + +hplot (lo, hi, p.true); +label ("Wavelength [Angstrom]", + "log Flux [photon cm\\u3\\d s\\u-1\\d]", + "T = 3.0e6 K"); +ohplot (lo, hi, p.pseudo); + +q = get_contin (lo, hi, 3.e6, 1.0e-3, O); % Contribution from Oxygen +ohplot (lo, hi, q.true); +ohplot (lo, hi, q.pseudo); +\end{verbatim} + +The fields of struct {\tt p} can be used in further calculations. For +example, one can integrate the various emission components over the +wavelength range of interest to determine the various continuum +contributions: +\begin{verbatim} +isis> e_erg = 1.988e-8/(0.5*(lo+hi)); % photon energy at bin center +isis> tot_true = sum(e_erg * p.true); % sum over bins +isis> tot_true; % print the value +\end{verbatim} + +\begin{figure}[ht] +\putfig{figures/contin} +\caption{Example of plotting continuum emission components for a solar abundance plasma at $T = 3 \times 10^6$ K.} +\label{fig:contin} +\end{figure} + +\section{Modeling Event Pileup in CCD Detectors} +\label{sec:pileup} + +For a detailed discussion of the pileup model see Davis (2001), +available on the web from +\begin{verbatim} + http://space.mit.edu/~davis/pileup2001.html +\end{verbatim} +See \S\ref{pileup-help} for a suggestion on how to speed up +the pileup model computations. +This section provides a brief example showing how to use the +model to fit CCD data. + +For an on-axis point source, extract counts in a circular region +with a radius of about four pixels; this will enclose +about 95\% of the encircled energy. A larger extraction +region will enclose more source counts but will also increase +the background level. + +Then, in \isisx issue the appropriate commands to load the data, e.g., +\begin{verbatim} + () = load_data ("data.fits"); + () = load_arf ("arf.fits"); + assign_arf (1,1); + () = load_rmf ("rmf.fits"); + assign_rmf (1, 1); +\end{verbatim} +Equivalently, one could use: +\begin{verbatim} + load_dataset ("data.fits", "rmf.fits", "arf.fits"); +\end{verbatim} + +Now group the data bins, e.g. use +\begin{verbatim} + group_data (1, 12); +\end{verbatim} +to group every 12 pha channels together. + +Then specify a model, e.g., +\begin{verbatim} + require ("xspec"); % this is optional + fit_fun ("wabs(1)*powerlaw(1)"); +\end{verbatim} + +Now indicate that you want to fit this data set using pileup: +\begin{verbatim} + set_kernel (1, "pileup"); +\end{verbatim} + +Finally, edit the parameters: +\begin{verbatim} + edit_par; + list_par; +\end{verbatim} + +This will produce something like: +\begin{verbatim} +wabs(1)*Powerlaw(1) + idx param tie-to freeze value min max + 1 wabs(1).NH_22 0 0 0.01 1e-5 0.1 + 2 Powerlaw(1).norm 0 0 0.003 1e-5 0.01 + 3 Powerlaw(1).alpha 0 0 1 0 0 + 4 pileup.<1>nregions 0 1 1 1 1.5 + 5 pileup.<1>g0 0 1 1 0 1 + 6 pileup.<1>alpha 0 0 0.5 0 0.75 + 7 pileup.<1>psffrac 0 1 0.95 0.9 1 +\end{verbatim} + +The \verb|pileup<1>| parameters are specific to the pileup model and the +number in angle-brackets (\verb|"<>"|) is the data-set index, e.g. here +indicating that the pileup model is being applied to data set 1. +For an on-axis point source, allow only \verb|alpha| to vary, leaving +\verb|psffrac| fixed at 0.95. This indicates that 95 percent +of the encircled energy in the extraction region fell within the +central 3x3 pixel. + +Finally, run the fit: +\begin{verbatim} + () = fit_counts; +\end{verbatim} + +Because the chi-square space is quite complicated, it is advisable +to repeat the fit several times, starting from random parameter +values. To simplify this process, \isisx provides a {\tt +randomize} function to automatically randomize all free +fit-function parameters within the currently specified {\tt +min-max} parameter ranges. It may also be helpful to fit first +using {\tt minim} to locate the neighborhood of the global +minimum and then use {\tt lmdif} to refine the answer. For +example: + +\begin{verbatim} + set_fit_method ("minim"); + loop (3) + { + () = fit_counts; + } + set_fit_method ("lmdif"); + () = fit_counts; +\end{verbatim} + +\part{ISIS Reference Manual \label{part:refman}} + +\chapter{The Spectroscopy Database} +\label{chap:specdb} + +This section discusses the database content, layout and parameter file +definition in some detail and may be of interest primarily to the person +installing \isisx and maintaining the local spectroscopy database. + +\section{Obtaining Spectroscopy Database Files} + +\isisx should be able to read files from the spectroscopy database assembled +by Smith, Brickhouse, Liedahl \& Raymond (2001). These files may be +downloaded from the web at +\begin{verbatim} + http://cxc.harvard.edu/atomdb +\end{verbatim} +The minimum \isisx configuration requires only the line emissivity tables +available from from this web page (see \S \ref{subsec:min-specdb}). + +\section{Organization} + +The structure of the local database is specified to \isisx by +providing directory paths and file names via a S-Lang structure. +Perhaps the most convenient way to specify this structure is by +creating and initializing it using a short S-Lang script; for +example, the following script is included in the \isisx +distribution as \verb|etc/aped.sl|: +\begin{verbatim} +public define aped () +{ + variable db = struct + { + dir, atomic_data_filemap, + abundance, ion_balance, + line_emissivity, continuum_emissivity + }; + + db.dir = "/nfs/atum/d2/houck/isis/data/aped/atomdb"; + db.atomic_data_filemap = "filemap"; + + db.abundance = "APED/misc/Abundances.fits"; + db.ion_balance = "APED/ionbal/MM98_ionbal.fits"; + + db.line_emissivity = "apec_line.fits"; + db.continuum_emissivity = "apec_coco.fits"; + + return db; +} +\end{verbatim} +This script generates an instance of the necessary \slang {\tt +Struct\_Type} containing the path to the spectroscopy database and +the names of files containing the line and continuum emissivities +({\tt apec\_line.fits} and {\tt apec\_coco.fits}), the +ionization balance tables ({\tt MM98\_ionbal.fits}), elemental +abundance tables ({\tt Abundances.fits}) and a filemap listing the +associated atomic-data files containing, among other things, +tables of energy levels and wavelengths of X-ray line transitions. + +In general, such an initialization script is defined only once, +perhaps when \isisx or when a new database is +installed, and is not accessed by the casual user afterward. + +Also, perhaps it is an obvious point, but please keep in mind that the +functionality of \isisx depends on the content of the spectroscopy database +provided by the user. Importantly, this database is {\it not part of +\isisx}. If the database contains little or no information on the wavelength +range of interest, the problem is in the database and not in \isis. + +In general, the spectroscopy database is logically divided into two +sections: 1) an emissivity database containing ionization balance tables and +tables of line and continuum emissivities as a function of plasma state +parameters (e.g. temperature and density and 2) a set of atomic data (energy +levels, emission line wavelengths and transition probabilities for selected +ions of astrophysically abundant elements -- quantities generally +independent of the plasma physical state). This organization is mirrored in +the two commands used to load data from the database (see {\tt atoms} +(\S\ref{sec:atomic-db}) and {\tt plasma} (\S \ref{sec:plasma-db}) below). +The database files are in FITS format and are described in detail in the CXC +Spectroscopy Database ICD. + +Although the atomic data tables are optional, when both data sets are used +together, it is assumed that the emissivity database has been derived from +the atomic database. Depending on the assumed emission model, different +emissivity databases may be derived from the same atomic data set. + +The standard emissivity database assumes collisional ionization equilibrium +as a function of electron temperature $T$ and electron density $n$. +\isisx supports reading several types of files from a collisional ionization +equilibrium spectroscopy database: +\begin{itemize} +\item A line emissivity file containing the + line spectrum for a solar abundance plasma as a function of temperature and + density. Each extension contains the line spectrum at a single +temperature, density combination. +\item A continuum emissivity file containing continua for a solar abundance + plasma as a function of temperature and density. + Continua are available for individual elements, with true-continuum + and pseudo-continuum (weak lines) stored separately; optionally, + continuum components broken down by ion may also be available. +\item A set of cosmic elemental abundance tables in a single FITS file. +\item An ionization balance file containing tables of ionization balance as a + function of temperature. +\end{itemize} + +\isisx also supports reading these files from the atomic database: +\begin{itemize} +\item Wavelength tables -- one per element -- with each extension containing + a list of wavelengths, A-values and energy-level indices for a single ion. +\item Energy level tables -- one per element -- with each extension + containing a list of energy levels for a single ion. +\end{itemize} +The spectroscopy database may be configured in several different ways, +depending on which of these files are available. + +Important technical note: Although \cfitsio\ is capable of reading +gzip-compressed FITS files transparently, the \cfitsio\ implementation first +uncompresses the {\it entire} FITS file into memory before {\it any} read +operation begins (even reading a single keyword from the header is enough). +This presents a severe problem if the {\it uncompressed} FITS file is larger +than the computer memory(!). To avoid problems of this nature, it is best to +uncompress the individual database files before reading them into +\isis. Reading uncompressed files has the added benefit that the files can +be read in more quickly and run-time memory usage is minimized. + +\subsection{Minimal Configuration} +\label{subsec:min-specdb} + +As mentioned above, the contents of the spectroscopy database must be specified +using a S-Lang structure of the form: +\begin{verbatim} + variable db = struct { dir, atomic_data_filemap, + abundance, ion_balance, + line_emissivity, continuum_emissivity + }; +\end{verbatim} +(the name of the structure is arbitrary -- for this example, +we have chosen to call it {\tt db}) +The fields of this structure are strings which provide the +spectroscopy database directory and the names of selected files. +\begin{center} +\begin{tabular}{|l|p{2.4in}|} +\hline +dir & database directory \\ +atomic\_data\_filemap & APEC-format atomic-data filemap \\ +abundance & Table of elemental abundances \\ +ion\_balance & Ionization balance table \\ +line\_emissivity & Table of line emissivities \\ +continuum\_emissivity & Table of continuum emissivities \\ +\hline +\end{tabular} +\end{center} + +Note that it is not necessary to have all of these files available +in order to use the spectroscopy database. The minimal database +configuration requires e.g. only a single line-emissivity table. +In this case, the required database configuration structure may be initialized by +defining only two of the struct fields: +\begin{verbatim} + db.dir = "/data/apec"; + db.line_emissivity = "apec_line.fits"; +\end{verbatim} +We point out that the database files can be placed in any convenient +directory -- for the purpose of this example, we assume the +database is in "/data/apec". + +Once the database configuration structure is defined, the indicated +files are loaded using the functions {\tt plasma} and/or {\tt atoms}. +To load both the atomic data and emissivity tables, use +\begin{verbatim} + plasma (db); +\end{verbatim} +where {\tt db} is the name of the database configuration structure. +Similarly, to load only the atomic-data files, use +\begin{verbatim} + atoms (db); +\end{verbatim} + +Note that the various database files need not all lie in the same +directory tree. If the files lie in different directories, one can +define the directory to be an empty string ({\tt dir = ""}) and +then use the other struct fields to specify the full path to each +file. + +To simplify creating the database configuration structure and to +provide greater versatility, we recommend defining the structure +in a S-Lang function. For example, the full APEC database might +be defined using a function like this: +\begin{verbatim} +public define aped () +{ + variable db = struct + { + dir, atomic_data_filemap, + abundance, ion_balance, + line_emissivity, continuum_emissivity + }; + + db.dir = getenv("ATOMDB"); + if (db.dir == NULL) db.dir = "./"; + + db.atomic_data_filemap = "filemap"; + + db.abundance = "APED/misc/Abundances.fits"; + db.ion_balance = "APED/ionbal/MM98_ionbal.fits"; + + db.line_emissivity = "apec_line.fits"; + db.continuum_emissivity = "apec_coco.fits"; + + return db; +} +\end{verbatim} +Because this subroutine initializes and returns the necessary +structure, the subroutine itself can be used as the argument +of the {\tt plasma} or {\tt atoms} functions. For example, +\begin{verbatim} + plasma (aped); +\end{verbatim} +is exactly equivalent to +\begin{verbatim} + db = aped(); + plasma (db); +\end{verbatim} + +\chapter{Interactive Mode Features} +\label{chap:interactive} + +\section{Command Line Editing} + +If \isisx was compiled with GNU \verb|readline|, the command +line editing features are those provided by GNU +\verb|readline|; see the GNU \verb|readline| documentation for +details. The editing features discussed below are those +provided by the native S-Lang interpreter. To select the +command-line behavior, use \verb|set_readline_method|. + +{\tt emacs}-style command line editing is supported. The cursor +movement keys can be used to navigate the command history as can +the following the control sequences: + +\begin{center} +\begin{tabular}{|l|p{4.5in}|} +\hline +ctrl-a & beginning of line \\ +ctrl-e & end of line \\ +ctrl-b & cursor left \\ +ctrl-f & cursor right \\ +ctrl-p & previous command \\ +ctrl-n & next command \\ +ctrl-d & delete the character under the cursor (also exits \isisx if it + is the only character typed on the command line) \\ +ctrl-h & delete the character to left of the cursor (or use the delete key) \\ +ctrl-k & delete to end of line \\ +\hline +\end{tabular} +\end{center} + +Command line editing works well for browsing and editing the history +of single-line commands, but doesn't fully support editing +multi-line commands. + +\section{Control Sequences} + +Several control sequences are available for controlling \isisx +in interactive mode: + +\begin{center} +\begin{tabular}{|l|p{4.5in}|} +\hline +ctrl-c & Halts execution of an \isisx command, returning to the \isisx prompt. + Use {\tt quit} to exit from ISIS. \\ +ctrl-z & Suspend \isisx and return the Unix system prompt. \\ +ctrl-s & XON/XOFF flow control; suspends the terminal\\ +ctrl-q & XON/XOFF flow control; un-suspend the terminal\\ +\hline +\end{tabular} +\end{center} + +\section{Unix Shell Escapes} + +\index{"!|see{shell escapes}} +\index{shell escapes} +If the first character on the command line is an exclamation +point(!), the remainder +of the line is passed to the Unix Bourne shell {\tt /bin/sh}. For example, +the following commands are equivalent: +\begin{verbatim} + isis> !ls .. + isis> ()=system("ls .."); +\end{verbatim} + +Because the Unix Bourne shell parses the command string, +csh-like special characters are not understood: +\begin{verbatim} + isis> !ls ~ % fails; Bourne shell doesn't understand '~' + isis> !ls src/*.fits % works; Bourne shell understands `*' + isis> !ls $HOME % works; Bourne shell understands `$HOME' +\end{verbatim} +Unix shell aliases are also unavailable because shell configuration files +(e.g. \verb|~/.cshrc|) are {\it not} invoked. + +The {\tt cd} (change directory) command is an exception. Because the +string argument of the {\tt cd} command is {\it not} interpreted by a Unix +shell, the specified directory path must be given explicitly without +making use of any environment variables or wildcard characters: +\begin{verbatim} + isis> !cd .. % works; '..' is a real directory + isis> !cd $HOME % fails; unless there is a directory named $HOME +\end{verbatim} + +\section{Command Shortcuts} +\label{sec:shortcuts} + +In interactive-mode, if the first character on the command line is a +period (.) the next non-blank characters are interpreted as a shortcut +command name and the rest of the line supplies whitespace-delimited +arguments for that command shortcut (if any). + +\begin{isisfunction} +{.apropos} % function +{Shortcut for the apropos() function} % synopsis +{.apropos string} % usage +{apropos} % see also + +See the documentation for the S-Lang {\tt \_apropos} intrinsic function +for details; the only difference between the shortcut and the +intrinsic function is that intrinsic function provides namespace and +filter arguments which are not supported by the shortcut command. +In particular, both support S-Lang regular expressions. + +\begin{verbatim} +For example: + +isis> apropos data +Found 29 matches: +all_data copy_data_keywords delete_data +get_data get_data_backscale get_data_counts +get_data_exposure get_data_flux get_data_info +group_data have_data list_data +load_data oplot_data oplot_data_counts +oplot_data_flux plot_data plot_data_counts +plot_data_flux put_data put_data_counts +put_data_flux rebin_data rebin_dataset +set_data_backscale set_data_color set_data_exposure +set_data_info unset_data_color +isis> +\end{verbatim} +\end{isisfunction} + +\begin{isisfunction} +{.cd} +{change \isisx working directory while in interactive-mode} +{.cd path} +{chdir} +This is the same as using the Unix shell-escape (see below) to +change directories: +\begin{verbatim} + isis> !cd .. +\end{verbatim} +Because the argument is not evaluated by the Unix shell, wildcards +and environment variables may not be used. +\end{isisfunction} + +\begin{isisfunction} +{.help} +{Shortcut for the help() function} +{.help topic} +{apropos, help} +See the documentation for the {\tt help} intrinsic function. +\end{isisfunction} + +\begin{isisfunction} +{.load} +{run a \slang\ script in interactive-mode} +{.load filename} +{.source, evalfile} + +This is an interactive-mode shortcut for the \slang\ intrinsic function {\tt +evalfile()} which interprets a file containing \slang\ code. For example, +the following commands are almost equivalent: +\begin{verbatim} + isis> .load script.sl + isis> ()=evalfile("script.sl"); +\end{verbatim} +The only difference is that {\tt evalfile()} returns an integer status code +to indicate whether or not the file was interpreted successfully (1 for +success, 0 for failure); the {\tt .load} command does not return a status +code and is only available in interactive-mode. + +The ``{\tt .sl}'' extension on the script name is optional. + +\end{isisfunction} + +\begin{isisfunction} +{.source} +{read \slang\ commands from a file} +{.source filename} +{.load, evalfile} + +This function is very similar to the {\tt .load} shortcut except that +lines from the file are interpreted as though they had been typed at the +command line -- all command shortcuts are available and variables need +not be declared before use. +\end{isisfunction} + +\chapter{ISIS Function Reference} +\label{chap:funcref} + +This chapter documents all parameters and functionality of all \isisx +intrinsic functions; related functions are grouped together in separate +sections. Valid functions may be \isisx intrinsics (e.g. {\tt load\_data}) +or \slang\ intrinsics (e.g. {\tt message}). Only \isisx intrinsic +functions are described here; see the \slang\ documentation for a +description of the available \slang\ functions. + +Many \isisx functions take a variable number of arguments. In the +following descriptions, optional arguments are enclosed in brackets +([]). Similarly, the notation {\tt [o]plot} is intended to stand for +either {\tt plot} or {\tt oplot}. + +The \isisx interactive help system supplies function name lookup ({\tt +apropos}) as well as more extensive documentation (({\tt help}). For +quick-reference, most \isisx functions display a usage message when invoked +with no arguments (\slang\ intrinsics do not). + +%\begin{isisfunction} % a template +%{} % name +%{} % synopsis +%{} % usage +%{} % see also +%\end{isisfunction} + +\newpage +\section{Utility Functions} + +A number of utility functions are provided for execution control ({\tt +quit}, {\tt reset}), customization ({\tt alias}), and help ({\tt apropos}, {\tt +help}). Repetitive tasks may be simplified by first logging an +interactive session (see \verb|start_log|, \verb|stop_log|, +\verb|save_input|) and +then editing the log-file to produce one or more scripts to handle +subsequent repetitions. + +\begin{isisfunction} +{\_A} +{Convert grids between \\Angstrom and keV} +{\_A (lo[, hi]) } +{} + +This simple function can convert either one or two numerical +arguments from \\Angstrom wavelength units to keV energy units +or the reverse. For array input, the returned arrays have +the same numerical sort order as the input array, making it +convenient to convert an array of energies to an array of +wavelengths, each in increasing order. + +\begin{verbatim} + Example: + + isis> e_kev = [1,2,3]; + isis> print(_A(e_kev)); + 4.132806e+00 + 6.199209e+00 + 1.239842e+01 + isis> lo_kev = [1,2,3]; + isis> hi_kev = [2,3,4]; + isis> (lo_angstrom, hi_angstrom) = _A(lo_kev, hi_kev); + isis> print(lo_angstrom); + 3.099605e+00 + 4.132806e+00 + 6.199209e+00 + isis> print(hi_angstrom); + 4.132806e+00 + 6.199209e+00 + 1.239842e+01 +\end{verbatim} + +When the function argument is a \verb|Struct_Type| of the +form +\begin{verbatim} + struct {bin_lo, bin_hi, value, err}, +\end{verbatim} +the arrays \verb|bin_lo, bin_hi| are converted as above +and the \verb|value| and \verb|err| arrays are reversed. +This allows one to use the \verb|_A| function in conjunction +with the various routines that handle these structures. +For example: + +\begin{verbatim} + d = get_data_counts(1); + hplot(_A(d)); +\end{verbatim} + +\end{isisfunction} + +\begin{isisfunction} +{\_featurep} +{Test whether or not a feature is present} +{Int\_Type \_featurep (String\_Type feature)} +{require, provide} + +The \verb|_featurep| function returns a non-zero value if the +specified feature is present. Otherwise, it returns 0 to indicate +that the feature has not been loaded. + +\end{isisfunction} + +\begin{isisfunction} +{add\_help\_file} +{Add a documentation file to the list searched by help} +{add\_help\_file (file)} +{help, apropos, add\_help\_hook} + +When search for documentation on a given symbol, isis searches +a list of ascii-format files and can also call a number of +user-supplied functions which also search for help. + +\verb|add_help_file| prepends a file to the list of +ascii-format documentation files which are searched to find +help on a specified topic. + +\end{isisfunction} + +\begin{isisfunction} +{add\_help\_hook} +{Add a function to display user-supplied help information} +{add\_help\_hook (name)} +{help, apropos, add\_help\_file} + +When search for documentation on a given symbol, isis searches +a list of ascii-format files and can also call a number of +user-supplied functions which also search for help. + +\verb|add_help_hook| adds to the list of functions which search +for help and display the search results. + +\end{isisfunction} + +\begin{isisfunction} +{add\_to\_isis\_load\_path} +{Add a directory to the file search path} +{add\_to\_isis\_load\_path ("dir")} +{get\_isis\_load\_path} + +{\tt add\_to\_isis\_load\_path} prepends a directory to +the script-search path. + +Related functions with fairly obvious definitions are: +\verb|set_isis_load_path|, \verb|prepend_to_isis_load_path|, +\verb|append_to_isis_load_path|. +\index{set\_isis\_load\_path@{\tt set\_isis\_load\_path}} +\index{prepend\_to\_isis\_load\_path@{\tt prepend\_to\_isis\_load\_path}} +\index{append\_to\_isis\_load\_path@{\tt append\_to\_isis\_load\_path}} + +\end{isisfunction} + +\begin{isisfunction} +{add\_to\_isis\_module\_path} +{Add a directory to the module search path} +{add\_to\_isis\_module\_path ("dir")} +{get\_isis\_module\_path} + +{\tt add\_to\_isis\_module\_path} prepends a directory to +the path searched for dynamically linked libraries (.so +files) containing, e.g. compiled modules or user-defined +fit-functions. + +For example, if a user-defined function is contained in a +dynamically linked library at +\verb|/home/joe/modules/libmodel.so|, one could add the directory +\verb|/home/joe/modules/| to the module search path using +\begin{verbatim} + add_to_isis_module_path ("/home/joe/modules"); +\end{verbatim} + +Related functions with fairly obvious definitions are: +\verb|set_isis_module_path|, \verb|prepend_to_isis_module_path|, +\verb|append_to_isis_module_path|. +\index{set\_isis\_module\_path@{\tt set\_isis\_module\_path}} +\index{prepend\_to\_isis\_module\_path@{\tt prepend\_to\_isis\_module\_path}} +\index{append\_to\_isis\_module\_path@{\tt append\_to\_isis\_module\_path}} + +\end{isisfunction} + +\begin{isisfunction} +{alias} +{define an alternate name for an intrinsic function} +{alias ("oldname","newname")} +{who} + +After defining an alias for an intrinsic function, the function can be +accessed using either the new name or the original name. +\end{isisfunction} + +\begin{isisfunction} +{any} +{Check for non-zero array elements} +{any (x[])} +{where, howmany} + +\verb|any| is a boolean function which returns non-zero if +any elements of its array argument are non-zero. Otherwise, +it returns zero. +\end{isisfunction} + +\begin{isisfunction} +{apropos} %name +{recall object names satisfying a regular expression} %purpose +{apropos("s")} +{.apropos, help, who} + +The apropos function may be used to get a list of all defined objects whose +name matches the regular expression {\tt "s"}. +\begin{verbatim} +For example: + +isis> apropos ("load"); +Found 13 matches: +add_to_isis_load_path autoload get_isis_load_path +load_alt_ioniz load_arf load_conf +load_data load_fit_method load_fit_statistic +load_kernel load_model load_par +load_rmf +isis> + +\end{verbatim} +Because all strings generate a match with the empty string ({\tt ""}), this +can be used to obtain a list of almost all available \isisx intrinsic +functions. +\end{isisfunction} + +\begin{isisfunction} +{array\_struct\_field} %name +{Make an array from one field of an array of Struct\_Type} %purpose +{a[] = array\_struct\_field (Struct\_Type[], "field\_name")} %usage +{print} + +For example: +\begin{verbatim} + isis> d=load_data ("pha2.fits"); + Reading: ............ + isis> info = get_data_info(d); + isis> part = array_struct_field(info, "part"); + isis> part; + Integer_Type[12] +\end{verbatim} + +\end{isisfunction} + +\begin{isisfunction} +{delete} %name +{un-initialize a variable} %purpose +{delete (["pattern"])} %usage +{who} + +All variables whose names contain {\tt "pattern"} are un-initialized; if if +{\tt "pattern"} is absent, all currently defined variables are +un-initialized. +\begin{verbatim} +For example: + + isis> x=[1,2,3,4]; % define 3 variables + isis> y=&x; + isis> z=x*3.0; + isis> who; % verify they exist + x: Integer_Type[4] + y: &x + z: Double_Type[4] + isis> delete; % delete all 3 + isis> who; + x: *** Not Initialized *** + y: *** Not Initialized *** + z: *** Not Initialized *** +\end{verbatim} +\end{isisfunction} + +\begin{isisfunction} +{atexit} %name +{Register a function to be called when ISIS exits} %purpose +{atexit (\&fcn)} %usage +{ } + +Use this function to indicate that a particular function should +be called when ISIS exits. The function will be called with +no arguments and should return nothing. + +If several such functions are specified, the functions will be +called in reverse order. If a slang error occurs when one of +the functions is called and if that error is not cleared, the +remaining functions registered with \verb|atexit| will not be +called. + +For example: +\begin{verbatim} +isis> define cleanup1 () {message ("called cleanup1");} +isis> define cleanup2 () {message ("called cleanup2");} +isis> atexit (&cleanup1); +isis> atexit (&cleanup2); +isis> exit; +called cleanup2 +called cleanup1 +\end{verbatim} + +\end{isisfunction} + + +\begin{isisfunction} +{chdir} %name +{Change directories} %purpose +{s = chdir (dir)} %usage +{ } + +If successful, this function returns \verb|s=0|, +otherwise it returns \verb|s=-1|. +\end{isisfunction} + +\begin{isisfunction} +{fft} %name +{Compute the discrete Fourier transform of a complex array} %purpose +{X[] = fft (x[], sign)} %usage +{fft1d} +\begin{verbatim} + fft(x, sign)[k] = sum_j( x[j] * exp(sign* 2*PI*i *j*k / length(x)) ) + /sqrt(length(x)) + +\end{verbatim} +where \verb|sign| is \verb|+1| or \verb|-1|. +\end{isisfunction} + +\begin{isisfunction} +{fft1d} %name +{Compute the discrete 1D Fourier transform} %purpose +{(R, I) = fft1d (re, im, sign)} %usage +{fft} + +{\it This function is deprecated:} \verb|fft1d| is essentially the +same function as \verb|fft| except that it handles the real and +imaginary parts separately. See \verb|fft| for details. +\end{isisfunction} + +\begin{isisfunction} +{finite} %name +{Return boolean array indicating which array values are finite} %purpose +{w[] = finite (x[])} %usage +{ } + +Finite array values are those which for which +\begin{verbatim} + x[i] != NaN and |x[i]| != Infinity +\end{verbatim} + +\begin{verbatim} +For Example: + x = urand(100) - 0.5; + y = log(x); + i = where(finite(y)); +\end{verbatim} + +\end{isisfunction} + +\begin{isisfunction} +{get\_isis\_load\_path} +{Get the current script load path} +{value = get\_isis\_load\_path ()} +{add\_to\_isis\_load\_path} + +When loading scripts, \isisx searches directories specified in the +current load path which, by default, is initialized using the +{\sc ISIS\_LOAD\_PATH} and {\sc SLANG\_LOAD\_PATH} environment +variables. {\tt get\_isis\_load\_path} retrieves this search path. +\end{isisfunction} + +\begin{isisfunction} +{get\_isis\_module\_path} +{Get the value of the current module search path} +{value = get\_isis\_load\_path ()} +{add\_to\_isis\_load\_path} + +When loading scripts, \isisx searches directories specified in the +current module path which, by default, is initialized using the +{\sc ISIS\_MODULE\_PATH} and {\sc SLANG\_MODULE\_PATH} environment +variables. {\tt get\_isis\_module\_path} retrieves this search +path. +\end{isisfunction} + +\begin{isisfunction} +{grand} +{Generate Gaussian-distributed random numbers} +{nums = grand ([n [,m ...]])} +{urand, prand, seed\_random} +\index{Random numbers!Gaussian} + +If no arguments are given, a single random number will be +generated. If N integer arguments are provided, they +are interpreted as defining the dimensionality of an +array which is to be populated with random numbers. + +For example: +\begin{verbatim} + x = grand(); % returns Double_Type + a = grand(10); % returns Double_Type[10] + b = grand(100,200); % returns Double_Type[100,200] +\end{verbatim} + +\end{isisfunction} + +\begin{isisfunction} +{help} %name +{Retrieve help on \isisx and \slang\ intrinsics} %purpose +{help ("string")} %usage +{apropos, who} +\index{?@{\tt ?}} + +If the string argument matches the name of a documented function, +the documentation for that function is displayed. + +If no documentation is found, the function prints a list of \slang\ +and \isisx intrinsic function names containing the string argument. +The function list is the same as would be obtained using the apropos +function with {\tt flags = 0xF}. Because all strings generate a match +with the empty string ({\tt ""}), an empty topic string can be used to +obtain a list of all available intrinsic functions. + +A usage message is generated if no topic string is specified. + +\end{isisfunction} + +\begin{isisfunction} +{histogram} +{Bin scatter data into a histogram} +{nx = histogram(x, lo [, hi[, \&rev]])} +{hplot, histogram2d, linear\_grid, make\_hi\_grid} + +Given $M$ values, $x_m$, and a set of $K$ bins, $[x_k^{\rm lo}, +x_k^{\rm hi})$, this function computes the number of values, $n_x$, +falling within each bin, such that $x_k^{\rm lo} <= x < x_k^{\rm +hi}$. It is assumed that $x_{k-1}^{\rm hi} = x_k^{\rm lo}$, +e.g. the grid has no holes. + +If this function is called with only 2 arguments, a default +\verb|hi| grid is constructed such that +\begin{verbatim} + hi = [lo[[1:K-1]], DBL_MAX]. +\end{verbatim} +This ensures that the last bin is an ``overflow bin'' containing +the number of values $x_m >$~\verb|lo[K-1]|. + +If present, the last optional argument is used to return an +array of arrays. Each array element is an array containing the +indices of the values falling into the corresponding bin. In +other words, using the above notation, \verb|rev[k]| is an +array listing the members of bin \verb|k|, so that +\verb|length(rev[k]) = nx[k]|. + +For example: +\begin{verbatim} + % Bin some Gaussian distributed random values: + (lo,hi) = linear_grid (-5,5,1024); + x = grand (10000); + nx = histogram (x, lo, hi); + hplot (lo, hi, nx); + + % Demonstrate the reverse-index array: + x = grand(10); + (lo, hi) = linear_grid (-2,2,5); + variable rev; + nx = histogram (x, lo, hi, &rev); + m = array_map (Int_Type, &length, rev); + + print(m); + => 1 + 1 + 6 + 2 + 0 +\end{verbatim} +\end{isisfunction} + +\begin{isisfunction} +{histogram2d} +{Bin scatter data into a 2-D histogram} +{num[,] = histogram2d (x[], y[], xgrid[], ygrid[] [, \&rev])} +{histogram, plot\_contour, plot\_image} + +Given $M$ points, ($x_m$, $y_m$), and a grid for each +coordinate axis $(xgrid_j, ygrid_k)$, +this function computes the number of points, $N(j,k)$, +falling within each bin, such that +$xgrid_j <= x < xgrid_{j+1}$ for $j=0,N_j-1$ and +$ygrid_k <= y < ygrid_{k+1}$ for $k=0,N_k-1$. +The last bin in each row or column is an overflow bin +such that its upper limit is at infinity. + +If present, the optional argument is used to return an array of +arrays such that \verb|rev[i,j]| contains a list of the indices +of the values that went into bin \verb|[i,j]|. +\end{isisfunction} + +\begin{isisfunction} +{howmany} +{Count non-zero array elements} +{n = howmany (x[])} +{where, any} + +This function returns the number of non-zero elements in +the specified array. + +\end{isisfunction} + +\begin{isisfunction} +{hypot} %name +{Compute the hypotenuse} %purpose +{r = hypot (x,y)} %usage +{} +As usual, r = sqrt(x*x + y*y). +\end{isisfunction} + +\begin{isisfunction} +{isis\_get\_pager} %name +{Retrieve the current pager definition string} %purpose +{s = isis\_get\_pager ()} %usage +{isis\_set\_pager} + +\end{isisfunction} + +\begin{isisfunction} +{isis\_set\_pager} %name +{Specify how extensive text output should be displayed} %purpose +{isis\_set\_pager ("pager\_command")} %usage +{isis\_get\_pager} + +By default, ISIS uses the program specified by the \verb|PAGER| +environment variable to display extensive text output such as ISIS +documentation and tables of emission line parameters. This +behavior can be changed by providing a different pager definition. +For example, to have text information displayed in a separate +window which is opened automatically, do something like this +(assuming your favorite pager program is \verb|most|) +\begin{verbatim} + isis_set_pager ("cat > /tmp/isis.help; xterm -e most /tmp/isis.help &"); +\end{verbatim} +To simply dump text output to the screen, use +\begin{verbatim} + isis_set_pager ("cat"); +\end{verbatim} +To revert to the default behavior, do +\begin{verbatim} + isis_set_pager (NULL); +\end{verbatim} +\end{isisfunction} + +\begin{isisfunction} +{linear\_grid} %name +{generate a linear histogram grid} %purpose +{(binlo[], binhi[]) = linear\_grid (min, max, nbins);} %usage +{make\_hi\_grid} +This function generates a linear grid of histogram bins +such that +\begin{verbatim} + binlo[0] = min + binhi[nbins-1] = max + binhi[j] - binlo[j] = (max - min) / nbins + binhi[j] = binlo[j+1] for j=0,1,...nbins-2 +\end{verbatim} +For example, to generate a wavelength grid with 1000 bins +extending from 1-20 \AA, type +\begin{verbatim} + (lo, hi) = linear_grid (1, 20, 1000); +\end{verbatim} +\end{isisfunction} + +\begin{isisfunction} +{make\_hi\_grid} %name +{Use a single grid array to define a histogram grid} %purpose +{hi[] = make\_hi\_grid (lo[]);} %usage +{linear\_grid} + +Given a grid which provides the lower bin edges of +a histogram grid, the high edges are defined as +\begin{verbatim} + hi[[i:n-1]] = [ lo[[1:n-1]], 2*lo[n-1] - lo[n-2] ]; +\end{verbatim} +so that the last two bins have the same width. + +\end{isisfunction} + +\begin{isisfunction} +{mean} %name +{Find the average value of an array} %purpose +{avg = mean (array)} %usage +{median, moment} +\end{isisfunction} + +\begin{isisfunction} +{median} %name +{Find the median value of an array} %purpose +{m = median (array)} %usage +{mean, moment} +\end{isisfunction} + +\begin{isisfunction} +{moment} %name +{Generate statistics for an array} %purpose +{Struct\_Type = moment (array)} %usage +{median, mean} +For example: +\begin{verbatim} +isis> x=grand(1000); % Gaussian random numbers +isis> s = moment(x); +isis> print(s); + num = 1000 % number of values + ave = -0.00860764 % average + var = 0.918971 % variance + sdev = 0.95863 % standard deviation + sdom = 0.0303145 % std dev. of the mean + min = -2.8576 % smallest + max = 2.82887 % largest +\end{verbatim} +\end{isisfunction} + +\begin{isisfunction} +{prand} +{Generate Poisson-distributed random values} +{x = prand (rate [,num])} +{grand, prand, seed\_random} +\index{Random numbers!Poisson} +If called with a single argument, this function returns an +equal-sized array of Poisson-distributed random values. +\begin{verbatim} +Example: + isis> print(prand([3,3,3])); + 1.000000e+00 + 0.000000e+00 + 8.000000e+00 +\end{verbatim} +If called with two scalar arguments, the specified number +of random values are chosen from the Poisson distribution +corresponding to the given rate. +\end{isisfunction} + +% \begin{isisfunction} +% {print} %name +% {Print the fields of a \slang\ structure, or elements of an array} %purpose +% {print (s)} %usage +% {writecol, who} +% \index{printing struct fields} +% \index{printing array elements} +% +% This function is useful for printing out elements +% of 1- and 2-D arrays and for determining the names and values +% structure fields in interactive mode. +% +% \begin{verbatim} +% Example: +% +% isis> y=line_info(127); % retrieve data on line #127 +% isis> print(y); +% id = 127 +% lambda = 256.318 +% flux = 0 +% Z = 2 +% ion = 2 +% upper = 6 +% lower = 1 +% up_name = +% lo_name = +% \end{verbatim} +% +% This output shows that line 127 happens to be a He~II transition with +% $\lambda = 256.318$ \AA. Although energy level labels are apparently not +% available, this transition connects energy levels 1 and 6 in the He~II +% energy level table. +% \end{isisfunction} + +\begin{isisfunction} +{provide} %name +{Declare that a specified feature is available} %purpose +{provide (String\_Type feature)} %usage +{require, \_featurep} +The \verb|provide| function may be used to declare that a +``feature'' has been loaded. See the documentation for +\verb|require| for more information. +\end{isisfunction} + +\begin{isisfunction} +{quit} %name +{exit \isis} %purpose +{quit} %usage +{exit} +Use this function to exit \isis. It is sometimes useful to have a script +exit and return an error code to the Unix shell; for this, use +{\tt exit (err)}, where {\tt err} is the integer error code. +\end{isisfunction} + +\begin{isisfunction} +{readcol} %name +{Read columns from an ASCII file} %purpose +{(a, b, ....) = readcol (file, [c1, c2, ....])} %usage +{writecol} +\index{ASCII files!reading} +The values \verb|c1|, \verb|c2|, etc. give the column numbers to +be read. For example, to read columns 3 and 6: +\begin{verbatim} + (x, y) = readcol ("ascii.dat", 3, 6); +\end{verbatim} +Lines beginning with a ``\verb|#|'' character are ignored. +\end{isisfunction} + +\begin{isisfunction} +{reset} %name +{reset \isis} %purpose +{reset([force])} %usage +{quit} + +This function frees all allocated memory, closes all plot windows and resets +most internal status variables to their internal defaults, but does {\it +not} reload the user's {\tt .isisrc} file. + +If invoked with no arguments, {\tt reset} prompts the user to confirm the +reset. If invoked with a non-zero value for {\tt force}, no user +confirmation is requested. +\end{isisfunction} + +\begin{isisfunction} +{require} %name +{Make sure a feature is present, and load it if not} %purpose +{require (String\_Type feature [,String\_Type file])} %usage +{provide, \_featurep, evalfile} +The \verb|require| function ensures that a specified ``feature'' is present. +If the feature is not present, the \verb|require| function will attempt to +load the feature from a file. If called with two arguments, the feature +will be loaded from the file specified by the second argument. Otherwise, +the feature will be loaded from a file given by the name of the feature, +with ``\verb|.sl|'' appended. + +If after loading the file, if the feature is not present, +a warning message will be issued. + +Note that ``feature'' is an abstract quantity that is undefined here. + +A popular use of the \verb|require| function is to ensure that a specified +file has already been loaded. In this case, the feature is the +filename itself. The advantage of using this mechanism over using +\verb|evalfile| is that if the file has already been loaded, \verb|require| +will not re-load it. For this to work, the file must indicate that it +provides the feature via the \verb|provide| function. +\end{isisfunction} + +\begin{isisfunction} +{save\_input} %name +{save commands to a disk file} %purpose +{save\_input [("filename")]} %usage +{start\_log, stop\_log, .source} + +If no file name is specified, the command log is saved in the file +{\tt isis.log}. If the log file already exists, the log is +appended to the existing file. +\end{isisfunction} + +\begin{isisfunction} +{seed\_random} +{Seed the random number generator} +{seed\_random (int)} +{urand, grand, prand} +\index{Random numbers!seed value} + +\end{isisfunction} + +\begin{isisfunction} +{set\_readline\_method} +{Select the command prompt readline method} +{set\_readline\_method ("method");} +{} +\index{Readline method} + +Use this function to select how the command-line interface +should behave. + +If \isisx was compiled with GNU \verb|readline|, then GNU +\verb|readline| will manage the command line, providing +command-line editing and other features. + +To use the command-line editing features provided by the +\slang interpreter, use +\begin{verbatim} + set_readline_method ("slang"); +\end{verbatim} + +To turn off the command-line editing features, use +\begin{verbatim} + set_readline_method ("stdin"); +\end{verbatim} +\end{isisfunction} + +\begin{isisfunction} +{shift} %name +{Cyclic permutation of array elements} %purpose +{s[] = shift (s[], num)} %usage +{howmany, any} + +If $num > 0$, the array elements are shifted downward $num$ +positions. If $num < 0$, the array elements are shifted upward +$num$ positions. For example: +\begin{verbatim} +isis> writecol (stdout, x, shift(x,2), shift(x,-2)); + 1 3 4 + 2 4 5 + 3 5 1 + 4 1 2 + 5 2 3 +\end{verbatim} +\end{isisfunction} + +\begin{isisfunction} +{start\_log} %name +{save commands to a disk file} %purpose +{start\_log [("filename")]} %usage +{stop\_log, save\_input, .source} + +If no file name is specified, the log is saved in the file {\tt isis.log}. +If the log file already exists, the log is appended to the existing file. +\end{isisfunction} + +\begin{isisfunction} +{stop\_log} %name +{turn off command logging} %purpose +{stop\_log} %usage +{start\_log, .source} +\end{isisfunction} + +\begin{isisfunction} +{urand} +{Generate Uniformly-distributed random numbers} +{nums = urand ([n [, m ...]])} +{grand, prand, seed\_random} +\index{Random numbers!uniform} + +If no arguments are given, a single random number will be +generated. If N integer arguments are provided, they +are interpreted as defining the dimensionality of an +array which is to be populated with random numbers. + +For example: +\begin{verbatim} + x = urand(); % returns Double_Type + a = urand(10); % returns Double_Type[10] + b = urand(100,200); % returns Double_Type[100,200] +\end{verbatim} + +\end{isisfunction} + +\begin{isisfunction} +{who} %name +{list currently defined variables and functions} %purpose +{who (["pattern"])} %usage +{apropos, print} + +All variables and functions hose names contain {\tt "pattern"} are listed; if if {\tt +"pattern"} is absent, all symbols are listed. +\begin{verbatim} +For example: + + isis> x=[1,2,3,4]; + isis> y=&x; + isis> z=x*3.0; + isis> who; + x: Integer_Type[4] + y: &x + z: Double_Type[4] + isis> +\end{verbatim} +\end{isisfunction} + +\begin{isisfunction} +{writecol} %name +{Write arrays to an ASCII file} %purpose +{writecol (fp, a, b, ....);} %usage +{readcol} +\index{ASCII files!writing} +The first argument may be either a filename or a file pointer. +For example: +\begin{verbatim} + % write to a file: +isis> writecol ("ascii.dat", x, y); + + % write to the screen +isis> x=[1:10]; +isis> writecol (stdout, x,x,x,x,x,x); +1 1 1 1 1 1 +2 2 2 2 2 2 +3 3 3 3 3 3 +4 4 4 4 4 4 +5 5 5 5 5 5 +6 6 6 6 6 6 +7 7 7 7 7 7 +8 8 8 8 8 8 +9 9 9 9 9 9 +10 10 10 10 10 10 +\end{verbatim} +\end{isisfunction} + +\newpage +\section{Handling High Resolution Spectra} +\label{sec:highres} + +\isisx manipulates histogram data in which both bin edges are explicitly +specified, along with data values and uncertainties in each bin. The +input data values in each bin must represent the integral of an +underlying continuous distribution over the bin-width. In other +words, the input data values must be in bin-integral units like {\it +counts} or {\it counts/bin}, rather than bin-density units like {\it +counts/\AA}. Although the {\it input} data values must be in +bin-integral units, the data can be {\it displayed} in either +bin-integral or bin-density units; see {\tt plot\_bin\_density}, {\tt +plot\_bin\_integral}. + +For each input data set, \isisx maintains storage to hold the +associated counts histogram, the flux-corrected data and model spectra +in both flux and counts units; the flux-corrected version of the data +is optional. When folding a spectral model through the instrument +response, \isisx stores both the input spectral model in flux units +and the counts histogram obtained by folding that model through the +instrument response. Either version of the model or data is accessible +through commands such as {\tt get\_data\_counts}, {\tt +plot\_model\_flux}, etc. + +For each dataset, the counts histogram, $D(h)$, is referred to +as \verb|data_counts|. The corresponding predicted counts +histogram, $C(h)$, is referred to as \verb|model_counts| and is +computed according to equation (\ref{eq:model-counts}). +Flux-corrected data, ${\bar S(h)}$, is derived from the counts +histogram, $D(h)$, and the instrument responses according to +equation (\ref{eq:flux-corr}). The term \verb|model_flux| +refers to the bin-integrated spectral model, $S(E)dE$. The term +\verb|convolved_model_flux| refers to the spectrum model +obtained by folding the model, $S(E)dE$ through the instrument +response, $RMF(h,E)$, with unit effective area, $A(E)$. + +\isisx also maintains a separate, rebinned version of the data to +support fitting rebinned data ``on-the-fly''. With \isis, it is not +necessary to run a separate program to generate a rebinned spectrum +file. Because the rebinned data is stored separately from the input +data, reverting to the input grid is a trivial operation. + +When folding data through the instrument response, one can also +rebin the instrument response matrix (RMF) using \verb|rebin_rmf|. +More often, it may be useful to simultaneously rebin the RMF and +the corresonding dataset using \verb|rebin_dataset|. +See \verb|rebin_rmf| for details. + +Histograms may be loaded from FITS Type I or Type II pha files or +from ASCII files (see \verb|load_data|, \verb|define_back|). \isisx +can handle multiple spectra simultaneously; reading successive +files appends the contents of each file to the internal list of +data sets. {\tt list\_data} displays a list of the currently +loaded spectra and {\tt delete\_data} removes items from the list. +Type II pha files can contain both count histograms and +flux-corrected spectra; both are accessible. + +Spectrum plots are generated using {\tt [o]plot\_data\_counts} and +{\tt [o]plot\_data\_flux}; model fits computed on the same grid as the +data may be displayed using {\tt [o]plot\_model\_counts} and {\tt +[o]plot\_model\_flux}. The data values may be accessed using the +functions {\tt get\_data\_counts} and {\tt put\_data\_counts}, and +similar functions for flux-corrected data. Similar functions are +available for obtaining model spectrum values, either in flux-units or +in counts (as usually determined by folding a source spectrum through +the instrument response). + +Effective area functions (ARFs) in both Type I and Type II formats may be +manipulated in a similar way using {\tt load\_arf}, {\tt list\_arf}, {\tt +delete\_arf}, {\tt get\_arf} and {\tt put\_arf}. +Event Redistribution Matrix Functions (RMFs) are accessible using +using {\tt load\_rmf}, {\tt list\_rmf}, {\tt assign\_rmf}, {\tt +unassign\_rmf}, and {\tt delete\_rmf}. +Observed spectra may be ``flux-corrected'' using {\tt flux\_corr}. + +Positions of higher-order spectral features may be displayed using +{\tt lambda\_mth\_order}. + +\begin{isisfunction} +{all\_arfs} %name +{Get a list of indices for all currently loaded ARFs} %purpose +{ids = all\_arfs();} %usage +{load\_arf, delete\_arf, all\_rmfs, all\_data} + +This function is useful when you want to do something to all currently +loaded ARFs. For example +\begin{verbatim} + isis> delete (all_arfs); +\end{verbatim} +\end{isisfunction} + +\begin{isisfunction} +{all\_data} %name +{Get a list of data-set indices for all currently loaded data-sets} %purpose +{ids = all\_data([noticed]);} %usage +{load\_data, exclude, include, ignore, notice} + +This function is useful when you want to do something to all currently +loaded data sets. For example +\begin{verbatim} + % to ignore all data sets + isis> ignore (all_data); + + % to get info on all % data sets + isis> info = get_data_info (all_data); +\end{verbatim} + +If the optional argument (\verb|noticed|) is non-zero, the +function returns only the indices of data sets which have +noticed bins. +\end{isisfunction} + +\begin{isisfunction} +{all\_rmfs} %name +{Get a list of indices for all currently loaded RMFs} %purpose +{ids = all\_rmfs();} %usage +{load\_rmf, delete\_rmf, all\_arfs, all\_data} + +This function is useful when you want to do something to all currently +loaded RMFs. For example +\begin{verbatim} + isis> delete (all_rmfs); +\end{verbatim} +\end{isisfunction} + +\begin{isisfunction} +{assign\_arf} %name +{Assign an ARF to one or more spectra} %purpose +{assign\_arf (arf\_index[], hist\_index[])} %usage +{load\_arf, list\_arf, unassign\_arf, flux\_corr, assign\_rsp} + +After loading an ARF, it may be associated with one or more +histograms by specifying the index of the ARF and the histograms. +This indicates which ARF function should be used when computing +flux-corrected spectra and for fitting. If an RMF is applied, the +ARF and RMF grids must match exactly. + +\begin{verbatim} +Example: + assign_arf (2, 1); % ARF 2 goes with spectrum 1 + + assign_arf (2, [3:6]); % Spectra 3, 4, 5 and 6 should + % use ARF 2 +\end{verbatim} +\end{isisfunction} + +\begin{isisfunction} +{assign\_rmf} %name +{Assign an RMF to one or more spectra} %purpose +{assign\_rmf (rmf\_index[], hist\_index[])} %usage +{load\_rmf, list\_rmf, unassign\_rmf, assign\_rsp} +After loading an RMF, it may be associated with one or more histograms +by specifying the indices of the RMF and the histograms. This indicates +which RMF functions should be used when fitting models to data. +\begin{verbatim} +Example: + assign_rmf (2, 1); % RMF 2 goes with spectrum 1 + + assign_rmf (2, [3:6]); % Spectra 3, 4, 5 and 6 should + % use RMF 2 +\end{verbatim} + +Note that the ARF and RMF grids must match exactly; relative +tolerances on the accuracy of the grid mismatch are controlled by +the intrinsic variable \verb|Rmf_Grid_Tol|. If the RMF grid match +is inexact but ``close enough'' one can suppress grid-mismatch +errors by setting \verb|Rmf_Grid_Tol| to a small positive value. +For example, \verb|Rmf_Grid_Tol=0.001| would indicate that +acceptable mismatches must be smaller than 1 part in 1000. +\end{isisfunction} + +\begin{isisfunction} +{assign\_rsp} %name +{Assign one or more ARF/RMF pairs to one or more spectra} %purpose +{assign\_rsp (arf\_list, rmf\_list, hist\_index\_list)} %usage +{load\_arf, load\_rmf, assign\_arf, assign\_rmf} + +Although \verb|arf_list| and \verb|rmf_list| can refer to a single +ARF or RMF, this function is primarily intended to support +assigning multiple responses to one or more datasets (e.g. for +fitting LETG data which must include contributions from higher +orders). The responses listed are applied pairwise (e.g. {\tt +arf\_list[k]} goes with {\tt rmf\_list[k]}). + +\begin{verbatim} +For example: + % Assuming ARFs 1-10 and RMFs 1-10 correspond to + % responses for dispersed orders 1-10: + assign_rsp ([1:10], [1:10], 1); + + % Assign ARF #2 and RMF #3 to dataset 1. + assign_rsp (2, 3, 1); +\end{verbatim} + +The wavelength grid for the data is taken from the first RMF in +the {\tt rmf\_list}. Therefore, in analyzing data containing +multiple dispersion orders, the first element of {\tt arf\_list} +and the first element of {\tt rmf\_list} should normally +correspond to first-order. + +Generating plots which compare the contribution from different +dispersion orders can be somewhat tricky to generate. +Here's how to examine the 3rd order contribution +to LETG/HRC data using a given spectral model: +\begin{verbatim} + % Assuming ARFs 1-10 and RMFs 1-10 correspond to + % responses for dispersed orders m=1-10: + + assign_rsp ([1:10], [1:10], 1); + + % First overplot the data with a model including + % orders m=1-10. Note that this plot uses the + % 1st order wavelength grid. + + plot_data_counts (1); + () = eval_counts; + oplot_model_counts (1); + + % Now evaluate the 3rd order contribution and + % overplot it using the 1st order wavelength grid + + assign_rsp (3,3, 1); + () = eval_counts; + assign_rsp (1,1, 1); + oplot_model_counts (1); +\end{verbatim} + +Values of \verb|arf_index|=0 or \verb|rmf_index|=0 imply the +corresponding identity response (e.g. ARF=1 or RMF=1). + +\end{isisfunction} + +\begin{isisfunction} +{combination\_members} %name +{Get a list of combined datasets} %purpose +{list = combination\_members (gid)} %usage +{combine\_datasets, match\_dataset\_grids, uncombine\_datasets, get\_combined, rebin\_combined} + +\end{isisfunction} + +\begin{isisfunction} +{combine\_datasets} %name +{Combine several datasets to improve the fit-statistics} %purpose +{gid = combine\_datasets (list [, weights])} %usage +{combination\_members, match\_dataset\_grids, uncombine\_datasets, get\_combined, set\_eval\_grid\_method, rebin\_combined} +\index{Combining datasets} +\index{Coupled sources} + +This function may be used to label several datasets which +should be combined to improve statistics during a model fit. +This function may also be used to help solve coupled systems of +equations describing multiple sources which are only marginally +resolved. + +Datasets to be combined must have identical grids; all spectral +bins must be the same and the same bins must be noticed in +each. Use \verb|match_dataset_grids| to put several datasets +onto a common spectral grid. + +The optional \verb|weights| argument specifies weights which +are used when combining the datasets. In particular, the value +of bin $k$ in the combined dataset is +\begin{equation} + D_k = \sum_i f_i D_{k,i} +\end{equation} +where the sum extends over all datasets and where $f_i$ is the +weight corresponding to dataset $i$. + +The return value is the index of the dataset combination. Multiple +dataset combinations are supported. + +Combining datasets in this way is conceptually equivalent to +summing datasets, but is somewhat more consistent because the +models for the individual datasets are treated consistently for +any fit-kernel. + +For example, the $\chi^2$ fit statistic for the combined +datasets is computed as +\begin{equation} + \chi^2 = \sum_k W_k \left(\sum_i f_i D_{ki} - M_{ki}\right)^2 +\end{equation} +where $D_{k,i}$ and $M_{k,i}$ are the data and model values, +respectively, for bin $k$ of dataset $i$ and where $W_k$ is the +statistical weight for bin $k$ in the combined dataset. For Poisson +statistics, +\begin{equation} + W_k = {1 \over \sum_i f_i D_{ki}}. +\end{equation} + +When working with combined datasets, one can use the +\verb|ignore|/\verb|notice| functions as long as each member is +treated the same way. For example: + +\begin{verbatim} + % create a dataset group: + g = [1, 2, 3, 4]; + match_dataset_grids (g); + gid = combine_datasets (g); + + % ignore the same data-range in every group member + ignore (g, 13.4, 14.2); + + % fit models in the usual way + () = fit_counts; +\end{verbatim} + +One may also combine datasets to analyze data for coupled +sources. For example, consider an observation of 2 sources +(\verb|a,b|) which are only marginally resolved. Suppose the +spectrum model for source (\verb|a|) is \verb|S_A| and +the model for source (\verb|b|) is \verb|S_B|. Separate spectra +(\verb|D_a, D_b|) may be extracted, but each spectrum is +contaminated by the other so that, in general, the 2 datasets +are represented by a system of equations of the form +\begin{verbatim} + D_a = R_Aa * S_A + R_Ba * S_B; + D_b = R_Ab * S_A + R_Bb * S_B; +\end{verbatim} +in which both source models contribute to each dataset through +a set of responses \verb|R_xy|. In this expression, the +products \verb|R*S| are intended as a shorthand notation to +represent folding the source model \verb|S| through the +(possibly nonlinear) instrument response \verb|R|. + +To solve this system of coupled equations, one can do the +following: + +\begin{verbatim} + load_dataset (D_a, R_Aa); % dataset #1 + load_dataset (D_a, R_Ba); % #2 + load_dataset (D_b, R_Ab); % #3 + load_dataset (D_b, R_Bb); % #4 + + weights = [0.5, 0.5]; + + combine_datasets (1,2, weights); + combine_datasets (3,4, weights); + + define coupled_sources_model() + { + switch (Isis_Active_Dataset) + { case 1 or case 3: return S_A(); } + { case 2 or case 4: return S_B(); } + } + + fit_fun ("coupled_sources_model()"); +\end{verbatim} + +Consider how this works for the combination of datasets 1 and +2. Evaluating the coupled source model for dataset 1 yields the +product \verb|R_Aa*S_A| and evaluating it for +dataset 2 yields the product \verb|R_Ba*S_B|. +Combination of the models for datasets 1 and 2 then yields +\begin{verbatim} + R_Aa*S_A + R_Ba*S_B +\end{verbatim} +while the weighted combination of the datasets themselves yields +\begin{verbatim} + 0.5*D_a + 0.5*D_a = D_a. +\end{verbatim} +(And similarly for the combination of datasets 3 and 4). It +follows that minimizing the fit-statistic for all 4 datasets +simultaneously yields the solution to the system of 2 coupled +equations. + +\end{isisfunction} + +\begin{isisfunction} +{copy\_data\_keywords} %name +{Copy keywords values between two data sets} %purpose +{copy\_data\_keywords (to\_id, from\_id)} %usage +{load\_data} + +\end{isisfunction} + +\begin{isisfunction} +{cursor\_counts} %name +{Compute statistics for a given wavelength region} %purpose +{cursor\_counts (hist\_index [, out\_file [, flag]])} %usage +{cursor\_flux, region\_counts, region\_flux }. + +This function is analogous to the {\tt region\_counts} function except that 1) +the input {\tt xmin}, {\tt xmax}, {\tt ymin}, {\tt ymax} values are taken +from reading the cursor position on a data plot and 2) the computed +statistics are automatically saved to a file. If {\tt flag} is one or is not +set, the statistics are continuum subtracted; if {\tt flag} is zero, the +continuum is assumed to be zero. +\end{isisfunction} + +\begin{isisfunction} +{cursor\_flux} %name +{Compute statistics for a given wavelength region} %purpose +{cursor\_flux (hist\_index [, out\_file [, flag]])} %usage +{cursor\_counts, region\_counts, region\_flux }. +See {\tt cursor\_counts}. +\end{isisfunction} + +\begin{isisfunction} +{define\_arf} % name +{Define an ARF using \slang\ arrays} % purpose +{id = define\_arf (Struct\_Type | binlo, binhi, arf, arf\_err)} % usage +{set\_arf\_exposure, set\_arf\_info, get\_arf\_info} + +This function provides a way to define a new ARF using \slang\ +arrays. As input, it accepts 1) a Struct\_Type with fields +\verb|bin_lo, bin_hi, value, err| or 2) a list of four +equal-length arrays with the same data. The \verb|bin_lo|, +\verb|bin_hi| arrays provide a wavelength grid in Angstrom +units, sorted in ascending order. The new ARF is added to the +internal list just as though the data had been loaded from a +FITS data file. Normally, the function returns the integer +index of the new data-set. If the function fails, the return +value is -1. + +Note that when an ARF is defined in this way, one must +set the associated exposure time explicitly using either +\verb|set_arf_exposure| or \verb|set_arf_info|. +\end{isisfunction} + +\begin{isisfunction} +{define\_back} % name +{Define a background spectrum file} % purpose +{status = define\_back (index, "file")} % usage +{define\_counts, define\_flux, load\_data, back\_fun, \_define\_back, get\_back} +\index{background!file} + +Use this function to specify a background spectrum for a data set +(e.g. the $B(h)$ term in equation (\ref{eq:model-counts})). The +background spectrum file format may be either ASCII or OGIP/FITS +Type-I PHA. If the FITS format is used, the BACKSCAL and EXPOSURE +keywords are used to scale the background relative to the data +spectrum. If the ASCII format is used, no re-scaling is performed. + +To unassign the background, use \verb|define_back(index,NULL)|. + +For example: +\begin{verbatim} + () = define_back (1, "background.pha"); +\end{verbatim} + +\end{isisfunction} + +\begin{isisfunction} +{\_define\_back} % name +{Define a background spectrum using \slang\ variables} % purpose +{status = \_define\_back (index, bgd [, area [, exposure]])} % usage +{define\_counts, define\_flux, load\_data, back\_fun, define\_back, get\_back} +\index{background!\slang\ variables} + +Use this function to specify a background spectrum for a data set +(e.g. the $B(h)$ term in equation (\ref{eq:model-counts})). The +optional values of \verb|area| and \verb|exposure| are used to +scale the background relative to the data spectrum. The array +\verb|bgd| containing the background values must be on an +ascending wavelength grid and must match the data set grid; the +\verb|rebin| function may be used to match the grids if +necessary). + +To unassign the background, use \verb|_define_back(index,NULL)|. + +For example: +\begin{verbatim} + bgd_area = 400.0; % extraction region [pixels^2] + bgd_exposure = 4.e4; % exposure time [sec] + () = _define_back (1, bgd_array, bgd_area, bgd_exposure); +\end{verbatim} + +\end{isisfunction} + +\begin{isisfunction} +{define\_counts} % name +{Define a counts-histogram using \slang\ arrays} % purpose +{s = define\_counts (Struct\_Type | bins | [lo, hi,] counts [, err])} % usage +{define\_flux, define\_back} + +This function provides a way to define a new data-set using +\slang\ arrays. As input, it accepts 1) a Struct\_Type with +fields \verb|bin_lo, bin_hi, value, err| or 2) a list of four +equal-length arrays with the same data or 3) a single array +containing only the bin values. The new data-set is +added to the internal list just as though the data had been +loaded from an ascii or FITS data file. Normally, the function +returns the integer index of the new data-set. If the +function fails, the return value is -1. + +The wavelength grid arrays (\verb|bin_lo, bin_hi|) and the +uncertainty (\verb|err|) arrays are optional. If the wavelength +grid arrays are shorter than the \verb|counts| array (or are +missing), they are ignored, and the data grid is assumed to be +supplied by an RMF. If the uncertainty array is shorter than the +\verb|counts| array (or is missing), a default uncertainty array +will be supplied assuming Poisson statistics. +\end{isisfunction} + +\begin{isisfunction} +{define\_flux} % name +{Define a flux-corrected histogram using \slang\ arrays} % purpose +{s = define\_flux (Struct\_Type | lo, hi, flux, err)} % usage +{define\_counts} + +This function is similar to \verb|define_counts| except that +it is used to define a flux-corrected histogram. + +\end{isisfunction} + +\begin{isisfunction} +{delete\_arf} % name +{Delete one or more ARFs from the internal table} % purpose +{delete\_arf (arf\_index\_list)} % usage +{list\_arf} + +This function removes the indicated ARFs from the internal list; it does +{\it not} affect the FITS file containing the ARF. +\begin{verbatim} +Example: + isis> delete_arf (3); + isis> delete_arf ([4,8,9]); +\end{verbatim} +\end{isisfunction} + +\begin{isisfunction} +{delete\_data} %name +{delete spectra from the internal list} %purpose +{delete\_data (hist\_index\_list)} %usage +{ list\_data} +This function removes the indicated spectra from the internal list; +it does not affect the disk files containing the spectra. +\begin{verbatim} +Example: + isis> delete_data (3); + isis> delete_data ([4,8,9]); +\end{verbatim} +\end{isisfunction} + +\begin{isisfunction} +{delete\_rmf} % name +{Delete one or more RMFs from the internal table} % purpose +{delete\_rmf (rmf\_index\_list)} % usage +{list\_rmf} + +This function removes the indicated RMFs from the internal list; it does +{\it not} affect the file containing the RMF definition. +\begin{verbatim} +Example: + isis> delete_rmf (3); + isis> delete_rmf ([4,8,9]); +\end{verbatim} +\end{isisfunction} + +\begin{isisfunction} +{factor\_rsp} %name +{Factor a response matrix (RSP) into an ARF and a normalized RMF} %purpose +{arfs = factor\_rsp (rmfs)} %usage +{load\_rmf, list\_arf, flux\_corr, eval\_flux} +\index{Response Matrices!factorization} +\index{flux-correction!RSP matrix} + +Some response matrices are defined as the product of the +instrument effective area (the ARF) and the instrument +redistribution function (the RMF). + +After loading such a response matrix with \verb|load_rmf|, this +function factors out the effective area and appends the +corresponding ARF function to the internal list of effective +area functions. In the process, the response matrix is +renormalized such that the redistribution function for each +incident photon energy is unit normalized. + +If the function succeeds, it returns the indices of the ARFs +appended to the internal list. If an error occurs, the function +returns -1. + +\begin{verbatim} +EXAMPLE: + + % load a response matrix which includes the + % effective area and the redistribution function + + rsp = load_rmf ("rsp.fits"); + + % factor out the effective area function + % and normalize the redistribution function + + arf = factor_rsp (rsp); + + % assign the ARF and RMF to a dataset of interest + + assign_rmf (rsp, data_index); + assign_arf (arf, data_index); + +\end{verbatim} + +\end{isisfunction} + +\begin{isisfunction} +{fakeit} % name +{Generate fake data using a given model, ARF and RMF} % purpose +{fakeit ([\&noise\_fun])} % usage +{load\_arf, load\_rmf, fit\_fun, set\_frame\_time, set\_arf\_exposure, define\_back, set\_fake} + +This function may be used to generate fake data with user-defined +uncertainties for a list of ARF, RMF pairs (any real datasets +which happen to be loaded at the time will not be overwritten). If +a noise function (\verb|noise_fun|) is not provided, Poisson +statistics are assumed; to generate noiseless data, use +\verb|fakeit (NULL)|. + +For example, to generate a single fake data set, +first load a matching ARF and RMF +and assign them to a non-existent data set index, +causing \isisx to generate an empty data set. +For example: +\begin{verbatim} + load_arf ("arf.fits"); + load_rmf ("rmf.fits"); + + assign_arf (1,1); + assign_rmf (1,1); +\end{verbatim} +Having created an empty data set, the next step is +to populate it with fake data. + +To do that, first define a spectral model using \verb|fit_fun|. +For example, one might use the XSPEC module: +\begin{verbatim} + require ("xspec"); % this is optional + fit_fun ("phabs(1)*mekal(1)"); +\end{verbatim} +Adjust the model parameters to the values desired +for the fake data set. + +Now, use \verb|fakeit| to populate the counts vector +for this data set, plus Poisson errors: +\begin{verbatim} + fakeit; + rplot_counts (1); +\end{verbatim} +Here, we've also used \verb|rplot_counts| to plot the data, +model and residuals. + +A user-defined noise function should take the model value +for a given bin as an argument and return the noise-added +value. For example, to add uniformly +distributed noise with a 10\% amplitude use: +\begin{verbatim} + define my_noise (model_in) + { + variable r = 2.0 * (urand(1) - 0.5); + return model_in * (1.0 + 0.1 * r); + } + + fakeit (&my_noise); +\end{verbatim} + +\end{isisfunction} + +\begin{isisfunction} +{flux\_corr} % name +{Compute the flux-corrected spectrum} % purpose +{flux\_corr (hist\_index [,threshold])} % usage +{flux\_corr\_model\_counts, load\_arf, assign\_arf, unassign\_arf, back\_fun} + +This function computes the ``flux-corrected'' spectrum, ${\bar +S(h)}$, defined by the expression +\begin{equation} + {\bar S(h)} \equiv \frac{ C(h) - B(h)}{t~\int_{\Delta E(h)}\D E~{\cal F}\Bigl(R(h,E), A(E), 1\Bigr)} +\label{eq:flux-corr} +\end{equation} +where $A(E)$ is the effective area (the ARF) at energy $E$, $R(h,E)$ +is the redistribution function (the RMF), $C(h)$ is the number of +source counts in detector bin $h$ and $t$ is the exposure time (from +the ARF EXPOSURE keyword). In this expression, +the fit ``kernel'', ${\cal F}(R, A, s)$ is evaluated for +a constant spectrum, $s(E)=1$, +and defaults to +\begin{equation} + {\cal F}\left(R,A,1\right) = R(h,E)A(E) +\end{equation} +for the standard kernel. The integral spans the energy range, +$\Delta E(h)$, that contributes to detector bin $h$ (e.g. +all energies represented by the response). + +In general, the degree to which this transformation produces a +useful result depends on the condition of the data, the +characteristics of the instrument response and the effect of the +relevant kernel, ${\cal F}$. For the standard kernel, in the limit +that $R(h,E)$ approaches a delta-function, the flux-corrected +spectrum, ${\bar S(h)}$, approaches the model spectrum, $s(E)$. +For example, flux-correcting high-resolution grating spectra +unaffected by photon pileup often provides a good estimate of the +incident spectrum (but uncorrected for blurring due to the line +spread function). With moderate levels of pileup, the +flux-corrected spectrum may also yield a good estimate of the +incident spectrum. For CCD resolution spectra which are +unaffected by photon pileup, the flux estimate may be reasonably +good for energies above $\sim 1$ keV and may be useful for +visualization purposes. But for $E \lesssim 1$ keV, the CCD RMF +becomes rather broad and the resulting estimate ${\bar S(h)}$ may +differ significantly from the incident spectrum $s(E)$. + +Note that the relevant instrumental background, $B(h)$, is +automatically subtracted (if available) to compute the number of +source counts $C(h)$. The flux result is stored separately and +does not over-write the counts histogram. If the counts histogram +is re-grouped or rebinned after being flux-corrected, {\tt +flux\_corr} should be re-run to compute the flux values on the new +grid. + +For the standard fit-kernel, uncertainties on the +flux-corrected spectrum are computed directly from the counts +so that +\begin{eqnarray} + &{\bar S_k} = \frac{C_k - B_k}{I_k} \\ + &\delta{\bar S_k} = \frac{\sqrt{C_k + B_k}}{I_k} +\end{eqnarray} +where $k$ is the bin index and +\begin{equation} +I_k \equiv t~\int_{\Delta E(k)}\D E~R(k,E)A(E) +\end{equation} + +The optional argument {\tt threshold} (= 0.0 by default) specifies the +detection limit in terms of the minimum acceptable signal-to-noise ratio +($S/N = C_k / \delta C_k$); bins which fall below this limit are assigned a +flux of zero. +\end{isisfunction} + +\begin{isisfunction} +{flux\_corr\_model\_counts} % name +{Compute a flux-corrected model spectrum} % purpose +{flux\_corr\_model\_counts (hist\_index [, threshold])} % usage +{flux\_corr, load\_arf, assign\_arf, unassign\_arf, back\_fun} + +This function computes the ``flux-corrected'' model spectrum, +${\bar S^{(m)}(h)}$, defined by the expression +\begin{equation} + {\bar S^{(m)}(h)} \equiv { {\Large\int}_{\Delta E(h)}\D E~{\cal +F}\Bigl(R(h,E), A(E), s(E)\Bigr) + \over \int_{\Delta E(h)}\D E~{\cal +F}\Bigl(R(h,E), A(E), 1\Bigr) } +\end{equation} +where $A(E)$ is the effective area (the ARF) at energy $E$, +$R(h,E)$ is the redistribution function (the RMF) mapping into +detector bin $h$. In the numerator of this expression, the model +counts are predicted using the fit ``kernel'' ${\cal F}(R, A, s)$ +as applied to the model spectrum, $s(E)$. In the denominator, this +``kernel'' is evaluated for a constant spectrum, $s(E)=1$. Recall +that the standard kernel is +\begin{equation} + {\cal F}\left(R,A,s\right) = R(h,E)A(E)s(E). +\end{equation} +The integrals span the energy range, $\Delta E(h)$, that +contributes to detector bin $h$ (e.g. +all energies represented by the response). + +The result, ${\bar S^{(m)}(h)}$, over-writes the internal array +used to store the convolved model flux; to retrieve the +numerical values, use \verb|get_convolved_model_flux()|. + +Because the current implementation works only on an unbinned model +spectrum, the model must be computed on the same grid as the +unbinned data. See \verb|flux_corr| for further details. + +\end{isisfunction} + +\begin{isisfunction} +{get\_arf} % name +{Get numerical values from an ARF} % purpose +{Struct\_Type = get\_arf (arf\_index)} % usage +{put\_arf, list\_arf}. + +This function retrieves an ARF function from the internal list +and loads the data into the fields of a \slang\ structure. + +\begin{verbatim} +arf_index = integer index of ARF in internal list + s.bin_lo = bin left edge [Angstrom] + s.bin_hi = bin right edge [Angstrom] + s.value = ARF value [cm^2 counts/photon] + s.err = ARF uncertainty [cm^2 counts/photon] +\end{verbatim} +\end{isisfunction} + +\begin{isisfunction} +{get\_arf\_info} % name +{Get ARF information} % purpose +{Struct\_Type = get\_arf\_info (id)} % usage +{set\_arf\_exposure, set\_arf\_info, get\_arf\_info} + +This function returns a structure which +contains the values of auxiliary ARF parameters: + +\begin{verbatim} +isis> s=get_arf_info(1); +isis> print(s); + order = -1 + part = 2 + srcid = 0 + exposure = 28123.4 + fracexpo = 1 +\end{verbatim} + +\end{isisfunction} + +\begin{isisfunction} +{get\_combined} +{Retrieve the combined dataset or corresponding model} +{Struct\_Type = get\_combined (gid, \&get\_function)} +{combination\_members, combine\_datasets, uncombine\_datasets, match\_dataset\_grids, rebin\_combined} + +Use this function to obtain the specified dataset combination +or the corresponding model combination. The return value is +a \verb|Struct_Type| of the form +\begin{verbatim} + struct {bin_lo, bin_hi, value, err} +\end{verbatim} +where the (\verb|bin_lo, bin_hi|) fields give the wavelength +grid, the (\verb|value|) field gives the sum of the specified +histograms and the (\verb|err|) field gives the corresponding +uncertainty. These sums are computed using the combination +weights specified via \verb|combine_datasets|: +\begin{equation} + D_k = \sum_i f_i D_{ik} + \delta D_k^2 = \sum_i \left(f_i \delta D_{ik}\right)^2 +\end{equation} +where $D_k$ is the summed value in bin $k$, $f_i$ is the weight +for dataset $i$ and $\delta D_k$ is the uncertainty of $D_k$. +Because models are assumed to be exact, models usually have a +\verb|NULL| value in the \verb|err| field. + +Note that it is assumed that the function used as the second +argument (e.g. \verb|get_function|) returns spectra with +matching grids. Any function returning a result which uses the +data grid is acceptable because \verb|match_dataset_grids| will +ensure that the specified data grids all match. In contrast, +one cannot in general use \verb|get_model_flux| here because +the model flux is computed on the ARF grid and the ARF grids +need not match. + +EXAMPLE: +\begin{verbatim} + + % To plot the sum of the combined datasets + % and over-plot the model for the combination: + + match_dataset_grids (3,4,9,10); + gid = combine_datasets (3,4,9,10); + () = eval_counts (); + + d = get_combined (gid, &get_data_counts); + m = get_combined (gid, &get_model_counts); + + hplot(d); + ohplot(m); + +\end{verbatim} + +Keep in mind that \verb|get_combined| always computes the sum +of vectors provided by the second argument. If those vectors +represent counts, then the computed sum yields the total +counts. However, if those vectors represent flux, then the +computed sum is probably not what was intended -- in this case, +an exposure weighted mean is more likely to be useful. To use +\verb|get_combined| to generate an exposure weighted mean, the +second argument might point to a custom function of this form: + +\begin{verbatim} +define exposure_weighted_model_flux (i) +{ + variable f, info, exposure, weight; + f = get_model_flux (i); + info = get_data_info (i); + exposure = get_arf_exposure (info.arfs[0]); + weight = exposure / Total_Exposure_Time; + f.value *= weight; + return f; +} +mean_flux = get_combined (g, &exposure_weighted_model_flux); +\end{verbatim} + +In this example, it is assumed that the global variable +\verb|Total_Exposure_Time| has been previously computed. + +\end{isisfunction} + +\begin{isisfunction} +{get\_convolved\_model\_flux} %name +{load spectral model into a \slang\ structure} %purpose +{Struct\_Type = get\_convolved\_model\_flux (hist\_index)} %usage +{get\_model\_counts, get\_model\_flux} + +\begin{verbatim} +hist_index = integer index of spectrum in internal list + s.bin_lo = bin left edge [Angstrom] + s.bin_hi = bin right edge [Angstrom] + s.value = bin value [photons/sec/cm^2] + s.err = bin uncertainty [photons/sec/cm^2] +\end{verbatim} + +This function retrieves the specified convolved flux histogram +from the internal list and loads the data into a structure. +Similar functions are available to retrieve counts data and +model values. + +The convolved model flux is computed using the expression +\begin{equation} +F(h) = t \int R(h,E)S(E)dE +\end{equation} + +\end{isisfunction} + +\begin{isisfunction} +{get\_data\_backscale} +{Retrieve the background scaling for a given spectrum} +{area = get\_data\_backscale (hist\_index)} +{set\_data\_backscale} +Returns BACKSCAL keyword from the header for histogram {\tt +hist\_index}. Grating data may have a BACKSCAL vector +of the same length as the data array; note that in this +case, some BACKSCAL values may be zero, corresponding +to wavelength values which fall off of the detector. +\end{isisfunction} + +\begin{isisfunction} +{get\_data\_counts} %name +{load spectral data into a \slang\ structure} %purpose +{Struct\_Type = get\_data\_counts (hist\_index)} %usage +{put\_data\_counts, get\_model\_counts, get\_data\_info} + +\begin{verbatim} +hist_index = integer index of spectrum in internal list + s.bin_lo = bin left edge [Angstrom] + s.bin_hi = bin right edge [Angstrom] + s.value = bin value [counts] + s.err = bin uncertainty [counts] +\end{verbatim} + +This function retrieves the specified counts histogram from the +internal list and loads the data into a structure. Similar +functions are available to retrieve flux-corrected data +and model values. + +\end{isisfunction} + +\begin{isisfunction} +{get\_data\_exposure} +{Retrieve the exposure time for a given spectrum} +{t = get\_data\_exposure (hist\_index)} +{set\_arf\_exposure} +Returns exposure time in seconds from the header for histogram {\tt +hist\_index}. +\end{isisfunction} + +\begin{isisfunction} +{get\_data\_flux} %name +{load spectral data into a \slang\ structure} %purpose +{Struct\_Type = get\_data\_flux (hist\_index)} %usage +{put\_data\_flux, get\_model\_flux, flux\_corr, get\_data\_info} + +\begin{verbatim} +hist_index = integer index of spectrum in internal list + s.bin_lo = bin left edge [Angstrom] + s.bin_hi = bin right edge [Angstrom] + s.value = bin value [photons/sec/cm^2] + s.err = bin uncertainty [photons/sec/cm^2] +\end{verbatim} + +This function retrieves the specified flux-corrected histogram +from the internal list and loads the data into a structure. See +\verb|flux_corr| for details on flux-correcting counts spectra. + +\end{isisfunction} + +\begin{isisfunction} +{get\_data\_info} %name +{load spectrum parameters a \slang\ structure} %purpose +{Struct\_Type[] = get\_data\_info (index\_list)} %usage +{set\_data\_info, load\_data, list\_data, array\_struct\_field} + +This function returns an array of structures whose fields +contain the {\tt spec\_num, order, part} and {\tt srcid} +keywords for each data set listed in the {\tt index\_list} +along with the {\tt target} name string and the observation +start time, {\tt tstart} and the frame time, {\tt frame\_time}. +This structure also contains \verb|notice| and +\verb|notice_list| arrays indicating which data bins are +currently noticed (for model fitting) and a flag array, +\verb|rebin|, which indicates which of the original bins have +been grouped together (see \verb|rebin_data| for details). In +addition, the returned structure contains the indices for the +ARF(s) and RMF(s) assigned to the data set. The \verb|exclude| +field indicates whether or not the dataset is currently +excluded from the fit. The names of the spectrum file +(\verb|file|) and associated background file (\verb|bgd_file|) +are also provided. + +\begin{verbatim} +Example: + isis> id = load_data ("o1318_heg+1_pha.fits"); + isis> s=get_data_info(id); + isis> print(s); + spec_num = 1 + order = 1 + part = 1 + srcid = 1 + exclude = 0 + combo_id = 0; + combo_weight = 1; + target = CAPELLA + tstart = 7.5667e+07 + frame_time = 3.2 + arfs = Integer_Type[1] + rmfs = Integer_Type[1] + notice = Integer_Type[8192] + notice_list = Integer_Type[8192] + rebin = Integer_Type[8192] + file = o1318_heg+1_pha.fits + bgd_file = +\end{verbatim} + +To extract a specific field from a returned array of +structures, use \verb|array_struct_field|. +\begin{verbatim} +Example: + isis> d=load_data ("pha2.fits"); + Reading: ............ + isis> info = get_data_info(d); + isis> part = array_struct_field(info, "part"); + isis> part; + Integer_Type[12] +\end{verbatim} + +\end{isisfunction} + +\begin{isisfunction} +{get\_dataset\_metadata} +{Retrieve user-defined meta data associated with a dataset} +{meta = get\_dataset\_metadata (hist\_index)} +{set\_dataset\_metadata} + +Use this function to retrieve arbitrary (user-defined) metadata +associated with a particular dataset. The ability to assign +arbitrary metadata to a dataset and later retrieve it can be +useful to support analysis techniques unforseen during isis +development. +\end{isisfunction} + +\begin{isisfunction} +{get\_flux\_corr\_weights} +{Retrieve the weights used to perform flux-correction} +{wt[] = get\_flux\_corr\_weights (hist\_index)} +{flux\_corr} + +Define +\begin{equation} +W(h) = t \int dy R(h,y)A(y). +\end{equation} +This function returns the array $W(h)$ at full resolution. +In the linear regime, the flux-corrected data and uncertainties +are defined to be +\begin{eqnarray} + f(h) &= (C(h) - B(h)) / W(h) \\ + df^2(h) &= (C(h) + B(h)) / W^2(h) +\end{eqnarray} +Summing over several bins $h$, to make a wider bin $H$, +a rebinned version is: +\begin{eqnarray} + f(H) &= \frac{\sum_h C(h) - \sum_h B(h)}{\sum_h W(h)} \\ + df^2(H) &= \frac{\sum_h C(h) + \sum_h B(h)}{(\sum_h W(h))^2} +\end{eqnarray} +If we define weights +\begin{equation} + w(h) = \frac{W(h)}{\sum_h' W(h')} +\end{equation} +we can rewrite the rebinned version, $f(H)$ and $df(H)$, as: +\begin{eqnarray} + f(H) &= \sum_h w(h) f(h) \\ + df^2(H) &= \sum_h w^2(h) df^2(h) +\end{eqnarray} +This approach allows one to perform arbitrary rebinning +after computing the $f(h)$, $df(h)$ and $W(h)$ values only once. +\end{isisfunction} + +\begin{isisfunction} +{get\_frame\_time} %name +{Get the CCD frame-time for a data set} %purpose +{frame\_time\_sec = get\_frame\_time (hist\_index)} %usage +{set\_frame\_time, get\_data\_info} +\index{Pileup!getting the frame time} + +This function is normally used in conjunction with the CCD photon +pileup model. The frame time is specified in units of seconds. + +\end{isisfunction} + +\begin{isisfunction} +{get\_back} +{Retrieve the scaled instrumental background for a given spectrum} +{b = get\_back (hist\_index)} +{define\_back, \_define\_back, back\_fun} + +Returns an array of instrumental background values. +These values are on the same wavelength grid as that returned +by e.g. \verb|get_data_counts|. +\end{isisfunction} + +\begin{isisfunction} +{get\_rmf\_arf\_grid} % name +{Get ARF grid from an RMF} % purpose +{Struct\_Type = get\_rmf\_arf\_grid (rmf\_index)} % usage +{list\_rmf, get\_rmf\_data\_grid}. + +This function retrieves the ARF grid from a specific RMF, +returning a \slang\ structure containing a wavelength grid +(angstrom units) in monotonic increasing order. The structure +returned has the form + +\begin{verbatim} + s.bin_lo = bin left edge [Angstrom] + s.bin_hi = bin right edge [Angstrom] +\end{verbatim} +\end{isisfunction} + +\begin{isisfunction} +{get\_rmf\_data\_grid} % name +{Get the data grid from an RMF} % purpose +{Struct\_Type = get\_rmf\_data\_grid (rmf\_index)} % usage +{list\_rmf, get\_rmf\_rmf\_grid}. + +This function retrieves the data grid from a specific RMF, +returning a \slang\ structure containing a wavelength grid +(angstrom units) in monotonic increasing order. The structure +returned has the form + +\begin{verbatim} + s.bin_lo = bin left edge [Angstrom] + s.bin_hi = bin right edge [Angstrom] +\end{verbatim} +\end{isisfunction} + +\begin{isisfunction} +{get\_sys\_err\_frac} % name +{Get the fractional systematic error} % purpose +{sys\_err\_frac = get\_sys\_err\_frac (hist\_index)} % usage +{set\_sys\_err\_frac, load\_data}. + +See \verb|load\_data| for a definition of fractional systematic +error, e.g. \verb|SYS_ERR|. + +\end{isisfunction} + +\begin{isisfunction} +{set\_sys\_err\_frac} % name +{Set the fractional systematic error} % purpose +{set\_sys\_err\_frac (hist\_index, sys\_err\_frac[])} % usage +{get\_sys\_err\_frac, load\_data}. + +See \verb|load\_data| for a definition of fractional systematic +error, e.g. \verb|SYS_ERR|. + +\end{isisfunction} + +\begin{isisfunction} +{group\_data} +{Group spectral bins by an integer factor} +{group\_data (hist\_index\_array, factor)} +{rebin\_data, use\_file\_group, regroup\_file, rebin\_dataset, set\_rebin\_error\_hook, rebin, rebin\_array} +\index{Rebinning!integer factor} + +The count data of each histogram in {\tt hist\_index\_array} is +rebinned by summing the contents of the original input data bins +and the associated bin uncertainties ({\tt stat\_err}) are +recomputed assuming Poisson statistics. Use +\verb|set_rebin_error_hook| to change the way bin uncertainties +are recomputed. Note that this rebinning does not involve an event +list. + +\begin{verbatim} +Example: + + group_data (1, 4); % group data set 1 by a factor of 4 +\end{verbatim} +\end{isisfunction} + +\begin{isisfunction} +{back\_fun} %name +{Specify instrumental background function for a data-set} %purpose +{back\_fun (idx, "function")} %usage +{fit\_fun, set\_par, flux\_corr, define\_back, \_define\_back, get\_back} +\index{background!fitted} + +This function allows one to define the component of the background +which is not folded through the ARF and RMF (e.g. the $B(h)$ term +in equation (\ref{eq:model-counts})). The syntax of the function +string is the same as that used by \verb|fit_fun|. + +To eliminate the instrumental background term for a data-set, use +\verb|NULL| or an empty string (\verb|""|) as the second argument. + +For example: +\begin{verbatim} + % use a sum of power-law functions to model + % the instrumental background for data-set 1: + back_fun (1, "Powerlaw(1) + Powerlaw(2)"); + + % Turn off the instrumental background term for + % data-set 2 + back_fun (2, NULL); +\end{verbatim} + +It is important to note that the specified background function +will be evaluated on the wavelength grid associated with the +data (at full resolution). If a different wavelength grid is +required, it may be necessary to implement the background +function using \verb|eval_fun2| to ensure that the correct grid +is used. + +Here is one way to implement the background function using +\verb|eval_fun2|: + +\begin{verbatim} +private variable First_Order_Grid = get_rmf_data_grid (1); +define backfun_fit (_l,_h,_p) +{ + variable l = First_Order_Grid.bin_lo; + variable h = First_Order_Grid.bin_hi; + variable p = eval_fun2 ("poly", l, h, _p[[:2]]); + variable g = eval_fun2 ("gauss", l, h, _p[[3:]]); + variable t = get_data_exposure (Isis_Active_Dataset); + + return t * (p + g); +} +add_slang_function ("backfun", + ["a0", "a1", "a2", + "area", "center", "sigma"]); + +back_fun (h, "backfun"); +set_par ("backfun", [0.030, -7.26e-6, 1.73e-6, + -0.32, 48.7, 16.4]); +\end{verbatim} + +The most important aspect of this implementation is that it +ignores the data grid passed in the variables (\verb|_l, _h|), +instead computing the background contribution explicitly using +the first-order spectral grid contained in the structure, +\verb|First_Order_Grid|. + +The distinction between the data grid and the background grid +can be important in the analysis of dispersed spectra +containing contributions from multiple dispersion orders and +with a significant background contribution(e.g. Chandra +LETG/HRC-S data). + +\end{isisfunction} + +\begin{isisfunction} +{interpol} +{Interpolate a function y(x) onto a new grid} +{new\_y[] = interpol (new\_x[], old\_x[], old\_y[])} +{rebin, interpol\_points} +\index{Interpolation!arrays} + +The input function \verb|y(x)| specified by the \slang\ arrays +(\verb|old_x, old_y|) is linearly interpolated onto the grid +(\verb|new_x|) to determine the corresponding interpolated values +\verb|new_y|. Both new and old grids must be in monotonic +increasing order. If the new grid extends beyond the old grid, +linear extrapolation is performed. +\end{isisfunction} + +\begin{isisfunction} +{interpol\_points} +{Interpolate a function y(x) onto a new grid} +{new\_y[] = interpol\_points (new\_x[], old\_x[], old\_y[])} +{rebin, interpol} +\index{Interpolation!points} + +This function is identical to \verb|interpol| except that +the array of X values, \verb|new_x|, need not be ordered. + +\end{isisfunction} + +\begin{isisfunction} +{is\_flux\_mode} +{Determine the current data mode} +{flag = is\_flux\_mode()} +{use\_flux, use\_counts} + +{\it Use of this function and the \isisx data modes is not +recommended.} Experience has shown that use of these data modes leads +to confusion and unnecessary complications in analysis scripts. This +function is still available primarily to provide compatibility with +earlier versions of \isisx -- it may be removed in a subsequent +release. + +Use this function to determine whether \isis is currently dealing with +flux data or count data. If the return value is one, commands such as +{\tt get\_data}, {\tt put\_data} and {\tt plot\_data} all refer to +{\it flux-corrected} data (e.g. the {\tt FLUX} column in the Type II +PHA file). If the return value is zero, these commands all refer to +{\it count} data (e.g. the {\tt COUNTS} column in the PHA file) +\end{isisfunction} + +\begin{isisfunction} +{lambda\_mth\_order} %name +{Plot the location of $m$th order given that the $n$th order + appears at $\lambda_n$.} %purpose +{lambda\_mth\_order (m, lambda\_n, [n])} %usage +{plot\_data\_counts} +If n is not specified, the default value is n=1. +lambda\_n is the wavelength in Angstroms (\AA). +\begin{equation} +\lambda_m = \lambda_n \left( {m \over n} \right) +\end{equation} +Non-integer orders are allowed. +\end{isisfunction} + +\begin{isisfunction} +{list\_arf} % name +{Display a list of currently loaded ARFs} % purpose +{list\_arf ([arg])} % usage +{get\_arf, put\_arf, delete\_arf}. + +The optional argument is used to redirect the output. If +\verb|arg| is omitted, the output goes to \verb|stdout|. If +\verb|arg| is of type \verb|Ref_Type|, it the output string is +stored in the referenced variable. If \verb|arg| is a file name, +the output is stored in that file. If \verb|arg| is a file +pointer (\verb|File_Type|) the output is written to the +corresponding file. + +The currently loaded list of effective area functions (ARFs) is +displayed. +The indices of the ARFs in this list ({\tt id} column) are used in other +commands to refer to individual ARFs; e.g. {\tt get\_arf (2)} +refers to ARF number 2. The ARF list looks like this: +\begin{verbatim} +isis> list_arf; + +Current ARF List: + id grating detector m prt src nbins exp(ksec) target + 1 HETG ACIS 1 1 1 8192 89.88 mysrc + 2 HETG ACIS 1 2 1 8192 89.88 src2 + +\end{verbatim} +where the columns are defined as + +\begin{verbatim} + id = integer id number (arf_index) + grating = e.g. HETG or LETG +detector = e.g. ACIS-S or HRC-S + m = diffraction order (TG_M) + prt = e.g. HEG or MEG, (TG_PART) + src = source index (TG_SRCID) + nbins = total number of bins + exp = Exposure time [ksec] + target = target name +\end{verbatim} + +If the intrinsic variable \verb|Isis_List_Filenames| is +non-zero, the name of the ARF file (if any) will be displayed +on the line following each list entry. + +\end{isisfunction} + +\begin{isisfunction} +{list\_data} %name +{display the currently loaded list of spectra} %purpose +{list\_data ([arg])} %usage +{delete\_data, load\_data, get\_data\_info, get\_dataset\_metadata} + +The optional argument is used to redirect the output. If +\verb|arg| is omitted, the output goes to \verb|stdout|. If +\verb|arg| is of type \verb|Ref_Type|, it the output string is +stored in the referenced variable. If \verb|arg| is a file name, +the output is stored in that file. If \verb|arg| is a file +pointer (\verb|File_Type|) the output is written to the +corresponding file. + +The currently loaded list of spectra is displayed. The indices of +the spectra in this list ({\tt id} column) are used in other +commands to refer to individual spectra; e.g. {\tt plot\_data (2)} +refers to spectrum number 2. The spectrum list looks like this: +\begin{verbatim} +id instrument m prt src use/nbins A R totcts exp(ksec) target + 1 HETG-ACIS -3 1 1 6972/ 6972 - - 4.8000e+01 0.00 src1 + 2x HETG-ACIS -2 1 1 6972/ 6972 1 1 2.2700e+02 0.00 src1 + 3 HETG-ACIS -1 2 1 6972/ 6972 - - 6.2870e+03 0.00 src1 +\end{verbatim} +where the columns are defined as +\begin{verbatim} + id = integer data set id number ['x' => excluded from fit] + grating = e.g. HETG or LETG + detector = e.g. ACIS-S or HRC-S + m = diffraction order (TG_M) + prt = e.g. HEG or MEG, (TG_PART) + src = source index (TG_SRCID) +use/nbins = number of noticed bins/ (total number of bins) + A = index of assigned ARF ("-" if none assigned) + R = index of assigned RMF ("-" if none assigned) + totcts = total counts summed over all bins + exp = Exposure time [ksec] + target = target name +\end{verbatim} + +If the intrinsic variable \verb|Isis_List_Filenames| is non-zero, +the names of the spectrum file and background file (if any) will +also be displayed on lines following each list entry. + +If the function \verb|list_data_hook| is defined in the Global +namespace, it will called for each dataset. Among other +things, this hook can be used to display user-defined metadata. +For example, suppose you want to associate a string and a +floating point number with each dataset and you want these +values printed out whenever you call \verb|list_data|. One way +to implement that is to store your metadata in a structure +along with a pointer to a function to do the printing. For +example, consider this structure definition: +\begin{verbatim} + define printm (m) + { + vmessage ("s=%s, x=%g", m.s, m.x); + } + variable metadata = struct {s, x, printm}; + metadata.s = "Hello World!"; + metadata.x = 3.1415; + metadata.printm = &printm; +\end{verbatim} +Use the \verb|set_dataset_metadata| function to associate this +structure with dataset \verb|1|: +\begin{verbatim} + set_dataset_metadata (1, m); +\end{verbatim} +Now, to have this metadata printed out whenever \verb|list_data| +is run, provide a \verb|list_data| hook like this: +\begin{verbatim} + public define list_data_hook () + { + variable m = get_dataset_metadata (Isis_Active_Dataset); + if (m != NULL) + (@m.printm)(m); + } +\end{verbatim} + +\end{isisfunction} + +\begin{isisfunction} +{list\_rmf} % name +{Display a list of currently loaded RMFs} % purpose +{list\_rmf ([arg])} % usage +{assign\_rmf, unassign\_rmf}. + +The optional argument is used to redirect the output. If +\verb|arg| is omitted, the output goes to \verb|stdout|. If +\verb|arg| is of type \verb|Ref_Type|, it the output string is +stored in the referenced variable. If \verb|arg| is a file name, +the output is stored in that file. If \verb|arg| is a file +pointer (\verb|File_Type|) the output is written to the +corresponding file. + +The list of currently loaded Redistribution Matrix Functions (RMFs) +is displayed. + +\begin{verbatim} +Example: + +isis> list_rmf; + +Current RMF List: + id grating detector type file + 1 HETG ACIS-S file: hetg_rmf.fits + +\end{verbatim} + +\end{isisfunction} + +\begin{isisfunction} +{load\_arf} % name +{Load an effective area (ARF) file} % purpose +{status = load\_arf ("filename")} % usage +{load\_dataset, list\_arf, delete\_arf, assign\_arf, unassign\_arf} + +This function loads either a FITS Type I or Type II ARF file; the +updated list of currently loaded ARFs is automatically displayed. On +return, {\tt status} is equal to the integer index of the ARF just +loaded ({\tt status} $>$ 0); a return value of {\tt status = -1} is +used to indicate failure. (For Type II ARF input, a return value of +zero indicates success). + +\end{isisfunction} + +\begin{isisfunction} +{load\_data} %name +{read a spectrum from an ASCII file or FITS Type I or II PHA file} %purpose +{status = load\_data("pha\_filename" [, rows])} %usage +{load\_dataset, define\_counts, define\_flux, define\_back, +get\_data\_*, put\_data\_*, plot\_unit, set\_dataset\_metadata, +get\_dataset\_metadata, get\_sys\_err\_frac} + +The format of the Type II PHA file is defined in the CXCDS Level 2 +Data Products ICD. An ASCII-format file should contain the histogram +data in 4 columns: {\tt bin\_lo}, {\tt bin\_hi}, {\tt bin\_value}, +{\tt bin\_uncertainty}. By default, all spectra in a Type II pha file +are loaded at once; to load a particular list of spectra, supply an +array of row numbers as the (optional) second argument. + +\begin{verbatim} + Example: + % to load spectra 9 and 10 from a standard + % Chandra Type II pha file + % (usually the MEG +1 and -1 order spectra): + + isis> id = load_data ("hetg_pha2.fits", [9,10]); +\end{verbatim} + +Although a Type I PHA file can be loaded without first +specifying the RMF, an RMF is required to use the data. The +RMF may be specified either by using the {\tt RESPFILE} keyword +in the FITS header or by loading the RMF file separately (see +{\tt load\_rmf} and {\tt assign\_rmf}). The ARF may be +specified either by using the {\tt ANCRFILE} keyword in the +FITS header or by loading the ARF file separately (see {\tt +load\_arf} and {\tt assign\_arf}). To ignore the +\verb|ANCRFILE| and \verb|RESPFILE| values when loading +the PHA file, set \verb|Ignore_PHA_Response_Keywords=1|. + +\index{Ignore\_PHA\_Response\_Keywords@{\tt Ignore\_PHA\_Response\_Keywords}} + +By default, isis ignores the \verb|GROUPING| column of the +input PHA file. To automatically apply the grouping on input, +set the intrinsic variable \verb|Isis_Use_PHA_Grouping| to a +non-zero value. + +Input data values must be bin-integral quantities rather than +bin-densities; uncertainty values should be positive. By default, any +input {\tt STAT\_ERR} uncertainty values smaller than 1 are reset to +\begin{verbatim} + stat_err = max[ sqrt(N), Minimum_Stat_Err ] +\end{verbatim} +Where \verb|Minimum_Stat_Err| is the smallest acceptable +(positive) uncertainty value with a default value of 1. + +\index{Minimum\_Stat\_Err@{\tt Minimum\_Stat\_Err}} +\index{Minimum valid stat\_err!see{{\tt Minimum\_Stat\_Err}}} + +If the \verb|SYS_ERR| column or header keyword is present, a +systematic error is added in quadrature so that the uncertainty +on each data bin becomes +\begin{verbatim} + sigma = sqrt ( sigma_stat^2 + (D * sys_err)^2 ), +\end{verbatim} +where \verb|sigma_stat| is the statistical uncertainty, +and \verb|D| is the corresponding data value. + +If the input data are in flux units (photons/cm**2/sec/bin) and +non-positive uncertainties are encountered, the uncertainty is +set equal to 1.0. In each case a message is printed to warn the +user. To reset the uncertainties to another value, see {\tt +get\_data\_*} and {\tt put\_data\_*}. + +Input bin coordinates may be given as Angstrom (\AA), nm, eV, keV or +Hz; if the bin coordinates are unspecified, the default is Angstrom +units. Although all internal calculations are done in Angstrom units, +plots may be generated in any of the supported physical units. See +{\tt plot\_unit}. + +In the ASCII format, lines with a \# symbol in column 1 are ignored +and may be used for comments. + +The ASCII file may also contain keywords analogous to the header +keywords in FITS files. All keywords must be grouped together at the +top of the file (possibly with interspersed comment lines). Each +keyword line must have a semicolon (;) in column 1 and may contain +only one keyword name/value pair; a maximum of 1024 characters will be +scanned on each such line. Only the first 8 characters of each keyword +name are significant; the keyword name and keyword value must be +separated by at least one space or tab character. Keyword values may +be of type int, float, double or string; string keyword values may +contain any printable characters including embedded whitespace +characters (except newline). The supported keyword names are + +\begin{verbatim} +___Keyname____Type____Definition_______________________ + + object string source name +instrument string e.g. ACIS-S or HRC-S + grating string e.g. HETG or LETG + exposure double exposure [sec] + tg_m int diffraction order + tg_part int e.g. HEG or MEG + tg_srcid int source id number + xunit string physical units of bin coordinates + bintype string bin-value units; [counts|flux] +\end{verbatim} + +This function returns {\tt status} equal to the integer index of the +data set(s) loaded; for Type I pha files, this is a single positive +integer ($> 0$) and for Type II pha files, this is an array of +positive integers. Otherwise, it returns {\tt status = -1} to +indicate failure. + +\begin{verbatim} +Example ASCII format file: + + # this is a comment line + # + ; Object test src 1 + # + ; Instrument acis-s + ; Grating heg + ; Exposure 1.e6 + ; xunit angstrom + ; bintype counts + # + # bin_lo bin_hi counts stat_err + 1.5955326e+01 1.5960888e+01 4.0 2.0 + 1.5960888e+01 1.5966450e+01 4.0 2.0 + # another comment line + 1.5966450e+01 1.5972012e+01 4.0 2.0 + 1.5972012e+01 1.5977573e+01 4.0 2.0 +\end{verbatim} + +If the function \verb|load_data_hook| is defined in the Global +namespace, it will be +called after the data is successfully loaded as +\begin{verbatim} + load_data_hook (file, id); +\end{verbatim} +where \verb|file| is the name of the file just loaded and +where \verb|id| is an array of \verb|Integer_Type| which +gives the indices of the datasets just loaded. Among other things, this +function may be used to automatically associate user-defined +metadata with each dataset. + +For example, suppose you want each dataset to carry along the +\verb|RA_NOM|, \verb|DEC_NOM|, values from the FITS header. +Consider the following function +\begin{verbatim} + public define load_data_hook (file, id) + { + variable m = fits_read_key_struct (file, "RA_NOM", "DEC_NOM"); + set_dataset_metadata (id, m); + } +\end{verbatim} + +\end{isisfunction} + +\begin{isisfunction} +{load\_dataset} %name +{Load a spectrum, ARF and RMF} %purpose +{load\_dataset ("data-file", "rmf-file", "arf-file")} %usage +{load\_data, define\_counts, define\_flux, load\_arf, load\_rmf, assign\_arf, assign\_rmf} + +This function is essentially equivalent to the sequence: +\begin{verbatim} + d = load_data ("data.fits"); + r = load_rmf ("rmf.fits"); + a = load_arf ("arf.fits"); + assign_rmf (r,d); + assign_arf (a,d); +\end{verbatim} +If either the RMF or ARF names are missing or NULL, +the corresponding response is not assigned and defaults +to an ideal response. +\end{isisfunction} + +\begin{isisfunction} +{load\_rmf} %name +{Load an RMF} %purpose +{status = load\_rmf ("filename[:init\_name[;options]]")} %usage +{load\_dataset, list\_rmf, assign\_rmf, unassign\_rmf} +\index{User-defined!RMF} +\index{Rmf\_OGIP\_Compliance@{\tt Rmf\_OGIP\_Compliance}} + +An RMF is usually a FITS file which conforms to the OGIP standard +RMF format. + +\isisx also supports RMFs which are defined in software. +In this case, the RMF is specified by giving the name of a shared +library (.so file) which provides the software implementation +conforming to the interface defined in the \isisx source code in +\verb|src/isis.h|. See \verb|test/rmf_user.c| +for an example implementation. + +The name of the initialization function for the user-defined RMF +module should be included in the string specifying the name of the +shared library; the two names fields should be separated by a +colon (:). Additional RMF-specific options may be specified +by adding semicolon-delimited arguments; these options +are passed to the RMF module initialization function when the RMF is +initialized for a specific histogram. User-defined RMFs may parse +this string to obtain additional useful parameters, e.g. perhaps +an auxiliary data file name or specific values for user-defined +RMF parameters. + +\begin{verbatim} +Examples: + % load an OGIP FITS-format RMF file + () = load_rmf ("heg_rmf.fits"); + + % load a user-defined RMF module from librmf.so, + % initialized by calling my_rmf_init_function(). + () = load_rmf ("librmf.so:my_rmf_init_function"); + + % here, additional option strings are used to supply + % two parameters to the RMF function when it is initialized. + () = load_rmf ("libotherrmf.so:init_function ;sigma=4.32;a=4"); +\end{verbatim} + +By default, isis will complain and refuse if asked to load a +FITS RMF file which does not adhere closely to the OGIP +standard format. Setting \verb|Rmf_OGIP_Compliance=0| will +reduce the required level of standards compliance. If isis +remains unable to read the file, the best approach may be to +modify the RMF file to adhere more closely to the standard +format. Usually this is just a matter of adding a few keywords +and making sure that important keywords have correct values. +In particular, isis looks for +\begin{verbatim} + EXTNAME = EBOUNDS + EXTNAME = MATRIX | SPECRESP MATRIX + HDUCLAS2 = RSP_MATRIX + HDUCLAS3 = REDIST | DETECTOR | FULL +\end{verbatim} +The \verb|HDUCLASn| keywords are required for full OGIP +compliance, but will be ignored if \verb|Rmf_OGIP_Compliance=0|. + +\end{isisfunction} + +\begin{isisfunction} +{match\_dataset\_grids} %name +{Put a list of datasets onto the same grid} %purpose +{match\_dataset\_grids (list[])} %usage +{combination\_members, combine\_datasets, uncombine\_datasets, get\_combined, rebin\_combined} + +This function uses \verb|rebin_dataset| to put all the listed +datasets onto the original (ungrouped) grid from the first dataset +in the list. All spectrum bins are noticed. + +Note that each dataset in the provided list should have its own +set of responses; in other words, no single response function (ARF +or RMF) should be assigned to more than one dataset. This +restriction is necessary to avoid unintended side-effects when the +responses are interpolated onto the new grid. + +The main purpose of this function is to support combining +datasets to improve statistics -- see \verb|combine_datasets|. +\end{isisfunction} + +\begin{isisfunction} +{plot\_data} %name +{plot spectral data (counts) using the current plot format} %purpose +{[o]plot\_data (hist\_index [,style])} %usage +{plot\_data\_counts} +This is an alias for \verb|plot_data_counts|. +\end{isisfunction} + +\begin{isisfunction} +{plot\_data\_counts} %name +{plot spectral data (counts) using the current plot format} %purpose +{[o]plot\_data\_counts (hist\_index [,style])} %usage +{rplot\_counts, set\_data\_color, [o]plot\_model, title} +\index{Label\_By\_Default@{\tt Label\_By\_Default}} +\index{oplot\_data\_counts@{\tt oplot\_data\_counts}} +\index{Plot!of spectra} + +This function plots the counts histogram of the specified data set. +Other similar functions are available to plot the flux-corrected data +set (See {\tt [o]plot\_data\_flux}) and to plot the corresponding +model values (See {\tt [o]plot\_model\_counts} and {\tt +[o]plot\_model\_flux}) + +The spectrum to plot is specified using its integer index ({\tt +hist\_index}) in the current internal list (see {\tt list\_data}). The +destination plot window if different from the current default, are +specified using {\tt window}. + +The plot data coordinates are in {\AA}ngstrom units by default, but +may be changed using the {\tt plot\_unit} function. Bin values may be +plotted in either bin-integral units (the default) or bin-density +units (see {\tt plot\_bin\_integral} and {\tt plot\_bin\_density}). + +Axis ranges default to the full range of the data, but may be +specified using {\tt [xy]range}. Both linear or logarithmic axis +scales are available; see {\tt [xy]log}. Errorbars are also available +(see {\tt errorbars}). + +Plot axes are labeled automatically by default, to turn off this +behavior, set {\tt Label\_By\_Default = 0}; setting this variable to a +non-zero value will restore the default behavior. + +Repeated invocations of {\tt oplot\_data\_counts} will automatically +switch line colors or styles to help distinguish the over-plotted +curves. Depending on the current setting [ see {\tt style} ] either +colors or line styles (e.g. solid vs. dashed) are used to distinguish +over-plots. To override the automatic color/style changes, the {\tt +style} index can be specified explicitly for each plot (see also {\tt +set\_data\_color}). Alternatively, the automatic color-changes can be +disabled using {\tt plot\_auto\_color}. + +See \S\ref{sec:plot-functions} for a general discussion of \isisx +plotting. +\end{isisfunction} + +\begin{isisfunction} +{plot\_convolved\_model\_flux} %name +{plot convolved spectral model flux for a specific data spectrum} %purpose +{[o]plot\_convolved\_model\_flux (hist\_index [,style])} %usage +{[o]plot\_data\_flux, [o]plot\_model\_flux} + +This function plots the model for the specified data set +broadened using the assigned RMF. The convolved model +flux is computed using the expression +\begin{equation} +F(h) = \int R(h,E)S(E)dE +\end{equation} + +See \verb|get_convolved_model_flux| and +\verb|plot_model_counts| for details. + +\end{isisfunction} + +\begin{isisfunction} +{plot\_data\_flux} %name +{plot spectral data flux using the current plot format} %purpose +{[o]plot\_data\_flux (hist\_index [,style])} %usage +{set\_data\_color, [o]plot\_model\_flux, title} + +This function plots the flux histogram of the specified data +set. The flux histogram may be computed from the counts +spectrum by \verb|flux_corr|, loaded from a data file by +\verb|load_data| or defined via \slang\ arrays using +\verb|define_flux|. For details, see \verb|plot_data_counts|. + +\end{isisfunction} + +\begin{isisfunction} +{plot\_model\_counts} %name +{plot spectral model counts for a specific data spectrum} %purpose +{[o]plot\_model\_counts (hist\_index [,style])} %usage +{[o]plot\_data\_counts, [o]plot\_model\_flux, [o]plot\_convolved\_model\_flux} +\index{oplot\_model@{\tt oplot\_model}} +\index{Plot!of spectra} + +This function plots the model for the counts histogram of the +specified data set. The model counts, $C(h)$, are computed +using the expression +\begin{equation} +C(h) = B(h) + t \int {\cal F}\Bigl(R(h,E), A(E), S(E)\Bigr)dE +\end{equation} +where $B(h)$ is the background spectrum, $R(h,E)$ is the RMF, +$A(E)$ is the ARF and $S(E)$ is the model for the incident +photon spectrum. + +See {\tt plot\_data\_counts} for details. +\end{isisfunction} + +\begin{isisfunction} +{plot\_model\_flux} %name +{plot spectral model flux for a specific data spectrum} %purpose +{[o]plot\_model\_flux (hist\_index [,style])} %usage +{[o]plot\_data\_flux, [o]plot\_model\_counts, [o]plot\_convolved\_model\_flux} + +This function plots the model for the specified data set. +Normally, the model represents the incident flux, $S(E)$, +integrated over the width of each spectral bin, and has units +of photons/sec/cm${}^2$. + +See {\tt plot\_model\_counts} for details. + +\end{isisfunction} + +\begin{isisfunction} +{put\_arf} %name +{Change ARF grid and/or values} %purpose +{put\_arf (arf\_index, arf\_struct | bin\_lo, bin\_hi, arf, arf\_err)} %usage +{get\_arf, list\_arf} + +If invoked with two arguments, the second argument should be a struct +with fields {\tt bin\_lo, bin\_hi, value, err}. If invoked with five +arguments, the last four arguments should provide the equivalent +values: + +\begin{verbatim} +arf_index = integer index of ARF in internal list + a.bin_lo = bin left edge [Angstrom] + a.bin_hi = bin right edge [Angstrom] + a.value = bin value [cm^2 counts/photon] + a.err = bin uncertainty [cm^2 counts/photon] +\end{verbatim} + +This command replaces internal ARF data with values from several +\slang\ array-variables. Only the internal values are changed; no disk +files are affected. + +The only restrictions are that 1) the dimensionality of the arrays +cannot be changed, 2) the input histogram grid must be consistent +(Angstrom units in monotonic increasing order with {\tt bin\_lo} $<$ +{\tt bin\_hi}) and 3) the uncertainty values must be positive. Any +non-positive input values of {\tt uncertainty} are reset to 1 and a +message is printed to warn the user. + +\begin{verbatim} +Example: + a = get_arf(1); + put_arf(1, a.bin_lo, a.bin_hi, a.value, 2 * a.err); +\end{verbatim} +\end{isisfunction} + +\begin{isisfunction} +{put\_data\_counts} %name +{Change the counts histogram for a data set} %purpose +{put\_data\_counts (hist\_index, struct | bin\_lo, bin\_hi, value, uncertainty)} %usage +{get\_data\_counts, list\_data, define\_counts, define\_flux} + +If invoked with two arguments, the second argument should be a struct +with fields {\tt bin\_lo, bin\_hi, value, err}. If invoked with five +arguments, the last four arguments should provide the equivalent +values: + +\begin{verbatim} +hist_index = integer index of spectrum in internal list + d.bin_lo = bin left edge [Angstrom] + d.bin_hi = bin right edge [Angstrom] + d.value = bin value [counts] + d.err = bin uncertainty [counts] +\end{verbatim} + +This command replaces internal histogram data with values from several +\slang\ array-variables. Only the internal values are changed; no +disk files are affected. A similar function is provided to modify +the flux-corrected data values ({\tt put\_data\_flux}). + +The only restrictions are that 1) the dimensionality of the arrays +cannot be changed, 2) the input histogram grid must be consistent +(Angstrom units in monotonic increasing order with {\tt bin\_lo} $<$ +{\tt bin\_hi}) and 3) the uncertainty values must be positive. Any +non-positive input values of {\tt uncertainty} are reset (e.g. +according to counting statistics for {\tt counts} = $N$, {\tt +uncertainty} = $\sqrt{N}$) and a message is printed to warn the user. + +\begin{verbatim} +Example: + c = get_data_counts (1); + put_data_counts (1, c.bin_lo, c.bin_hi, c.value, sqrt(c.value)); +\end{verbatim} +\end{isisfunction} + +\begin{isisfunction} +{put\_data\_flux} %name +{Change the flux-corrected histogram for a data set} %purpose +{put\_data\_flux (hist\_index, struct | bin\_lo, bin\_hi, value, uncertainty)} %usage +{get\_data\_flux, list\_data, define\_counts, define\_flux} + +This function is analgous to \verb|put_data_counts|, except +that it overwrites the appropriate internal array containing +flux-corrected data. See \verb|put_data_counts| for details. + +\end{isisfunction} + +\begin{isisfunction} +{put\_model\_counts} %name +{Replace the counts model for a data set} %purpose +{put\_model\_counts (hist\_index, counts[])} %usage +{put\_model\_flux, put\_convolved\_model\_flux, eval\_counts, eval\_flux} + +Use this function to replace the model counts array for a +particular data set. Note that the dimension of the input +array must match the current, possibly rebinned, data set +including both noticed and ignored bins. + +\end{isisfunction} + +\begin{isisfunction} +{put\_model\_flux} %name +{Replace the flux model for a data set} %purpose +{put\_model\_flux (hist\_index, counts[])} %usage +{put\_model\_counts, put\_convolved\_model\_flux, eval\_counts, eval\_flux} + +Use this function to replace the model flux array, \verb|S(E)|, +for a particular data set. Note that the dimension of the +input array must match the ARF (or the unbinned data, if no ARF +has been assigned). + +\end{isisfunction} + +\begin{isisfunction} +{put\_convolved\_model\_flux} %name +{Replace the convolved flux model for a data set} %purpose +{put\_convolved\_model\_flux (hist\_index, counts[])} %usage +{put\_model\_counts, put\_model\_flux, eval\_counts, eval\_flux} + +Use this function to replace the convolved model flux array for +a particular data set. Note that the dimension of the input +array must match the current, possibly rebinned, data set. + +\end{isisfunction} + +\begin{isisfunction} +{rebin} +{Rebin a histogram} +{newval = rebin (new\_lo, new\_hi, lo, hi, value)} +{rebin\_data, group\_data, rebin\_dataset, rebin\_array, interpol} +\index{Rebinning!histograms} +\index{Adding plus and minus orders} + +Using linear interpolation where necessary, the input histogram +specified by the \slang\ arrays ({\tt lo, hi, value}) is mapped onto +the specified grid (\verb|new_lo|, \verb|new_hi|) to produce the new +bin-value array {\tt newval}. Both input and output grids must be in +monotonic order. Note that the input histogram is assumed +to be a bin-integrated quantity such as {\tt counts/bin} and that no +unit conversions are performed; to rebin a bin-density such as {\tt +counts/\AA}, the user must explicitly handle the unit conversion, e.g. +\begin{verbatim} + x = density * (hi - lo); % convert to bin-integral + new_x = rebin (new_lo, new_hi, lo, hi, x); + new_density = new_x / (new_hi - new_lo); % convert to bin-density +\end{verbatim} +This function can be used to simplify adding spectra together (e.g. +summing plus and minus order diffracted spectra, and summing the +associated ARFs): +\begin{verbatim} + Example: + m = get_data_counts (megm1); % get MEG m=-1 order + h = get_data_counts (hegm1); % get HEG m=-1 order + + mcts = m.value; + hcts = h.value; + + % map HEG onto MEG grid: + new_hcts = rebin (m.bin_lo, m.bin_hi, h.bin_lo, h.bin_hi, hcts); + + total = mcts + new_hcts; % total counts in -1st order MEG+HEG + % using MEG -1 wavelength grid. +\end{verbatim} +\end{isisfunction} + +\begin{isisfunction} +{rebin\_array} +{Rebin a \slang\ array to match a rebinned spectrum} +{result[] = rebin\_array (array[], rebin\_flags[])} +{rebin\_data, group\_data, rebin\_dataset} +\index{Rebinning!arrays} + +It is sometimes useful to rebin a \slang\ array so that it matches +a rebinned dataset. For example, suppose we have a dataset with +\verb|N| bins and a matching model array with the same number of +elements. If we rebin the data, the model array no longer matches: +\begin{verbatim} + % rebin dataset 1 to have at least 30 counts per bin + rebin_data (1, 30); +\end{verbatim} +To generate a new, matching model array, do the following: +\begin{verbatim} + % retrieve the flag array used to rebin the data .. + s = get_data_info (1); + % .. and rebin the model the same way + m = rebin_array (model, s.rebin); +\end{verbatim} + +\end{isisfunction} + +\begin{isisfunction} +{rebin\_combined} +{Rebin a combination of binned spectra} +{rebin\_combined (gid[], min\_counts\_per\_bin | index\_array)} +{combine\_datasets, group\_data, rebin\_dataset, set\_rebin\_error\_hook, rebin, rebin\_array} +\index{Rebinning!minimum counts per bin} +\index{Rebinning!using index array} + +This function is the same as \verb|rebin_data| except that it +operates on dataset combinations. For example, one can use +this function to rebin a combination of datasets so that the +sum has a specified minimum number of counts per bin. +See \verb|rebin_data| and \verb|combine_datasets| for details. + +\end{isisfunction} + +\begin{isisfunction} +{rebin\_data} +{Rebin a binned spectrum} +{rebin\_data (hist\_index\_array, min\_counts\_per\_bin | index\_array)} +{group\_data, rebin\_dataset, set\_rebin\_error\_hook, rebin, rebin\_array} +\index{Rebinning!minimum counts per bin} +\index{Rebinning!using index array} + +The count data of each histogram in {\tt hist\_index\_array} is +rebinned by summing the contents of the original input data bins +and the associated bin uncertainties ({\tt stat\_err}) are +recomputed assuming Poisson statistics. Use +\verb|set_rebin_error_hook()| to change the way bin uncertainties +are recomputed. Note that this rebinning does not involve an event +list. + +The second argument to {\tt rebin\_data} may be either a positive +scalar value or an integer array of the same size as the original +input histogram. + +If the second argument is a scalar, it is interpreted as the +minimum desired number of counts per bin; e.g. +\verb|rebin_data(1,25)| will rebin spectrum 1 so that each bin +contains at least 25 counts. + +If the second argument is an integer array the same length as the +original input histogram, it defines the scheme for summing over +the data bins. The integer values of this array should be either +-1, 0 or 1; neighboring bins with the same sign (-1 or +1) are +summed together, while bins with a zero are ignored. + +For example, if the original data has 10 bins, the index array should +have 10 bins. These commands will: +\begin{verbatim} + isis> i = [1, 1, -1, 1, 0, 1, -1, -1, -1, -1]; + isis> rebin_data (meg, i); +\end{verbatim} +will generate a 4 bin version of spectrum {\tt meg} with this grouping: +\begin{verbatim} + result_bin[0] = original_bin[0] + original_bin[1] + result_bin[1] = original_bin[2] + result_bin[2] = original_bin[3] + original_bin[5] + result_bin[3] = original_bin[6] + original_bin[7] + + original_bin[8] + original_bin[9] +\end{verbatim} +Note that zero values mean that the associated bin should be ignored +(\verb|original_bin[4]| in this example). + +The original input histogram may be restored using +\begin{verbatim} + isis> rebin_data (idx, 0); +\end{verbatim} +This also restores the ignore/notice values in effect before the data was +first rebinned; this feature provides a mechanism to excise bad bins in the +input spectrum. + +{\it The flux-columns must be recomputed after rebinning the count +data.} Similarly, any associated fit-models must be recomputed. + +\end{isisfunction} + +\begin{isisfunction} +{rebin\_dataset} %name +{Rebin an RMF and its assigned spectrum} %purpose +{rebin\_dataset (dataset, bin\_lo, bin\_hi)} %usage +{rebin\_rmf, rebin\_data, group\_data, set\_rebin\_error\_hook, rebin} +\index{Rebinning!data and response} + +This function rebins a counts spectrum and its assigned instrument +response matrix (RMF) so that the RMF maps onto the new instrument +grid \verb|bin_lo|, \verb|bin_hi|. The RMF normalization is +preserved. See \verb|rebin_data| and \verb|rebin_rmf| for +details. + +\end{isisfunction} + +\begin{isisfunction} +{rebin\_rmf} %name +{Rebin an RMF} %purpose +{rebin\_rmf (dataset, bin\_lo, bin\_hi)} %usage +{rebin\_dataset, rebin\_data} +\index{Rebinning!RMF} + +This function rebins an instrument response matrix (RMF) so that +it maps onto a new instrument grid (\verb|bin_lo|, \verb|bin_hi|). +The RMF normalization is preserved. + +RMF rebinning makes it possible to apply an RMF to a dataset with +a grid different from that for which the RMF was originally +constructed. + +As one application, RMF rebinning provides a consistent way to +apply the instrument response to CCD spectra in PI space. The +instrument response is normally measured in PHA space but, to +account for gain variations over large areas of the detector, CCD +spectra from extended sources are often analyzed in PI space. When +constructing PI-RMFs, these gain variations are usually accounted +for by simply shifting the locations of Gaussian peaks in the +PHA-RMF. However, this process does not account for the distortion +in the Gaussian profile shape introduced by the nonlinear +transformation from PHA to PI space. In contrast, constructing +PI-RMFs by rebinning PHA-RMFs automatically includes any such +distortions. + +\begin{verbatim} +Example: + + % This function rebins a PHA-RMF onto a PI-RMF grid + define make_pi_rmf (k) + { + variable lo, hi; + + % Standard PI energy grid [keV] + hi = 0.0146 * [1:1024]; + lo = hi - 0.0146; + + % tweak low end to E>0 + lo[0] += 1.e-3 * hi[0]; + + return rebin_rmf (k, _A(lo, hi)); + } + + pi_data = load_data ("ccd_pi.fits"); + rmf = load_rmf ("pha_rmf.fits"); + make_pi_rmf (rmf); + assign_rmf (rmf, pi_data); + +\end{verbatim} + +\end{isisfunction} + +\begin{isisfunction} +{regroup\_file} %name +{Apply grouping to PHA file} %purpose +{regroup\_file (grp[], file) OR regroup\_file (id [,file])} %usage +{group\_data, use\_file\_group, i2x\_group, x2i\_group} + +Use this function to regroup a \verb|PHA| file using an \isis\ +grouping array. The grouping array, \verb|grp| should be a +standard, wavelength-ordered, isis grouping array as defined in +the documentation for \verb|rebin_data|. The length of the +grouping array should match the length of the spectrum stored +in the PHA file. This function will convert the grouping array +to an OGIP-standard, energy-ordered grouping array and will +write that array to the \verb|GROUPING| column in the specified +\verb|PHA| file. If the first argument is an integer dataset +index, the grouping array associated with that dataset will be +used (e.g. \verb|get_data_info(id).rebin|). If the file name is +omitted, the file name associated with the dataset will be used +(e.g. \verb|get_data_info(id).file|). + +For example: +\begin{verbatim} + % regroup a PHA file to match a given dataset + grp = get_data_info (3).rebin; + regroup_file (grp, "pha.fits"); + + % update the input PHA file to match the current grouping: + id = load_data ("pha_x.fits"); + group_data (id, 4); + regroup_file (id); +\end{verbatim} + +\end{isisfunction} + +\begin{isisfunction} +{region\_counts} %name +{Compute count statistics for a given wavelength region} %purpose +{Struct\_Type = region\_counts (hist\_index, xmin, xmax [,ymin, ymax])} %usage +{region\_flux} + +A data structure is returned for the histogram indicated by {\tt +hist\_index}. This structure contains a number of statistics for the +interval {\tt [xmin, xmax)}. Individual fields are accessible using +the \slang\ structure syntax; e.g. {\tt s.sum} or {\tt +s.centroid\_err} (see below). + +If {\tt ymin} and {\tt ymax} are not specified, no continuum +subtraction is performed (it is assumed that the continuum level is +zero). If {\tt ymin} and {\tt ymax} values are specified, they are +used to define a linear continuum $c(\lambda) = a * \lambda + b$ +passing through the two points {\tt (xmin, ymin)} and {\tt +(xmax,ymax)}. The continuum value in bin {\tt k} between +[$\lambda_{\rm lo}^k$, $\lambda_{\rm hi}^k$] is then computed using +\begin{equation} +C_k = \left(\lambda_{\rm hi}^k - \lambda_{\rm lo}^k\right) +\left[ a { \left(\lambda_{\rm hi}^k + \lambda_{\rm lo}^k\right) \over 2} + + b \right] +\end{equation} +Note that \verb|ymin| and \verb|ymax| represent the continuum +{\it density} and have units of e.g. counts per Angstrom +or flux per Angstrom. + +With this continuum level, the structure fields are: +\begin{verbatim} + min, max = wavelength limits defining this region [Angstrom] + nbins = number of noticed bins in this region + sum, sum_err = sum of noticed bins and RMS uncertainty + net, net_err = continuum subtracted sum of noticed bins + and RMS uncertainty + centroid, centroid_err = centroid of continuum subtracted emission + in noticed bins and RMS uncertainty [Angstrom] + eqwidth, eqwidth_err = equivalent width (positive/negative for + emission/absorption) of noticed bins and + RMS uncertainty [Angstrom] + contin, slope = continuum density and slope at the + centroid position +\end{verbatim} +\end{isisfunction} + +\begin{isisfunction} +{region\_flux} %name +{Compute flux statistics for a given wavelength region} %purpose +{Struct\_Type = region\_flux (hist\_index, xmin, xmax [,ymin, ymax])} %usage +{region\_counts} + +See {\tt region\_counts}. +\end{isisfunction} + +\begin{isisfunction} +{rplot\_counts} %name +{Plot counts data and model with residuals} %purpose +{rplot\_counts (hist\_index)} %usage +{rplot\_flux, plot\_data\_counts, title} +\index{Plot!plotting residuals} + +This function generates a two-paned plot, the upper pane +showing the counts data with model overlaid and the lower +pane showing the residuals. The type of residuals plotted +is determined by the value of the intrinsic variable +\verb|Isis_Residual_Plot_Type|; supported values are: + +\begin{verbatim} +___Value____Definition_________ + STAT value provided by current fit-statistic + DIFF (data-model) + RATIO (data/model) +\end{verbatim} + +The default is \verb|Isis_Residual_Plot_Type=STAT|. When the +fit-statistic is \verb|chisqr|, the plotted residual is +$\Delta\chi$. When the fit-statistic is \verb|cash|, the +plotted residual for each bin is the (positive) Cash statistic +for that bin, multiplied by the sign of \verb|(data-model)|. + +\end{isisfunction} + +\begin{isisfunction} +{rplot\_flux} %name +{Plot flux-corrected data and model with residuals} %purpose +{rplot\_flux (hist\_index)} %usage +{rplot\_counts, plot\_data\_flux, title} +\index{Plot!plotting residuals} + +This function generates a two-paned plot, the upper pane +showing the flux-corrected data with model overlaid and the lower +pane showing the residuals. See \verb|rplot_counts| for +details. + +\end{isisfunction} + +\begin{isisfunction} +{\_[o]rplot\_counts} %name +{Plot residuals for counts data} %purpose +{\_[o]rplot\_counts (hist\_index[, style])} %usage +{rplot\_counts, \_[o]rplot\_flux} + +This function plots residuals of the type specified by the +intrinsic variable \verb|Isis_Residual_Plot_Type| See +\verb|rplot_counts| for details. + +\end{isisfunction} + +\begin{isisfunction} +{\_[o]rplot\_flux} %name +{Plot residuals for flux-corrected data} %purpose +{\_[o]rplot\_flux (hist\_index[, style])} %usage +{rplot\_flux, \_[o]rplot\_counts} + +This function plots residuals of the type specified by the +intrinsic variable \verb|Isis_Residual_Plot_Type| See +\verb|rplot_counts| for details. + +\end{isisfunction} + +\begin{isisfunction} +{set\_arf\_exposure} +{Set the exposure time for a given ARF} +{set\_arf\_exposure (arf\_index, exposure\_sec)} +{get\_data\_exposure} + +Use this to set exposure time in seconds for a particular effective +area function (ARF). + +\end{isisfunction} + +\begin{isisfunction} +{set\_arf\_info} % name +{Set ARF information} % purpose +{set\_arf\_info (id, Struct\_Type)} % usage +{set\_arf\_exposure, set\_arf\_info, get\_arf\_info} + +This function provides access to auxiliary ARF parameters +through a structure: + +\begin{verbatim} +isis> s=get_arf_info(1); +isis> print(s); + order = -1 + part = 2 + srcid = 0 + exposure = 28123.4 + fracexpo = 1; +isis> s.exposure=3.e4; % change the exposure time +isis> set_arf_info(1,s); % update the internal value +isis> list_arf; + +Current ARF List: + id grating detector m prt src nbins exp(ksec) target + 1 -1 2 0 8192 30.00 +\end{verbatim} +\end{isisfunction} + +\begin{isisfunction} +{set\_data\_color} %name +{Specify a plot color for one or more data sets} %purpose +{set\_data\_color (hist\_index\_list, color\_index)} %usage +{unset\_data\_color, color, plot\_data\_counts, plot\_auto\_color} + +If a plot color is specified for a data set, that color will always be +used when plotting that data set. Unless this command is used to +specify a particular color, the data set will be plotted using the +default color in the corresponding plot window pane at the time the +plot is created. + +\begin{verbatim} + Example: + red = 2; + blue = 4; + + set_data_color (2, blue); % always plot spectrum 2 in blue. + + set_data_color ([1,4,5], red); % always plot spectra 1,4 and 5 in red +\end{verbatim} + +\end{isisfunction} + +\begin{isisfunction} +{set\_data\_backscale} +{Set the background scaling for a given spectrum} +{set\_data\_backscale (hist\_index, area)} +{set\_arf\_exposure} +Set the BACKSCALE value associated with for histogram {\tt +hist\_index}. Normally, this is the area of the spectral +extraction region; the same area units must be used for both +the source and background spectra. +\end{isisfunction} + +\begin{isisfunction} +{set\_data\_exposure} +{Set the exposure time for a given spectrum} +{set\_data\_exposure (hist\_index, exposure\_sec)} +{set\_arf\_exposure} +Set the exposure time in seconds for histogram {\tt +hist\_index}. Note that the ARF exposure time is the +important quantity for fitting data. +\end{isisfunction} + +\begin{isisfunction} +{set\_data\_info} %name +{Change spectrum parameters using a \slang\ structure} %purpose +{set\_data\_info (index\_list, Struct\_Type)} %usage +{get\_data\_info, load\_data, list\_data} + +This function changes selected data parameters using a structure +whose fields are integers which define the {\tt spec\_num, +order, part, srcid} and {\tt exclude} keywords along with +the {\tt target} name string. + +\begin{verbatim} +Example: + isis> load_data ("acisf01318N003_pha2.fits.gz"); + Reading: ............ + Integer_Type[12] + isis> s = get_data_info(9); + isis> print(s); + spec_num = 9 + order = -1 + part = 2 + srcid = 1 + exclude = 0 + combo_id = 0; + combo_weight = 1; + target = CAPELLA + tstart = 7.5667e+07 + frame_time = 3.2 + notice = Integer_Type[8192] + notice_list = Integer_Type[8192] + rebin = Integer_Type[8192] + arfs = Integer_Type[1] + rmfs = Integer_Type[1] + isis> + isis> s.order = 2; % change #9 to 2nd order + isis> set_data_info (9, s); +\end{verbatim} + +\end{isisfunction} + +\begin{isisfunction} +{set\_dataset\_metadata} +{Associate user-defined meta data with a particular dataset} +{set\_dataset\_metadata (hist\_index, meta)} +{get\_dataset\_metadata} + +Use this function to associate arbitrary (user-defined) metadata +with a particular dataset. For example: + +\begin{verbatim} + set_dataset_metadata (1, "SKY_X=4013.42; SKY_Y=3987.4"); +\end{verbatim} + +The metadata may be retrieved using the \verb|get_dataset_metadata| +function. The ability to assign arbitrary metadata to a +dataset and later retrieve it can be useful to support analysis +techniques unforseen during isis development. + +\end{isisfunction} + +\begin{isisfunction} +{set\_eval\_grid\_method} %name +{Specify the model evaluation grid method for a dataset} %purpose +{set\_eval\_grid\_method (method, datasets[][, hook [,cache]])} %usage +{combine\_datasets} +\index{Extending model grid} + +Supported grid methods are \verb|MERGED_GRID|, +\verb|SEPARATE_GRID| and \verb|USER_GRID| + +\verb|SEPARATE_GRID| (the default) means that, when the model +is evaluated for each dataset, it is evaluated on the +wavelength grid defined by the ARF. If no ARF is specified, +the data grid is used. + +\verb|MERGED_GRID| means that, for the specified list of +datasets, the model is evaluated once at the highest resolution +needed and then the resulting model histogram is rebinned onto +the model grid associated with each dataset (usually the +associated ARF grid). This method is automatically +selected when datasets are combined using +\verb|combine_datasets|. When computation of the model is more +expensive than rebinning and when several datasets with +extensive wavelength overlap are being fitted simultaneously, +this feature should save a considerable amount of CPU time. +Because model computation usually dominates the CPU usage, +merging grids is often a valuable optimization. + +For example: +\begin{verbatim} + + set_eval_grid_method (MERGED_GRID, [1:10]); + +\end{verbatim} +means that a single wavelength grid will be derived by merging +the wavelength grids assigned to datasets 1-10. When fitting +these datasets, the model will be evaluated once on the merged +grid and then rebinned onto the grid of each individual +dataset. This means that on each iteration, the model will be +evaluated only once and not 10 times. + +To revert to the default mode, use: +\begin{verbatim} + + set_eval_grid_method (SEPARATE_GRID, [1;10]); + +\end{verbatim} + +\verb|USER_GRID| means that, when the model is evaluated +for each dataset, it is evaluated on the wavelength grid +supplied by a user-provided S-Lang function. This function +must be of the form +\begin{verbatim} + Struct_Type = grid_hook (hist_index, Struct_Type); +\end{verbatim} +where the \verb|Struct_Type| has fields \verb|bin_lo| and +\verb|bin_hi|. The grid returned by this function must +define a wavelength grid in Angstrom units, in ascending +order. The optional fourth argument is a boolean value +which indicates whether or not the model value computed +on the specified grid should be cached and subsequently +rebinned onto all other grids in the specified group. + +For example, suppose that 10 datasets have been loaded +and we want to extend the wavelength grid of 5 of them +beyond the range covered by the ARF grid. First, define +a function to provide the necessary grid: +\begin{verbatim} + define extender (id, s) + { + % + return s; + } +\end{verbatim} +We can then impose this model grid using: +\begin{verbatim} + set_eval_grid_method (USER_GRID, [3:8], &extender); +\end{verbatim} +With this grid definition, ISIS will use the extended grid when +evaluating the model, S(E), for datasets 3-8. Note that the +model will be evaluated once for each dataset. If all these +datasets have the same wavelength grid and if the same +wavelength ranges are noticed in each, considerable +computational work may be saved by specifying that the model be +evaluated for one of these datasets and then simply rebinned +for the others in this group. To turn on model-caching for the +specified datasets, the optional fourth argument should be +non-zero: +\begin{verbatim} + set_eval_grid_method (USER_GRID, [3:8], &extender, 1); +\end{verbatim} + +IMPORTANT: Note that, by default, the standard fit kernel +evaluates the fit model only on those wavelength ranges that +contribute to noticed data bins, as determined from the +instrumental response. When fitting data with operators that +represent convolutions, this behavior may not be desirable. +In such cases, it may be necessary to compute the model and to +apply the convolution operator over a much broader wavelength +range. To ensure that the model is computed over the entire +wavelength range specified by the user-defined grid, use the +\verb|eval| option on the standard kernel. For example, +\begin{verbatim} + set_kernel ([3:8], "std;eval=all"); +\end{verbatim} +To revert to the default behavior, use +\begin{verbatim} + set_kernel ([3:8], "std;eval=noticed"); +\end{verbatim} +\end{isisfunction} + +\begin{isisfunction} +{set\_fake} %name +{Specify whether or not a dataset should be considered fake} %purpose +{set\_fake (hist\_index, 0|1)} %usage +{fakeit} + +This function is used to change the default status of a given +dataset. By default, spectral data generated by \verb|fakeit| +is considered to be fake and will be over-written by subsequent +calls to \verb|fakeit|. All other spectral data is considered +to be ``real'' and will not be over-written by calls to +\verb|fakeit|. + +For example, to over-write a real dataset with fake data: +\begin{verbatim} +% load ascii-format spectral data + load_data ("ascii.dat"); + +% mark dataset 1 as fake data + set_fake (1, 1); + +% over-write dataset 1 + fakeit; +\end{verbatim} + +Alternatively, to keep a particular fake spectrum from being +over-written by subsequent calls to `fakeit', one could change +the status of that dataset using +\begin{verbatim} + set_fake (id, 0); +\end{verbatim} +\end{isisfunction} + +\begin{isisfunction} +{set\_frame\_time} %name +{Specify the frame-time for a data set} %purpose +{set\_frame\_time (hist\_index, frame\_time\_sec)} %usage +{set\_kernel, load\_kernel, set\_data\_info} +\index{Pileup!setting the frame time} + +This function is normally used in conjunction with the CCD photon +pileup model. The frame time is specified in units of seconds. + +\end{isisfunction} + +\begin{isisfunction} +{set\_post\_model\_hook} %name +{Modify the computed model before computing the fit-statistic} %purpose +{set\_post\_model\_hook (id[], \&func)} %usage +{fit\_fun, fit\_counts} + +Use this function to modify the computed model after the +separate source and background contributions have been +computed, but before the fit-statistic is computed. One can +define a function of the form +\begin{verbatim} + m = func (lo, hi, c, b) +\end{verbatim} +which will be called during fitting for the specified dataset. +This function will be passed the original (ungrouped) +wavelength grid of the detector (\verb|lo|, \verb|hi|) along +with the predicted source (\verb|c|) and background counts +(\verb|b|). It should return the predicted total counts in +each detector bin; by default, it returns the sum of the source +and background counts: +\begin{verbatim} + define post_model (lo, hi, c, b) + { + return (c + b); + } + set_post_model_hook (id, &post_model); +\end{verbatim} + +This function may be used for a variety of other purposes, e.g. +to plot the model at each iteration of a fit, to treat +systematic errors or to examine alternate fitting techniques. + +Note that this function may also include parameters which are +varied during the fit. Suppose the desired hook-function +depends on two parameters which we'd like to vary during the +fit. In the following example, we show how to use a do-nothing +function to introduce the two parameters: + +\begin{verbatim} +define dummy_fit (l,h,p) +{ + return 1; +} +add_slang_function ("dummy", ["a", "b"]); + +fit_fun ("dummy(1)*powerlaw(1)"); + +define tweak_model (lo, hi, counts, bgd) +{ + variable a, b, x, y; + x = counts; + a = get_par ("dummy(1).a"); + b = get_par ("dummy(1).b"); + + y = x*(1 + a*x)*exp(-b*x) + bgd; + + return y; +} +set_post_model_hook (id, &tweak_model); +\end{verbatim} + +With this definition, the computed model has two additional +parameters: + +\begin{verbatim} +isis> list_par; +dummy(1)*powerlaw(1) + idx param tie-to freeze value min max + 1 dummy(1).a 0 0 0 0 0 + 2 dummy(1).b 0 0 0 0 0 + 3 powerlaw(1).norm 0 0 1 0 1e+10 + 4 powerlaw(1).PhoIndex 0 0 1 -2 9 +\end{verbatim} + +which will vary during the fit, controlling the action +of the hook-function provided by \verb|set_post_model_hook|. +\end{isisfunction} + +\begin{isisfunction} +{set\_rebin\_error\_hook} +{Change the way rebinning propagates uncertainties} +{set\_rebin\_error\_hook (hist\_index, \&hook)} +{rebin\_data, group\_data, rebin\_dataset, Minimum\_Stat\_Err} +\index{Rebinning!error propagation} + +Use this function to define the way uncertainties are propagated +when a counts spectrum is rebinned. By default, Poisson +uncertainties are assumed. To change this default, specify the +name of a S-Lang function of the form +\begin{verbatim} + define hook (orig_cts, orig_stat_err, grouping) +\end{verbatim} +where +\begin{verbatim} + orig_cts = the unbinned counts array + orig_stat_err = the unbinned uncertainties + grouping = index array specifying which bins are to + be grouped (see rebin_data() for details) +\end{verbatim} +This function should return the array of uncertainties +corresponding to the specified grouping. To indicate an error, it +should return \verb|NULL|. Because ISIS validates the uncertainties +returned by this routine, it may also be necessary +to change the value of \verb|Minimum_Stat_Err| to ensure that +the uncertainties computed by the error-hook are not modified. +Uncertainties must always be positive -- negative or zero values +are not allowed. + +For example, to add bin uncertainties in quadrature when dataset 1 +is rebinned: +\begin{verbatim} + define rebin_error_hook (orig_cts, orig_stat_err, grouping) + { + return sqrt(rebin_array (orig_stat_err^2, grouping)); + } + set_rebin_error_hook (1, &rebin_error_hook); +\end{verbatim} + +To delete the error-hook for a particular dataset, use +\begin{verbatim} + set_rebin_error_hook (index, NULL); +\end{verbatim} + +\end{isisfunction} + +\begin{isisfunction} +{unassign\_arf} %name +{Undo the assignment of an ARF to a data set} %purpose +{unassign\_arf (hist\_index\_array)} %usage +{load\_arf, list\_arf, assign\_arf} + +\begin{verbatim} +Example: + unassign_arf (1); % unassign the ARF for spectrum 1 + unassign_arf ([3:6]); % unassign the ARF for spectra 3, 4, 5 and 6 + +\end{verbatim} +\end{isisfunction} + +\begin{isisfunction} +{unassign\_rmf} %name +{Undo the assignment of an RMF to a data set} %purpose +{unassign\_rmf (hist\_index\_array)} %usage +{list\_rmf, assign\_rmf} + +\begin{verbatim} +Example: + unassign_rmf (1); % unassign the RMF for spectrum 1 + unassign_rmf ([3:6]); % unassign the RMF for spectra 3, 4, 5 and 6 + +\end{verbatim} +\end{isisfunction} + +\begin{isisfunction} +{uncombine\_datasets} %name +{Turn off dataset combination} %purpose +{uncombine\_datasets (gid[])} %usage +{combine\_datasets, match\_dataset\_grids, combination\_members, get\_combined, rebin\_combined} + +\end{isisfunction} + +\begin{isisfunction} +{unset\_data\_color} %name +{Revert to using the current default plot color when plotting a data set} %purpose +{unset\_data\_color (hist\_index\_list)} %usage +{color, plot\_data\_counts, plot\_auto\_color} +This removes a color specification set by {\tt set\_data\_color} +and reverts to the default plot behavior. +\end{isisfunction} + +\begin{isisfunction} +{use\_file\_group} %name +{Apply PHA file grouping to a specified dataset} %purpose +{use\_file\_group (id, file)} %usage +{group\_data, regroup\_file, i2x\_group, x2i\_group} + +Use this function to group a dataset to match the grouping in a +specified \verb|PHA| file. The length of the spectrum stored in +the PHA file should match the length of the ungrouped dataset. +This function will convert the OGIP-standard, energy-ordered +grouping array from the file to an array that matches the isis +convention (see \verb|rebin_data|) and will apply that grouping +to the specified dataset. If the file name is omitted, the +file name associated with the dataset will be used (e.g. +\verb|get_data_info(id).file|). + +For example: +\begin{verbatim} + % regroup a dataset to match a given PHA file + use_file_group (id, "pha.fits"); +\end{verbatim} + +\end{isisfunction} + +\begin{isisfunction} +{i2x\_group} %name +{Convert isis-convention grouping array to OGIP-convention grouping array} %purpose +{xg[] = i2x\_group (ig[])} %usage +{x2i\_group, regroup\_file, use\_file\_group} + +The isis grouping array convention is described in the help +page for \verb|rebin_data|. See the xspec documentation for +details on the OGIP grouping array convention. + +\end{isisfunction} + +\begin{isisfunction} +{x2i\_group} %name +{Convert OGIP-convention grouping array to isis-convention grouping array} %purpose +{ig[] = x2i\_group (xg[])} %usage +{i2x\_group, regroup\_file, use\_file\_group} + +The isis grouping array convention is described in the help +page for \verb|rebin_data|. See the xspec documentation for +details on the OGIP grouping array convention. + +\end{isisfunction} + +\newpage +\section{Access to the Atomic Database} +\label{sec:atomic-db} + +Because wavelength tables may be unavailable or may not provide a +complete listing of all emission lines present in the line emissivity +tables, the run-time atomic database is populated using {\it both} +wavelength and energy level tables {\it and} the line-emissivity +tables. For this reason, some of the functions described in this +section may be useful even when atomic data files are unavailable. + +To simplify access to a large database of emission line wavelengths, +\isisx provides a number of functions to define, track and manipulate +{\it groups} of lines defined by various criteria. Over-plotting line groups +on observed spectra ({\tt plot\_group}) provides an important aid to line +identification. + +A line group is defined by a list of integers which represent the +index of each group member in the internal wavelength table. This +integer list may be held in a \slang\ array-variable or (optionally) +stored in an internal table. A group may be registered in the internal +table using {\tt define\_group}; groups may be deleted from this +internal list using ({\tt delete\_group}). Each group in the internal +list can be given a mnemonic name ({\tt name\_group}). + +The user can browse the contents of a line group using {\tt +page\_group}. Among other things, this output provides line indices +which may be used to refer to lines individually. Given the line +index, the {\tt line\_info} function can retrieve information on a +single line. {\tt group} returns an array containing the indices of +all lines in a given group. Line groups may be saved to a disk file +using {\tt save\_group}. + +Lines can be grouped by element, ion ({\tt el\_ion}), wavelength ({\tt +wl}) and predicted flux in some specified spectral model ({\tt flx}) +using the {\tt where} command which is a \slang\ intrinsic. The +brightest lines in the current model (see {\tt create\_aped\_fun} in \S +\ref{sec:spectral_models}) can be selected using the function {\tt +brightest}. Groups may be defined using logical expressions as arguments to +the {\tt where} command: +\begin{verbatim} + lines = brightest(20, where(el_ion([8,12],[3:6]) and wl(1,15))); +\end{verbatim} +uses the current spectral model to select the brightest 20 lines in +the range 1-15 \AA~ which arise from O and Mg atoms ionized 3,4,5 or 6 +times (e.g. O III, O IV, O V, OVI, Mg III, Mg IV, Mg V and Mg VI). +Logical operators {\tt not}, {\tt and} and {\tt or} and may be used in +these expressions. + +Because some emission line wavelengths may not be accurately known, +high-resolution spectral data may provide better values than those +listed in the atomic database. {\tt change\_wl} allows the user to +provide ``corrected'' wavelength values for use in \isisx run-time +analysis (the wavelength values in the FITS files are {\it not} +affected). + +Energy level diagrams can be plotted using {\tt plot\_elev} and {\tt +[o]plot\_elev\_subset}; line transitions can be over-plotted on energy +level diagrams using {\tt oplot\_transitions} + +\begin{isisfunction} +{add\_abundances} %name +{Add a new abundance table} %purpose +{id = add\_abundances (Struct\_Type | name, abun[], Z[]);} %usage +{set\_abund, list\_abund, get\_abundances} + +Use this function to define a new abundance table. The +abundance table may be defined by a structure with fields +\verb|Z[]|, \verb|abun[]| and \verb|name| containing the proton +number of each element, its abundance and the name of the +abundance table, respectively. Alternatively, these values +may be provided as separate arguments. The abundance +values must be given as log cosmic abundance by number, +relative to Hydrogen = 12.0. The return value is the +index of the new table. + +\end{isisfunction} + +\begin{isisfunction} +{aped\_bib} %name +{Retrieve bibcodes for APED database sources} %purpose +{Struct\_Type = aped\_bib (Struct\_Type db, Integer\_Type[] lines)} %usage +{aped\_bib\_query\_string, el\_ion, wl, flx, trans, page\_group} + +\begin{verbatim} +EXAMPLE + % Retrieve references for emission lines between 1-20 Angstrom + ref_struct = aped_bib (aped, where(wl(1,20))); +\end{verbatim} +\end{isisfunction} + +\begin{isisfunction} +{aped\_bib\_query\_string} %name +{Make a URL to retrieve APED bibcodes from the ADS database} %purpose +{String\_Type = aped\_bib\_query\_string (Struct\_Type refs)} %usage +{aped\_bib} + +\begin{verbatim} +EXAMPLE + % Retrieve references for emission lines between 1-20 Angstrom + ref_struct = aped_bib (aped, where(wl(1,20))); + qs = aped_bib_query_string (ref_struct); + + () = system ("lynx -dump '$qs' > /tmp/qs.bib"$); +\end{verbatim} +\end{isisfunction} + +\begin{isisfunction} +{aped\_fun\_details} %name +{Retrieve detailed information (e.g. emission line fluxes) on a computed APED spectral model} %purpose +{List\_Type = aped\_fun\_details ("name(id)")} %usage +{create\_aped\_fun, aped\_bib, aped\_bib\_query\_string} + +A multi-temperature plasma emission model with a custom +parameterization can be constructed using +\verb|create_aped_fun|. A particular dataset may be modeled by +a sum of such multi-temperature models -- for example, consider +a three component model: +\begin{verbatim} + xaped(1) + xaped(2) + xaped(3) +\end{verbatim} +where each \verb|xaped| component introduces N +temperatures-density components, +\begin{verbatim} + T[i], n[i], i=0,1,2,...N-1. +\end{verbatim} + +In the resulting model spectrum, any given emission line +represents the sum of 3N contributions -- 3 model components, +with N temperature-density components each. + +The \verb|aped_fun_details| function can be used to retrieve +all of these separate contributions to each emission line. For +example, the contribution to emission line, k, from +temperature/density component, i, of model component, j, can be +retrieved like so: +\begin{verbatim} + create_aped_fun ("xaped", p); + fit_fun ("xaped(1) + xaped(2) + ... + xaped(N)"); + + % let 1 <= j <= N + + info = aped_fun_details ("xaped($j)"$); + flux = info[i].line_flux[k]; +\end{verbatim} + +The single required input parameter is a string specifying a +particular instance of an APED model created by +\verb|create_aped_fun|. + +The return value is a \verb|List_Type| quantity with one +\verb|Struct_Type| entry for each temperature-density component +of the APED model. Each structure contains selected model +parameters: +\begin{verbatim} + struct {density, temperature, line_flux, + norm, redshift, vturb, metal_abund} +\end{verbatim} +The \verb|line_flux| field is an array of length equal to the +number of emission lines in the APED database. For this reason, +the line indices returned by other isis functions, e.g. +\verb|brightest|, may be used to index into this array. + +\begin{verbatim} +EXAMPLE + + % define a spectral model + create_aped_fun ("xaped", default_plasma_state()); + fit_fun ("xaped(1) + xaped(2)"); + + % line index for O VIII Ly alpha 2p~^2P_{3/2} - 1s~^2S_{1/2} + id = where(trans(O,8,4,1))[0]; + + % view database parameters for this emission line + print(line_info (id)); + + % evaluate the spectral model (computing all the line fluxes) + variable lo, hi, f; + (lo, hi) = linear_grid (1, 20, 2000); + f = eval_fun (lo, hi); + + % retrieve flux contribution to this line from the first + % temperature-density component of xaped(1) + info = aped_fun_details ("xaped(1)"); + flux0 = info[0].line_flux[ id ]; + +\end{verbatim} + +\end{isisfunction} + +\begin{isisfunction} +{atoms} %name +{load the atomic database} %purpose +{atoms (Struct\_Type)} %usage +{plasma} + +This function loads all the FITS-format atomic data files listed in +the ``filemap'' file specified by the {\tt atomic\_data\_filemap} +field if the database configuration structure. + +\begin{verbatim} +Example: + isis> s.atomic_data_filemap = "data/filemap"; + isis> atoms (s); +\end{verbatim} + +Although it is not necessary to load the atomic data files, they may +provide more information than is contained in the line and continuum +emissivity tables (e.g. energy level data, transition probabilities, +identification labels for the emission lines, etc. ). +\end{isisfunction} + +\begin{isisfunction} +{brightest} %name +{get indices of the k brightest lines in a given list} %purpose +{indices = brightest (k, line-list)} %usage +{line\_em, ratio\_em, create\_aped\_fun} + +A plasma emission model must be defined and a model spectrum computed +{\it before} using this function. For the purpose of selecting the +brightest lines, the total flux from each line is summed over all +model components without regard to the relative Doppler-shifts or +line-profile shapes involved. + +\begin{verbatim} +Example: + % define and compute a model spectrum +load_model("model_dat"); +(lo, hi) = linear_grid (1, 25, 6000); +flux = model_spectrum (lo, hi); + + % find the indices of the + % 20 brightest Fe lines + % in that model spectrum + +b = brightest(20, where(el_ion(Fe))); % Fe = 26 + +\end{verbatim} +\end{isisfunction} + +\begin{isisfunction} +{change\_wl} %name +{Change internal wavelength values for specific lines} %purpose +{change\_wl("filename")} %usage +{plasma, atoms} + +This function loads a file containing a list of emission lines +specified by element, ion, and upper and lower energy level indices +along with values for the line wavelength and its uncertainty. The +wavelengths and uncertainties in the file over-write those in the +\isisx memory at run time (the wavelengths in the atomic database +files on disk are {\it not} changed). + +This function can be used to correct line wavelengths in the atomic +database using wavelengths measured from observational data. + +The wavelength file is ASCII-formatted with these columns +in order from left to right: +\begin{verbatim} + lambda [Angstrom] + lambda_err [Angstrom] +proton_number + ion state + upper_level + lower_level +\end{verbatim} +Lines with a \# in column 1 are ignored and may be used +for comments. +\end{isisfunction} + +\begin{isisfunction} +{define\_group} %name +{register a line group in the internal group list} %purpose +{define\_group (group\_index, line-list)} %usage +{delete\_group, name\_group, save\_group, brightest, trans, el\_ion, wl, flx}. + +Note: The main purpose of this internal list is bookkeeping. Because +essentially all line-group functionality is available using line +groups specified by \slang\ array-variables, there is no requirement +to register a group in the internal list. Because it is not clear +that this additional functionality is useful, it may not be supported +in future releases. + +A line group ({\tt line-list}) is specified by an integer array of +line indices. This array may be specified explicitly (e.g. {\tt \[ 27, +39, 415 \]}) or may be generated via a logical expression to the {\tt +where} command (a \slang\ intrinsic function). This function registers +the specified group using the specified integer {\tt group\_index}, +replacing any group already registered with that index. + +\begin{verbatim} +Example: + % group 2 = brightest 20 lines from Fe XVI, Fe XVII, Ni XVI, Ni XVII + % with wavelengths between 10-12 angstroms or 14-15 angstroms + + define_group(2, brightest(20, + where( el_ion([Fe, Ni], [16,17]) + and (wl(10,12) or wl(14,15))))); + + % The same effect can be achieved using S-Lang array + % operations: + + % `all' and `bright' are arrays of integer line-indices: + + all = where( el_ion([Fe, Ni], [16,17]) + and (wl(10,12) or wl(14,15))); + bright = brightest(20, all); + define_group(2,bright); + define_group(3,all); % retains the complete list, +\end{verbatim} + +\end{isisfunction} + +\begin{isisfunction} +{delete\_group} %name +{delete a line group} %purpose +{delete\_group (group\_index)} %usage +{define\_group} + +The line group corresponding to {\tt group\_index} is deleted from the +internal list of defined groups. + +\end{isisfunction} + +\begin{isisfunction} +{el\_ion} %name +{flag line transitions from selected elements and ions} %purpose +{flag = el\_ion ([proton\_number\_list], [ion\_list])} %usage +{define\_group, trans, wl, flx, where, and, or, not} +\begin{verbatim} +Examples: + + % indices of lines from Oxygen and Magnesium +o_and_mg = where( el_ion([O,Mg])); % O = 8, Mg = 12 + + % group 2 = lines from ions VII, IX and XX +idlist = where( el_ion(, [7, 9, 20])); +define_group (2, idlist); + + % group 1 = lines from Fe XVII, Fe XVIII, Fe XIX +define_group (1, where( el_ion(26, [17:19]))); + + % indices of lines from all elements except Iron +not_fe = where(not(el_ion(Fe))); % Fe = 26 +\end{verbatim} + +{\it This function is intended to be used in conjunction with the +\slang\ intrinsic function {\tt where}.} It returns a character +array of length equal to the number of emission lines in the current +database line list. If a given line belongs to one of the listed +elements/ions, the corresponding array element is set equal to one, +otherwise the array element is zero. + +\end{isisfunction} + +\begin{isisfunction} +{flx} %name +{flag line transitions by which occupy a given flux range} %purpose +{flag = flx ([flx\_min], [flx\_max])} %usage +{define\_group, where, and, or, not} + +\begin{verbatim} +Examples: + % indices of lines brighter than f photons/cm^2/s +above_f = where ( flx(f) ); + + % indices of lines between f1 and f2 photons/cm^2/s +between_f1_f2 = where ( flx(f1, f2)); + +\end{verbatim} + +{\it This function is intended to be used in conjunction with the \slang\ +intrinsic function {\tt where}.} It returns a character array of length +equal to the number of emission lines in the current database line list. If +a given line falls within the specified flux range (photons cm${}^{-2}$ +s${}^{-1}$ for the currently defined model) ($F_{\rm min} \leq F < F_{\rm +max}$) the corresponding array element is set equal to one, otherwise the +array element is zero. + +\end{isisfunction} + +\begin{isisfunction} +{isis\_linelabel\_hook} +{Reformat line label strings for plotting} +{new\_label = isis\_linelabel\_hook (label)} +{plot\_group, line\_label\_default\_style, latex2pg} + +The energy level labels in the APED spectroscopy database are +formatted using \LaTeX-style syntax which must be reformatted for +plotting purposes so that subscripts and superscripts are handled +properly. + +If defined in the Global namespace, the function +\verb|isis_linelabel_hook| is used to handle this reformatting. +By default, \verb|isis_linelabel_hook| is defined as +\begin{verbatim} + public define isis_linelabel_hook (s) + { + return latex2pg (s); + } +\end{verbatim} +where \verb|latex2pg| is a simple parser which can handle +most of the APED database energy-level labels. + +To change the way line labels are reformatted, simply provide an +alternate definition for \verb|isis_linelabel_hook|. +\end{isisfunction} + +\begin{isisfunction} +{lines\_in\_group} %name +{get indices of lines in a given group} %purpose +{indices = lines\_in\_group (group\_index)} %usage +{line\_em, ratio\_em} + +This function retrieves indices of lines belonging to a group registered in +the internal group-list. It simplifies the use of functions which require a +list of line indices as input. + +\begin{verbatim} +Example: + + % define a group by a list of line indices + all = where( el_ion([Fe, Ni], [16,17]) ); + define_group (2, all); + + % retrieve a list of line indices from a group: + list = lines_in_group(2); + +\end{verbatim} +\end{isisfunction} + +\begin{isisfunction} +{line\_info} %name +{Get data for a single emission line} % purpose +{Struct\_Type s = line\_info (line\_index)} % usage +{page\_group} + +This function returns a \slang\ structure defined as +\begin{verbatim} +struct +{ + id, lambda, A, flux, Z, ion, upper, lower, up_name, lo_name + } +\end{verbatim} + +The structure fields give the line index (id), wavelength (lambda) +and Einstein A-value (A), and +identify the ion and energy levels involved (proton number (Z), ionization +state (ion), upper and lower energy level indices (upper/lower) and labels +(up\_name/lo\_name) if available. The ionization state is the integer +equivalent of the roman numeral; for example, an Fe XVII line would have +{\tt Z=26}, {\tt ion=17}. The total flux from this line in the currently +defined model (photons cm${}^{-2}$ s${}{-1}$) is returned in {\tt flux}. + +\end{isisfunction} + +\begin{isisfunction} +{line\_label\_default\_style} %name +{Get a structure with the default line labeling style parameters} %purpose +{s = line\_label\_default\_style ()} %usage +{plot\_group, isis\_linelabel\_hook} + +The returned structure has the following fields: +\begin{verbatim} + +___Field______Type____Default___Definition________________________________ + label_type int 0 0 for short labels (e.g. Ca XI); + 1 for long labels (e.g. Ca XI 2p 1s) +char_height float 1.0 + justify float 0 0=right, 0.5=centered, 1.0=left + angle float 90.0 [degrees] + top_frac float 0.6 coordinate of upper endpoint of indicator + line, as a fraction of the Y plot-range +bottom_frac float 0.7 coordinate of lower endpoint of indicator + line, as a fraction of the Y plot-range + offset float 0.1 spacing of text above upper endpoint of + indicator line as a fraction of the + indicator line length +\end{verbatim} + +\end{isisfunction} + +\begin{isisfunction} +{list\_branch} %name +{List radiative transition branching ratios for an ion} %purpose +{list\_branch (proton\_number, ion)} %usage +{list\_elev} + +For each energy level having more than one downward radiative +transition, this function lists the fraction of spontaneous decays +going into each downward transition along with the transition +wavelength (\AA), A-value (s${}^{-1}$), lower level index and line +list index. + +\begin{verbatim} +For example: + +isis> list_branch (He, 2); % He II + +He II +upper level = 5 +lower lambda branch A index + 3 1.640375e+03 3.3337e-01 3.3690e+07 14 + 4 1.640533e+03 6.6663e-01 6.7370e+07 15 + .... +\end{verbatim} + +The value $b_{ul}$ given in the {\tt branch} column is defined by +\begin{equation} + b_{ul} = { A_{ul} \over \sum_{k=1}^{u-1} A_{uk} } +\end{equation} +where $A_{uk}$ is the Einstein A value for the transition +from upper level $u$ to lower level $k$ and where the ground +state is $k=1$. +\end{isisfunction} + +\begin{isisfunction} +{list\_elev} %name +{browse the energy level structure of an ion} %purpose +{list\_elev (proton\_number, ion)} %usage +{plot\_elev} + +This command displays a listing of the energy level data for the +specified ion using a user defined pager. The energy level data +includes the level index, excitation energy (eV), statistical weight, +the total spontaneous downward transition rate (s${}^{-1}$), the +number of downward radiative transitions, $nLS$ quantum numbers, and a +name string. + +The pager is specified by the {\sc PAGER} environment variable. If +the {\sc PAGER} variable is not set, {\tt more} is the default. If +{\tt more} is not found on the command search path, the function will +fail with an error message. +\end{isisfunction} + +\begin{isisfunction} +{list\_group} %name +{list the currently defined line groups} %purpose +{list\_group} %usage +{define\_group, name\_group} + +This function lists the number of lines in each group registered in +the internal group-list along with the group-name, if one has been +defined using {\tt name\_group}. + +\end{isisfunction} + +\begin{isisfunction} +{name\_group} %name +{Define a mnemonic name for a group of lines} %purpose +{name\_group (group\_index, "group-name-string")} %usage +{define\_group, list\_group} +This function is used to provide a mnemonic name for a group of lines +registered in the internal group-list. +\begin{verbatim} +Example: + name_group (3, "Bright Fe XVII lines"); +\end{verbatim} +\end{isisfunction} + +\begin{isisfunction} +{oplot\_lines} %name +{over-plot line transitions on an energy level diagram} %purpose +{oplot\_lines (proton\_number, ion, line\_list, [style])} %usage +{plot\_elev, [o]plot\_elev\_subset}. + +This function over-plots the line transitions in {\tt line\_list} on an +existing energy level diagram; {\tt line\_list} may be a single line index +or an array of line indices. + +\begin{verbatim} +Example: + % plot an energy level diagram showing how the 10 brightest + % Fe XVI lines form (assuming a spectral model has been computed) + + Fe = 26; + plot_elev (Fe,16); + bright_fe16 = brightest (10, where(el_ion(Fe,16))); + oplot_lines(Fe,16, bright_fe16); + +\end{verbatim} + +Repeated invocations of {\tt oplot\_lines} will automatically switch +line styles to help distinguish the overlaid line transitions. +Depending on the current setting [ see {\tt style} ] either colors or +line styles (e.g. solid vs. dashed) are used to distinguish overlaid +data sets. To override the automatic style changes, the style index +can be specified explicitly for each plot. Alternatively, {\tt +plot\_auto\_color} can be used to disable the automatic style changes. +\end{isisfunction} + +\begin{isisfunction} +{page\_group} %name +{browse the data for lines in a given group} %purpose +{page\_group (group\_index or line\_list)} %usage +{plot\_group, trans, el\_ion, wl, flx} + +Line data for the specified lines is presented using a user-defined pager +program. For each line, the listing provides these values: +\begin{verbatim} + Line index + Wavelength [Angstrom] + Element name + Ion state (by charge or Roman numeral) + Einstein A [1/s] + Flux [photons/s/cm^2] + Energy level names and indices +\end{verbatim} +The integer line index can be used to refer to a specific +line in other commands e.g. {\tt plot\_group} + +An asterisk (*) by the wavelength indicates that emissivity data for +that line is loaded. The flux is computed using the currently defined +spectral model. If no model is defined, the flux is listed as zero. + +The pager is specified by the {\sc PAGER} environment variable. If +the {\sc PAGER} variable is not set, {\tt more} is the default. If +{\tt more} is not found on the command search path, the function will +fail with an error message. +\end{isisfunction} + +\begin{isisfunction} +{plot\_elev} %name +{plot the energy level diagram of an ion} %purpose +{plot\_elev (proton\_number, ion)} %usage +{list\_elev} + +An LS coupling energy level diagram is plotted using the current +format settings for color, line style, etc. This function requires +that LS coupling quantum numbers be available for all energy levels. + +\end{isisfunction} + +\begin{isisfunction} +{plot\_elev\_subset} %name +{plot a subset of the energy level diagram of an ion} %purpose +{[o]plot\_elev\_subset (proton\_number, ion, line\_list)} %usage +{plot\_elev, oplot\_lines} +\index{oplot\_elev\_subset@{\tt oplot\_elev\_subset}} + +This function [over]plots an energy level diagram consisting of all +energy levels involved in the given list of line transitions ({\tt +line\_list}). It can be used to examine a subset of the available +energy levels or to generate a color-coded energy level diagram. + +\end{isisfunction} + +\begin{isisfunction} +{plot\_group} %name +{over-plot a spectrum with all lines belonging to a particular group} %purpose +{plot\_group(group [, color\_index [,label\_style [, redshift]]])} %usage +{plot\_linelist, line\_label\_default\_style, isis\_linelabel\_hook, page\_group, save\_group} + +All lines in the specified group are displayed on the current plot, +meaning that a vertical line is plotted at the line wavelength along +with a text label. A line group may be specified by an array of line +indices or by giving the index of the group in the internal +group-list. + +This assumes that the currently active plot window already contains a +spectrum plot. + +If {\tt color\_index} is not specified, the current plot-color is +used; if {\tt color\_index} is specified, the color applies only to +the line labels and is not retained in the internal plot format +parameter structure. The third argument is used to specify formatting +information for the line labels. If this argument is an integer, it +specifies whether short (0) or long (1) text labels should be used. +This argument may also be a structure containing multiple style +parameters; see {\tt line\_label\_default\_style} for details. + +To plot lines at some Doppler shifted wavelength, specify the +redshift value defined as +\begin{equation} + {\rm redshift} = z = {\lambda_{\rm observed} \over \lambda_{\rm emitted}} - 1 +\end{equation} + +\begin{verbatim} +Example: + +plot_group (2); % plot group 2 with short labels + +plot_group (where(el_ion(Mg)), 2, 1); % plot Mg lines using long + % labels in color 2 +\end{verbatim} + +Similarly, to obtain red line labels which are 25\% smaller and tilted at a 45 +degree angle with an indicator line extending all the way to the plot border, +use +\begin{verbatim} + s = line_label_default_style (); + s.char_height = 0.75; + s.angle = 45; + s.bottom_frac = 0.0; + plot_group (g, red, s); +\end{verbatim} + +\end{isisfunction} + +\begin{isisfunction} +{plot\_linelist} %name +{over-plot a spectrum with a user-provided line list} %purpose +{plot\_linelist (lambdas, labels, [, color\_index [,label\_style [, redshift]]])} %usage +{line\_label\_default\_style, isis\_linelabel\_hook, page\_group, save\_group} + +This function is essentially the same as \verb|plot_group| +except that the line wavelengths and labels are provided +explicitly by the user rather than being drawn from the +spectroscopy database. + +\end{isisfunction} + +\begin{isisfunction} +{save\_group} %name +{save line parameters to an ASCII file} %purpose +{save\_group (group\_index or line\_list, filename)} %usage +{page\_group} +A list of lines may be specified using a \slang\ array-variable +or by specifying the index of a group in the internal group-list. +Repeated saves to the same filename append data to the file +rather than overwriting it. +\begin{verbatim} + Example: + fe17 = where (el_ion(Fe,17)); + save_group (fe17, "fe17_lines.txt"); +\end{verbatim} +\end{isisfunction} + +\begin{isisfunction} +{trans} %name +{flag line transitions from a given ion} %purpose +{flag = trans ([proton\_number[, ion\_number [, upper\_list[, lower\_list]]]])} %usage +{define\_group, el\_ion, wl, flx, where, and, or, not} +\begin{verbatim} +Examples: + + % g = all lines +g = where( trans()); + % g = Neon line list +g = where( trans(Ne)); + % g = Ne IX lines +g = where( trans(Ne, 9)); + % g = Ne IX lines from levels 20-30 downward +g = where( trans(Ne, 9, [20:30])); + % g = Ne IX lines from levels 20-30 down to levels 1-5 +g = where( trans(Ne, 9, [20:30], [1:5])); + % g = Ne IX lines down to levels 1-5 +g = where( trans(Ne, 9, , [1:5])); + +\end{verbatim} + +{\it This function is intended to be used in conjunction with the +\slang\ intrinsic function {\tt where}.} It returns a character +array of length equal to the number of emission lines in the current +database line list. If a given line belongs to one of the listed +elements/ions, the corresponding array element is set equal to one, +otherwise the array element is zero. + +\end{isisfunction} + +\begin{isisfunction} +{unblended} %name +{get indices of unblended lines in a given list} %purpose +{indices = unblended (frac, wl\_sep, allowed\_type, line-list)} %usage +{page\_group, el\_ion, line\_em, ratio\_em} + +A line with wavelength $\lambda_k$ is defined to be ``unblended'' if the +flux from the line of interest dominates the total flux from nearby {\it +contaminating} lines. More precisely, the criterion is that $\sum_{j +\neq k} F(\lambda_j) < {\tt frac}\times F(\lambda_k)$ where the summation +extends over all {\it contaminating} lines with wavelength $\lambda_j$ +within $\pm {\tt wl\_sep}\lambda_k$ of the line of interest ($\lambda_k$). +The blend type {\tt allowed\_type} specifies which lines are to be +considered contaminants. + +{\tt allowed\_type = 0} indicates that wavelength spacing is the only +determining factor; any other line falling within the stated wavelength band +limit is considered a contaminant. {\tt allowed\_type = SAME\_ELEM} means +that lines from the same element are not considered contaminants and are +excluded from the summation over $j$. Similarly, {\tt allowed\_type = +SAME\_ION} means lines from the same ionization state are not considered +contaminants. To find lines free of blends with any ion of any element, use +{\tt allowed\_type = SAME\_ELEM \& SAME\_ION}. + +Note that, because this function requires line fluxes, a spectrum +model must be computed {\it before} using it. + +\begin{verbatim} +Example: + % define and compute a model spectrum +load_model("model_dat"); +(lo, hi) = linear_grid (1, 25, 6000); +flux = model_spectrum (lo, hi); + + % find the indices of the + % 100 brightest lines between 1-100 Angstrom + % in that model spectrum + +b = brightest (100, where(wl(1,100))); + + % lines with < 10% "contamination" + % from other elements + % within +/- 0.001*lambda + +ue = unblended (0.1, 0.001, SAME_ELEM, b); + + % lines for which > 90% + % of the flux within +/- 0.001*lambda + % comes from a single ion of a single + % element: + +uei = unblended (0.1, 0.001, SAME_ELEM & SAME_ION, b); + +\end{verbatim} + +For the purpose of selecting unblended lines, the total flux from each line +is summed over all model components without regard to the relative +Doppler-shifts or line-profile shapes involved. In particular, the current +implementation of this function does not support searching for unblended +lines in models which have components at significantly different redshifts; +wavelength separation is always determined using the rest-wavelength. +\end{isisfunction} + +\begin{isisfunction} +{wl} %name +{flag line transitions from a given wavelength range} %purpose +{flag = wl ([min\_wavelen], [max\_wavelen])} %usage +{page\_group, where, and, or, not} + +\begin{verbatim} +Examples: + +% indices of all lines longward of 20 angstroms + above_20 = where(wl(20)); + +% indices all lines shortward of 30 angstroms + below_30 = where(wl(,30)); + +% indices Fe XVI lines between 10 and 15 angstroms + fe_16_subset = where( el_ion(26,16) and wl(10,15)); +\end{verbatim} + +{\it This function is intended to be used in conjunction with the +\slang\ intrinsic function {\tt where}.} It returns a character +array of length equal to the number of emission lines in the current +database line list. If a given line's rest wavelength lies inside the +specified wavelength range ($\lambda_{\rm min} \leq \lambda < \lambda_{\rm +max}$) the corresponding array element is set equal to one, otherwise the +array element is zero. +\end{isisfunction} + +\newpage +\section{Access to the Plasma Emissivity Database} +\label{sec:plasma-db} + +The emissivity database contains theoretical models of the state of an +emitting plasma as a function of its physical state variables. The +standard emissivity database is generated for conditions of +collisional ionization equilibrium. Although \isisx is designed to +make it possible to work with other databases (e.b. photoionized +plasmas), at this writing the collisional ionization database is the +only one available. + +In collisional equilibrium, the primary physical state variables are +the electron temperature $T$ and the electron density $n$. Observed +line intensities and line ratios may be used to infer the temperature +and density (or distribution of temperatures and densities) in the +emitting plasmas. To facilitate this analysis, \isisx provides +several functions to manipulate the line emissivity tables. + +{\tt line\_em} retrieves the emissivity of a single line (or the sum +over lines in a group) as a function of density and/or temperature. +{\tt ratio\_em} generates line (or line group) ratios as a function of +density and/or temperature. Details of the ionization balance as a +function of temperature can be examined using {\tt ion\_bal} and {\tt +ion\_frac}. Each of these functions returns arrays of emissivities or +ion-fractions when can then be plotted ({\tt [o]plot}) or used in +computations via the \slang\ array-oriented mathematical operators. + +For information on computing spectral models see \S\ref{sec:spectral_models}. + +\begin{isisfunction} +{db\_grid} %name +{Returns the density and temperature grid used by the spectroscopy database} %purpose +{Struct\_Type = db\_grid ([file | Struct\_Type])} %usage +{plasma, [v]list\_db} + +\verb|db__grid| returns a structure of the form +\begin{verbatim} + s = struct {temp, dens} +\end{verbatim} +whose fields are arrays giving the temperature [Kelvin] and +electron density [cm$^{-3}$] grids used to compute emissivities +in the spectroscopy database. + +If no argument is given, the grid used by the currently loaded +database is returned. + +\end{isisfunction} + +\begin{isisfunction} +{free\_alt\_ioniz} %name +{Free memory for alternate ionization balance table} %purpose +{free\_alt\_ioniz ()} %usage +{load\_alt\_ioniz} + +If an alternate ionization balance table is loaded, it is used to +re-scale the line and continuum emissivities. Freeing the alternate +ionization balance table reverts to the ionization balance that was +used to generate the emissivity tables (no re-scaling is then +performed). + +\end{isisfunction} + +\begin{isisfunction} +{get\_abundances} %name +{Get abundance table values} %purpose +{Struct\_Type = get\_abundances ([id | name]);} %usage +{set\_abund, list\_abund, add\_abundances} + +This function returns a structure with fields \verb|Z[]|, +\verb|abun[]| and \verb|name| containing the proton number of +each element, its abundance and the name of the abundance +table, respectively. The abundance table may be specified +either by the name or numerical index shown in the listing +produced by \verb|list_abund|. If no table is specified, the +current default table is returned. The abundance values are +normally given as log cosmic abundance by number, relative to +Hydrogen = 12.0. + +\end{isisfunction} + +\begin{isisfunction} +{get\_contin} +{get continuum contributions by ion} +{p = get\_contin (lo, hi, temp, [dens], [Z], [ion])} +{plasma, line\_em} +This function provide access to the continuum emissivity tables in the +spectroscopy database. + +\begin{verbatim} + lo = bin low edge [Angstrom] + hi = bin high edge [Angstrom] +temp = electron temperature (K) +dens = electron density [cm^(-3)] [default=1.0] + Z = proton number + ion = ion state (1, 2, ... Z+1) +\end{verbatim} + +For the specified electron temperature, this function returns the +continuum spectral contribution ({\tt photon cm${}^3$ sec${}^{-1}$}) +vs. wavelength (\AA) for the true continuum ({\tt true}), which is the +sum of Bremsstrahlung, radiative recombination and two-photon +emission, and the pseudo-continuum due to weak line emission ({\tt +pseudo}) using the input wavelength grid. + +These spectra are organized in a structure defined by +\begin{verbatim} +struct +{ + true, pseudo +} +\end{verbatim} +(each structure component is a \slang\ floating point +array of length $N$). + +If the electron density is not specified, the default value is for a +low-density coronal plasma (or whatever is available in the database +files). If a particular element is specified (by proton number {\tt +Z}) the result contains the continuum contributions for that element +only (summed over ions), otherwise, the result will be summed over all +available elements. Similarly, if a specific ion is specified (by +proton number {\tt Z} and ionization state {\tt j}), the result +contains the contribution for that ion only. +\begin{verbatim} +Example: + + plasma (aped); % initialize the database + + (lo, hi) = linear_grid(1,20,5000); % define a wavelength grid + p = get_contin (lo, hi, 2.e6); % get continua for T=2.0e6 K + hplot(lo, hi, p.true); % plot the true continuum +\end{verbatim} +\end{isisfunction} + +\begin{isisfunction} +{ion\_bal} %name +{get ion fractions at a specified temperature} %purpose +{(ion, frac) = ion\_bal (proton\_number, temp, [ioniz\_table\_id])} %usage +{ion\_frac, load\_alt\_ioniz} +The ion fractions are normalized so that the sum over ions of a given +element is unity. +\begin{verbatim} + temp = input array of temperatures [K] + frac = output array of ion fractions + ion = output array of ion states + (1 = neutral, 2 = once ionized, etc.) +ioniz_table_id = index of ionization table (0=std or 1=alt) +\end{verbatim} +The ionization table index is used only if more than one ionization +table is loaded (see also {\tt load\_alt\_ioniz}); the default is to use +the standard table ({\tt ioniz\_table\_id = 0}). +\end{isisfunction} + +\begin{isisfunction} +{ion\_frac} %name +{get ion fraction vs. temperature} %purpose +{frac = ion\_frac (proton\_number, ion, temp, [ioniz\_table\_id])} %usage +{ion\_bal, load\_alt\_ioniz} +The ion fractions are normalized so that the sum over ions of a given +element is unity. +\begin{verbatim} + temp = input array of temperatures [K] + frac = output array of ion fractions + ioniz_table_id = index of ionization table (0=std or 1=alt) +\end{verbatim} +The ionization table index is used only if more than one ionization +table is loaded (see also {\tt load\_alt\_ioniz}); the default is to use +the standard table ({\tt ioniz\_table\_id = 0}). +\end{isisfunction} + +\begin{isisfunction} +{line\_em} %name +{Compute line-group emissivity vs. temperature and/or density} %purpose +{emis = line\_em (l\_array, [temp] [,dens])}%usage +{group, ratio\_em, line\_em1, get\_contin} +\begin{verbatim} +_Variable_____Size______Value____________________________________ + l_array nl Input 1-D array of line indices + temp nt Input 1-D array of temperatures [K] + dens nd (optional) Input 1-D array of densities [cm^(-3)] + emis (nt)x(nd) Output 1-D or 2-D emissivity array. +\end{verbatim} +This function computes +\begin{equation} + {\tt emis} = + \varepsilon\left( T,\rho\right) = + \sum_k \varepsilon \left(T, \rho; k\right) +\end{equation} +where $\varepsilon \left(T ,\rho; k\right)$ is the emissivity of emission +line $k$ at temperature $T$ and density $\rho$ with elemental abundance and +ionization balance factors included. When the density array is absent (the +lowest available density data is used as the default) and when either $nt=1$ +or $nd=1$, {\tt emis} is a 1-D array of size max($nt,nd$). When both $nt>1$ +and $nd>1$, {\tt emis} is a $nt\times nd$ 2-D array with the first index +corresponding to density and the second to temperature. For example, +\begin{verbatim} + t=10.0^[6.0:7.0:0.05]; % temperature array, nt=21 + % log-spacing + d=10.0^[11.0:13.0:0.25]; % density array, nd=9 + % log-spacing + + k = lines_in_group(2); % list of lines in group 2 + + em2 = line_em(k,t,d); % em2 = 2-D emissivity array + % with dimension [9,21] + + y = em2[3,7]; % line emissivity at + % density d[3], temperature t[7], + % summed over lines in group 2. + + emt = line_em(k[2], t, d[4]); % emt = 1-D emissivity array + % with dimension [21] + + z = emt[9]; % z = emissivity line line k[2] at + % density d[4], temperature t[9] +\end{verbatim} +\end{isisfunction} + +\begin{isisfunction} +{line\_em1} %name +{Retrieve line emissivity table} %purpose +{(emis, temp, dens) = line\_em1 (line\_index)}%usage +{group, ratio\_em, line\_em, get\_contin} + +This function is similar to {\tt line\_em} except that it returns the +line emissivity values tabulated in the spectroscopy database rather +than interpolating those values onto a user-specified +temperature/density grid. For a particular line, it returns three +arrays $\varepsilon_i$, $n_i$, $T_i$, of size $N$, (where $N$ is the +number of $(n,T)$ points available in the database) giving the +emissivity as a function of density and temperature: +\begin{equation} + \varepsilon_i (n_i, T_i), i = 1,2,..N +\end{equation} +\end{isisfunction} + +\begin{isisfunction} +{list\_abund} %name +{List the available cosmic abundance tables} %purpose +{list\_abund ([verbose]);} %usage +{set\_abund, get\_abundances} + +The abundance table in the spectroscopy database may contain +several sets of elemental abundances. This function lists the +available abundance tables providing an integer index which is +used in function arguments to select a particular table. By +default, the optional argument is \verb|verbose=0| so that only +the names of the tables are listed. Set \verb|verbose=1| to see +the abundance values listed as well. + +\end{isisfunction} + +\begin{isisfunction} +{list\_db} %name +{List density and temperature range covered by the spectroscopy database} %purpose +{list\_db ([file | Struct\_Type])} %usage +{plasma, vlist\_db, db\_grid} + +\verb|list_db| generates a short listing showing only the available +range of density and temperature; \verb|vlist_db| generates a +more verbose listing showing all available density-temperature points. + +If no argument is given, the grid used by the currently loaded +database is listed. + +\end{isisfunction} + +\begin{isisfunction} +{vlist\_db} %name +{List density and temperature range covered by the spectroscopy database} %purpose +{vlist\_db ([file | Struct\_Type])} %usage +{plasma, list\_db, db\_grid} +Similar to \verb|list_db|, but provides a more detailed listing. +\end{isisfunction} + +\begin{isisfunction} +{load\_alt\_ioniz} %name +{Load an alternate ionization balance table} %purpose +{load\_alt\_ioniz (file)} %usage +{free\_alt\_ioniz} + +Use this function to specify an alternate ionization balance table. +Such a table may be used to re-scale the plasma emissivities as a simple way +of seeing the effect of an alternate ionization balance calculation +without repeating a complete spectrum synthesis calculation. + +By default, when two ionization balance tables are loaded, all +emissivities are re-scaled using the alternate ionization balance table. +The emissivities are re-scaled so that +\begin{equation} + \varepsilon_1 = { X_1(T; Z,q) \over X_0(T; Z,q) } \varepsilon_0 +\end{equation} +where $\varepsilon_0$ is the tabulated emissivity computed using +ionization fraction $X_0 (T; Z, q)$ for ion $(Z, q)$ at temperature $T$ and +where $X_1 (T; Z, q)$ is the ionization fraction from the alternate +ionization balance table. + +To revert to the standard ionization balance table, delete the +alternate table using {\tt free\_alt\_ioniz}. +\end{isisfunction} + +\begin{isisfunction} +{plasma} %name +{load the emissivity database} %purpose +{plasma (Struct\_Type ~[,density\_range ~[, temp\_range]] )} %usage +{atoms, [v]list\_db} +\index{{\tt Use\_Memory}} +\index{Emissivity Database!memory usage} +\index{{\tt Incomplete\_Line\_List}} +\index{Emissivity Database!completeness of wavelength tables} + +This function is similar to the {\tt atoms} function and uses the same +database configuration structure. It causes \isisx to load the atomic +data files and the line and continuum emissivity tables into memory +(actually, because of their size, the continuum emissivity tables are +just scanned so that continua may be quickly retrieved from disk as +needed). + +The optional arguments {\tt density\_range} and {\tt temp\_range} are +two element floating point arrays specifying a subset of densities +(cm${}^{=3}$) and temperatures (Kelvin) for which line and continuum +emissivities are to be loaded from the database. + +Access to the emissivity tables is usually most efficient if the all +of the tables fit in memory at once (the default mode assumes that +this is the case). For large databases, however, this may not be +practical. + +To support very large line lists, it may be necessary to +increase the size of an internal hash table. To increase the +size of the table, set the intrinsic variable +\verb|EM_Hash_Table_Size_Hint| to a value at least 25\% larger +than the number of emission lines in your database. + +The {\tt Use\_Memory} variable is used to indicate whether +the emissivity tables should be loaded into memory all at once +or should be accessed from disk files as needed: + +\begin{verbatim} + __Use_Memory__ ____Behavior____ + 0 Read lines and continua on-demand + 1 Read lines up front, continua on-demand + 2 Read lines on-demand, continua up front + 3 Read lines and continua up front +\end{verbatim} + +As long as sufficient memory is available, model computations will +be fastest if all the data is loaded into memory at once +(\verb|Use_Memory=3|, the default), thereby minimizing the number +of relatively slow disk accesses. However, when not making use of +the continuum tables, one might prefer \verb|Use_Memory=1|; by not +loading the continuum tables, database input is faster and the +run-time memory footprint is minimized. On small memory machines, +one might prefer \verb|Use_Memory=0|. + +\isisx maintains a lookup table containing a complete list of +all lines in both the atomic database and in the emissivity database. + +In order to ensure that this table is complete, \isisx normally scans +the line emissivity tables on input and merges any "new" lines into +the internal tables. However, this step is necessary only if the +spectroscopy database wavelength tables are incomplete (in the sense +that some lines in the emissivity tables are not listed in the +wavelength tables loaded by \isisx). To stop \isisx from carrying out +this (sometimes slow) scanning step, set {\tt Incomplete\_Line\_List = +0}; when this variable is non-zero, input line emissivity tables will +be scanned automatically. + +Note that if the scan is not performed and "new" lines are present in +the line emissivity tables, those lines will be ignored and an error +message will be generated. + +\end{isisfunction} + +\begin{isisfunction} +{ratio\_em} %name +{compute a line-group emissivity ratio vs. temperature and density} %purpose +{ratio = ratio\_em (l1\_array, l2\_array [,temp [,dens]])} %usage +{line\_em} +This function computes +\begin{equation} +R\left( T,\rho\right) = { \varepsilon_1\left( T,\rho\right) \over +\varepsilon_2\left( T,\rho\right)} +\end{equation} +where $\varepsilon_g\left( T,\rho\right)$ is the result of {\tt +line\_em} for line group $g$. +\end{isisfunction} + +\begin{isisfunction} +{set\_abund} %name +{Choose a cosmic abundance table} %purpose +{set\_abund (id | name);} %usage +{list\_abund, get\_abundances, atoms, plasma} + +The abundance table in the spectroscopy database may contain +several sets of elemental abundances. This function specifies +an abundance table either by name or by index in the list of +tables generated by {\tt list\_abund}. If the specified +abundance table is different from the one used to generate the +line and continuum emissivity tables, the emissivities are +re-scaled using the specified table. + +\end{isisfunction} + +\newpage +\section{Defining a Plasma Emission Model} +\label{sec:spectral_models} + +The section describes how to define a plasma emission model by summing +line and continuum emissivity components tabulated in the spectroscopy +database. Plasma models may also be obtained using the {\tt XSPEC} +module (see \S\ref{chap:xspec-module}). + +After initializing the spectroscopy database (see \S +\ref{sec:atomic-db} and \S \ref{sec:plasma-db}), multicomponent +plasma models may be generated using the function +\verb|create_aped_fun()| (See \S \ref{sec:fitting-data}). + +% use {\tt load\_model} and/or {\tt edit\_model} to +% define a multi-component plasma model. The current model parameters +% may be browsed with {\tt list\_model} or saved to a disk file using +% {\tt save\_model}. + +% Similarly, multiple plasma models may be created using the +% functions \verb|mt_def_model|, \verb|mt_calc_model|. These models +% are represented as instances the ISIS-intrinsic data type, +% \verb|Model_Type|. Such models may be saved as ASCII files +% and reloaded using the functions \verb|mt_save_model|, +% \verb|mt_load_model|. + +% After generating a wavelength grid, perhaps using {\tt +% linear\_grid}, the spectrum of this model can be computed using +% {\tt eval\_fun} and fitted using \verb|fit_counts| or +% \verb|fit_flux|. + +By default, spectral line profiles are delta-functions; {\tt +use\_thermal\_profile} specifies that a thermal line profile +should be used instead. + +\begin{isisfunction} +{append\_model} %name +{Append model components using \slang\ arrays} %purpose +{append\_model (state[]);} %usage +{default\_plasma\_state, model\_spectrum, define\_model} + +{\it This interface is obsolete and is no longer supported. +A much more versatile interface is provided by +\verb|create_aped_fun|.} + +This function is identical to the \verb|define_model| function +except that it appends an array of components to an existing model. +If no model has been defined, a new model is created. +See \verb|define_model| for details. +\end{isisfunction} + +\begin{isisfunction} +{create\_aped\_fun} %name +{Create a custom fit-function using a multi-component APED spectrum} %purpose +{create\_aped\_fun (name, Struct\_Type [, hook\_ref])} %usage +{fit\_fun, aped\_fun\_details, create\_aped\_line\_modifier, create\_aped\_line\_profile} +\index{Fitting a spectrum model} +\index{model spectrum, Fitting a} +\index{spectrum model} +\index{Emissivity Database!fitting a spectrum model} +\index{APED!fitting a spectrum model} + +This function creates a custom fit-function which computes a +multi-component APED model. The first argument gives the name of +the new fit-function and the second argument is a +\verb|Struct_Type| which defines the number of spectrum components +in the function's fit-parameter list. The values contained +in this structure provide default values for the associated fit +parameters. The optional third argument +is used to select specific lines and continua and is discussed +further below. + +The \verb|Struct_Type| argument has the form of the structure +returned by the \verb|default_plasma_state()| function: +\begin{verbatim} + struct { norm, temperature, density, + elem, elem_abund, metal_abund, + vturb, redshift } +\end{verbatim} +where +\begin{verbatim} + norm[] = float array of size Num_Components + temperature[] = float array of size 1 or Num_Components + density[] = float array of size 1 or Num_Components + elem[] = NULL or int array of size Num_Elements + elem_abund[] = NULL or float array of size Num_Elements + metal_abund = float + vturb = float + redshift = float +\end{verbatim} +All components in the resulting model have the same values of +\verb|metal\_abund|, \verb|vturb|, \verb|redshift|, \verb|elem|, +\verb|elem\_abund|. For detailed definitions of these struct +fields, see \verb|default_plasma_state()|. + +EXAMPLE 1: + +In the simplest case, a new fit-function can +be generated with one line: +\begin{verbatim} + create_aped_fun ("xaped", default_plasma_state()); +\end{verbatim} +This creates a fit-function called \verb|xaped| which allows +fitting a single temperature APED spectrum. This function can be +used like any other fit-function; the resulting fit-parameter list +looks like this: +\begin{verbatim} +isis> create_aped_fun ("xaped", default_plasma_state()); +isis> fit_fun ("xaped(1)"); +isis> list_par; +xaped(1) + idx param tie-to freeze value min max + 1 xaped(1).norm 0 1 1 0 0 + 2 xaped(1).temperature 0 1 1e+07 0 0 + 3 xaped(1).density 0 1 1 0 0 + 4 xaped(1).vturb 0 1 0 0 0 + 5 xaped(1).redshift 0 1 0 0 0 + 6 xaped(1).metal_abund 0 1 1 0 0 +isis> +\end{verbatim} +Any parameters not explicitly specified will receive reasonable +defaults. Note that by default, all parameters are frozen and the +parameter ranges are unbounded. To fit such a function +to data, first thaw a few selected parameters and optionally +provide reasonable parameter ranges. + +EXAMPLE 2: + +Generating multicomponent models is not much more complicated. To +define a model which corresponds to an APED spectrum with 3 +temperature components: +\begin{verbatim} +variable n = 3; +variable t = default_plasma_state (); + +t.norm = Double_Type[n]; +t.norm[*] = 1.0; +t.temperature = 1.e6 + (1.e7 * [1:n])/n; +create_aped_fun ("xaped", t); +\end{verbatim} + +This yields a function with the following parameter list: +\begin{verbatim} + isis> fit_fun ("xaped(1)"); + isis> list_par; + xaped(1) + idx param tie-to freeze value min max + 1 xaped(1).norm1 0 1 1 0 0 + 2 xaped(1).norm2 0 1 1 0 0 + 3 xaped(1).norm3 0 1 1 0 0 + 4 xaped(1).temperature1 0 1 4333333 0 0 + 5 xaped(1).temperature2 0 1 7666667 0 0 + 6 xaped(1).temperature3 0 1 1.1e+07 0 0 + 7 xaped(1).density 0 1 1 0 0 + 8 xaped(1).vturb 0 1 0 0 0 + 9 xaped(1).redshift 0 1 0 0 0 + 10 xaped(1).metal_abund 0 1 1 0 0 +\end{verbatim} + +EXAMPLE 3: + +As a more complex example, one could specify an overall metal +abundance of 0.5 solar and specify e.g. Ne, Mg and Fe explicitly: + +\begin{verbatim} +t.norm = Double_Type[n]; +t.norm[*] = 1.0; +t.temperature = 1.e6 + (1.e7 * [1:n])/n; +t.density = 1.0; +t.metal_abund = 0.5; +t.elem = [Ne, Mg, Fe]; +t.elem_abund = [1.0, 3.1, 0.0]; +t.redshift = 0.0; + +create_aped_fun ("xaped", t); +\end{verbatim} + +This produces the following parameter list: +\begin{verbatim} +xaped(1) + idx param tie-to freeze value min max + 1 xaped(1).norm1 0 1 1 0 0 + 2 xaped(1).norm2 0 1 1 0 0 + 3 xaped(1).norm3 0 1 1 0 0 + 4 xaped(1).temperature1 0 1 4333333 0 0 + 5 xaped(1).temperature2 0 1 7666667 0 0 + 6 xaped(1).temperature3 0 1 1.1e+07 0 0 + 7 xaped(1).density 0 1 1 0 0 + 8 xaped(1).vturb 0 1 0 0 0 + 9 xaped(1).redshift 0 1 0 0 0 + 10 xaped(1).metal_abund 0 1 0.5 0 0 + 11 xaped(1).Ne 0 1 1 0 0 + 12 xaped(1).Mg 0 1 3.1 0 0 + 13 xaped(1).Fe 0 1 0 0 0 +\end{verbatim} + +EXAMPLE 4: + +The optional \verb|hook_ref| argument can be used to +indicate that the model should compute only a specified +combination of lines and continua. It provides +a reference to a function defined as +\begin{verbatim} + Struct_Type f = hook (id) +\end{verbatim} +where the \verb|id| argument provides the instance of +the current fit-function (e.g. 1 for \verb|xaped(1)| +and 4 for \verb|xaped(4)|) and the returned structure looks like +\begin{verbatim} + variable f = struct {contrib_flag, line_list} +\end{verbatim} +These struct fields carry the corresponding optional arguments +which are accepted by \verb|mt_calc_model| and +\verb|model_spectrum| (see \verb|model_spectrum| for details). + +For example, to generate a function which can compute the +line-spectrum of a single ion (with model continuum excluded), we +can do the following: In addition to the above \verb|Struct_Type| +parameter definitions, we first provide an appropriate hook +function: + +\begin{verbatim} + +% we want to look at Ne and Mg lines: +variable Ne_Lines = where (el_ion(Ne,10)); +variable Mg_Lines = where (el_ion(Mg,12)); +variable Contrib_Flag = MODEL_LINES; + +define xaped_hook (id) +{ + variable f = mt_model_qualifier(); + f.contrib_flag = Contrib_Flag; + + if (id == 1) f.line_list = Ne_Lines; + else if (id == 2) f.line_list = Mg_Lines; + else f = NULL; + + return f; +} + +create_aped_fun ("xaped", t, &xaped_hook); +\end{verbatim} + +With this definition, \verb|xaped(1)| will compute the Ne~X line +spectrum and \verb|xaped(2)| will compute the Mg~XII line +spectrum. Note that the global variable \verb|Contrib_Flag| +defined in this example provides a mechanism to alter the behavior +of both functions. without changing \verb|xaped_hook| or defining +a new function via \verb|create_aped_fun|. + +EXAMPLE 5: + +In some applications, it may be useful to modify selected line +emissivities according to a user-defined function. When this +user-defined function has adjustable parameters, it may be +useful to allow those parameters to vary during a fit. + +For example, suppose we've defined a custom APED spectral model +as defined above: +\begin{verbatim} + create_aped_fun ("xaped", template_struct); +\end{verbatim} + +To adjust the emissivity of selected spectral lines, we can +write a \slang\ function of the form: +\begin{verbatim} + define line_emis_modifier (params, line_id, state, emis) + { + variable info = line_info(line_id); + % + % ... modify the emissivity of selected emission lines ... + % + return emis; + } +\end{verbatim} +This function accepts an array of parameters, an integer line +index, a structure containing plasma state information (e.g +temperature and number density) and the value of the line +emissivity for the current plasma state, and it should return a +new value for the line emissivity. This function will be called +while the \verb|xaped| function is being computed and its +adjustable parameters will be included in the fit. + +To enable this function to perform these tasks, we must +register it as a line-modifier function: +\begin{verbatim} + create_aped_line_modifier ("modifier", &line_emis_modifier, ["a", "b", "c"]); +\end{verbatim} +Note that we have provided a name for the function and each of +its parameters. These names will appear in the output of +\verb|list_par|. + +To invoke this helper function, we specify a fit-function using +the syntax: +\begin{verbatim} + fit_fun ("xaped(1, modifier(1))"); +\end{verbatim} +This syntax is a generalization of the ``operator function'' +syntax (see \verb|set_function_category|). At run-time, the +helper function \verb|modifier(1)| is evaluated and returns +values that are interpreted by the \verb|xaped| model function. +With this model definition, the list of fit parameters looks +something like: +\begin{verbatim} +xaped (1, modifier(1)) + idx param tie-to freeze value min max + 1 modifier(1).a 0 0 0 0 0 + 2 modifier(1).b 0 0 0 0 0 + 3 modifier(1).c 0 0 0 0 0 + 4 xaped(1).norm 0 1 1 0 0 + 5 xaped(1).temperature 0 1 1e+07 0 0 + 6 xaped(1).density 0 1 1 0 0 + 7 xaped(1).vturb 0 1 0 0 0 + 8 xaped(1).redshift 0 1 0 0 0 + 9 xaped(1).metal_abund 0 1 1 0 0 +\end{verbatim} + +The \verb|modifier| function may require additional +user-defined data to perform the necessary computations. +One solution to this problem is to store the additional data +in global variables, but this is sometimes inconvenient because +the implementation of the \verb|modifier| function then +depends on symbols with global scope. + +An alternative is to have additional user-defined arguments +passed to the modifier function when it is called. The +advantage to this approach is that the line modifier function +can be defined without referring to global variables. + +For example, suppose we want to pass 2 additional arguments to +the line modifier function. First, write a line modifier +function that handles the additional arguments: +\begin{verbatim} + define my_mod (params, line_id, state, emis, extra1, extra2) + { + %... perform calculation... + return emis; + } +\end{verbatim} +Then, declare the number of extra arguments (2) in the call to +\verb|create_aped_line_modifier|: +\begin{verbatim} + create_aped_line_modifier ("mod", &my_mod, ["X", "Y"], 2); +\end{verbatim} +Now, simply use the extra arguments in the fit-function +definition: +\begin{verbatim} + fit_fun ("xaped (1, my_mod(1, Value1, Value2))"); +\end{verbatim} +When this fit-function is evaluated, the extra arguments +provided will be passed to \verb|my_mod|. In this case, +\verb|my_mod| will be called with \verb|extra1=Value1| and +\verb|extra2=Value2|. + +EXAMPLE 6: + +In some applications, it may be useful to introduce a +user-defined line profile function. When this user-defined +function has adjustable parameters, it may be useful to allow +those parameters to vary during a fit. + +User-defined line profile functions can be introduced using a +helper function in a manner similar to that described in the +previous example. Because line profile functions are evaluated +a large number of times and are not easily vectorized, these +functions are best implemented in a compiled language. +A user-defined line profile function can be compiled as a +shared library and imported at run-time using the function +\verb|load_line_profile_function|. + +To register the line profile function as a helper function, +use +\begin{verbatim} + fptr = load_line_profile_function ("example-profile.so", "square"); + create_aped_line_profile ("square_profile", &fptr, ["width"]); +\end{verbatim} +Note that we have provided a name for the function and each of +its parameters. These names will appear in the output of +\verb|list_par|. + +To invoke this helper function, we specify a fit-function using +the syntax: +\begin{verbatim} + fit_fun ("xaped(1, square_profile(1))"); +\end{verbatim} +This syntax is a generalization of the ``operator function'' +syntax (see \verb|set_function_category|). At run-time, the +helper function \verb|square_profile(1)| is evaluated and returns +values that are interpreted by the \verb|xaped| model function. +With this model definition, the list of fit parameters looks +something like: +\begin{verbatim} +xaped (1, square_profile(1)) + idx param tie-to freeze value min max + 1 square_profile(1).width 0 0 0 0 0 + 2 xaped(1).norm 0 1 1 0 0 + 3 xaped(1).temperature 0 1 1e+07 0 0 + 4 xaped(1).density 0 1 1 0 0 + 5 xaped(1).vturb 0 1 0 0 0 + 6 xaped(1).redshift 0 1 0 0 0 + 7 xaped(1).metal_abund 0 1 1 0 0 +\end{verbatim} + +Note that multiple ``helper'' functions maybe used +simultaneously by providing a comma-separated list of helper +functions in the model definition. For example: +\begin{verbatim} +fit_fun ("xaped(1, modifier(1), square_profile(1))"); +\end{verbatim} + +\end{isisfunction} + +\begin{isisfunction} +{create\_aped\_line\_modifier} %name +{Register a line-emissivity modifier function as an APED model helper function} %purpose +{create\_aped\_line\_modifier (name, Ref\_Type [, param\_name\_array [,num\_extra\_args]])} %usage +{fit\_fun, create\_aped\_line\_profile} + +See \verb|create_aped_fun| for details. + +\end{isisfunction} + +\begin{isisfunction} +{create\_aped\_line\_profile} %name +{Register a line profile function as an APED model helper function} %purpose +{create\_aped\_line\_profile (name, Line\_Profile\_Type [, param\_name\_array])} %usage +{fit\_fun, create\_aped\_line\_modifier, load\_line\_profile\_function} + +See \verb|create_aped_fun| for details. + +\end{isisfunction} + +\begin{isisfunction} +{default\_plasma\_state} %name +{Return a structure describing the default CIE plasma state} %purpose +{Struct\_Type = default\_plasma\_state ()} %usage +{create\_aped\_fun} + +This function is provided to simplify using the +\verb|define_spectrum| function by returning a template structure +describing the default plasma state. The user can modify the +fields of the structure before using it, or an array of such +structures, as an argument to the \verb|define_spectrum| function. + +The struct fields are defined as follows: +\begin{verbatim} + norm = [1.0e-14/(4\pi D^2)] \int n_e n_H dV + where D is the source distance [cm] +temperature = electron temperature (K) + density = electron density [cm^(-3)] +metal_abund = metal abundance relative to solar + elem_abund = (optional) array of elemental abundances relative to solar + elem = (optional) list of element proton numbers; + size must match the elem_abund array + vturb = turbulent velocity component [km/s] + redshift = the redshift +\end{verbatim} +To define the elemental abundances, the value of +\verb|metal_abund| is first applied to all of the elements +heavier than helium. If present, the abundances in the +\verb|elem_abund| array are assigned to the corresponding +element listed in the \verb|elem| array. + +For example: +\begin{verbatim} +isis> s=default_plasma_state(); +isis> print(s); + norm = 1 + temperature = 1e+07 + density = 1 + metal_abund = 1 + elem_abund = NULL + elem = NULL + vturb = 0 + redshift = 0 +isis> +\end{verbatim} + +\end{isisfunction} + +\begin{isisfunction} +{define\_model} %name +{Define a theoretical spectrum model using \slang\ arrays} %purpose +{define\_model (state[]);} %usage +{default\_plasma\_state, model\_spectrum, append\_model, mt\_def\_model, create\_aped\_fun} + +{\it This interface is obsolete and is no longer supported. +A much more versatile interface is provided by +\verb|create_aped_fun|.} + +Analogous to \verb|load_model|, this function defines a +multi-component spectrum model using parameters stored in +an array of \slang\ structures, \verb|state[]|. + +See \verb|default_plasma_state| for the structure field +definitions. + +For example: +\begin{verbatim} + % Choose the grid to match a data set + d = get_data_counts (1); + + % Use the default plasma state except with + % a different temperature, and metal abundance + % [and with enhanced neon and low iron abundances] + s = default_plasma_state (); + + s.metal_abund = 0.7; + s.temperature = 2.4e7; + s.elem = [Fe, Ne]; + s.elem_abund = [0.1, 3.0]; + + define_model (s); + flux = model_spectrum (d.bin_lo, d.bin_hi); +\end{verbatim} +\end{isisfunction} + +\begin{isisfunction} +{edit\_model} %name +{edit current model parameters} %purpose +{edit\_model (["filename"]);} %usage +{load\_model} + +{\it This interface is obsolete and is no longer supported. +A much more versatile interface is provided by +\verb|create_aped_fun|.} + +This function uses a text editor to simplify entering and modifying +parameters of a multi-component spectral model. If no model is +currently specified, it starts the text editor with a blank form +containing only a header to indicate the parameter columns (see {\tt +load\_model} for a detailed description of the input format). If a +model is already specified, the model parameters are presented for +editing in the format described. + +As long as the specified format is adhered to, model components may be +added or removed by adding and deleting lines in the parameter file. + +The text editor specified by the {\sc EDITOR} environment variable; if +the environment variable is not set, {\tt vi} is used. When using {\tt +emacs}, the {\tt emacsclient} feature (of {\tt emacs}) can be used to +avoid invoking a new {\tt emacs} process for each edit. + +If a filename is specified, the model is saved in that file, +otherwise, a temporary file is generated and is deleted when editing +is finished. If the {\sc TMPDIR} environment variable is set, the +temporary file created for editing will be placed in the indicated +directory. Otherwise, the temporary file will be placed in the +current directory. +\end{isisfunction} + +\begin{isisfunction} +{list\_model} %name +{list parameters defining the current spectral model} %purpose +{list\_model} %usage +{edit\_model, save\_model, load\_model, mt\_list\_model} + +{\it This interface is obsolete and is no longer supported. +A much more versatile interface is provided by +\verb|create_aped_fun|.} + +This function lists the parameters defining the current spectral +model using the format described in {\tt load\_model}. +\end{isisfunction} + +\begin{isisfunction} +{load\_line\_profile\_function} %name +{load a user-defined line profile function} %purpose +{Line\_Profile\_Type = load\_line\_profile\_function ("library.so", "name")} %usage +{create\_aped\_line\_profile} +\index{User-defined!line profile function} + +Here is an example implementation of a user-defined line profile +function that provides a square line profile: +\begin{verbatim} +#include +#include + +#include "isis.h" + +/* gcc -shared -fPIC -o example-profile.so example-profile.c */ + +ISIS_LINE_PROFILE_MODULE(square,g,flux,wl,atomic_weight,mid, + params,num_params,options) +{ + double width, lo_edge, hi_edge, frac, xl, xh; + double *lo, *hi, *val; + int i, n; + + (void) atomic_weight; (void) num_params; (void) options; + + /* params[0] = \Delta\lambda/\lambda */ + width = params[0] * wl; + if (width <= 0.0) + return 0; + + lo_edge = wl - 0.5*width; + hi_edge = wl + 0.5*width; + + lo = g->bin_lo; + hi = g->bin_hi; + val = g->val; + n = g->nbins; + +#define INCREMENT_BIN(i) do { \ + if ((hi_edge < lo[i]) || (hi[i] < lo_edge)) \ + break; \ + xl = (lo_edge < lo[i] ) ? lo[i] : lo_edge; \ + xh = ( hi[i] < hi_edge) ? hi[i] : hi_edge; \ + frac = (xh - xl) / width; \ + val[i] += flux * frac; } while (0) + + for (i = mid; i >= 0; i--) + { + INCREMENT_BIN(i); + } + + for (i = mid+1; i < n; i++) + { + INCREMENT_BIN(i); + } + + return 0; +} +\end{verbatim} + +The \verb|ISIS_LINE_PROFILE_MODULE| macro is used both to +ensure that the correct interface is implemented and to +provide a way for isis to check interface compatibility at +run-time. + +\end{isisfunction} + +\begin{isisfunction} +{load\_model} %name +{load model parameters from a file} %purpose +{load\_model ("file");} %usage +{edit\_model, save\_model, define\_model, mt\_def\_model, mt\_load\_model} + +{\it This interface is obsolete and is no longer supported. +A much more versatile interface is provided by +\verb|create_aped_fun|.} + +For a collisional ionization equilibrium plasma, the file has +this format (numerical values given here are for illustration only): +\begin{verbatim} + # id Temp Density Abund Norm Vturb redshift + # (K) (cm^-3) (km/s) + 1 2.e6 1.e-3 1.0 1.0 200.0 0.0 + # + # abundances for component 1: + Si = 0.8 Na = 0.9 Fe = 0.3 + # + 2 3.e6 1.e00 0.4 1.5 150.0 0.0 + # + # abundances for component 2: + Si = 0.8 S = 0.9 Ca = 2.1 + # + 3 4.e6 1.e12 1.0 1.5 150.0 0.0 +\end{verbatim} +where +\begin{verbatim} + Temp = electron temperature [K] + Density = electron density [cm^(-3)] + Abund = metal abundance relative to solar + Norm = [10^(-14)/(4\pi D^2)] \int n_e n_H dV + where D is the source distance [cm] + Vturb = turbulent velocity component [km/s] +redshift = the redshift +\end{verbatim} +Lines with a \# symbol in column 1 are ignored and may be used +for comments. For a more precise definition of {\tt Vturb}, +see {\tt use\_thermal\_profile}. + +For each model component, any elemental abundances which differ from the +value given in the {\tt Abund} column may be listed separately on lines +immediately following the line defining the temperature and density. +Individual elements are specified using their 2 character chemical +abbreviation; unrecognized abbreviations are ignored. For example, to set +the Iron abundance to 0.25 and all the other elements to 0.6, specify {\tt +Abund = 0.6} with {\tt Fe = 0.25} on the following input line. +\end{isisfunction} + +\begin{isisfunction} +{model\_spectrum} %name +{generate a theoretical spectrum model on a given wavelength grid} %purpose +{flux = model\_spectrum (binlo, binhi [, contrib\_flag [, line\_list]]);} %usage +{load\_model, edit\_model, linear\_grid, use\_thermal\_profile, create\_aped\_fun, mt\_calc\_model} + +% DONT DELETE THIS DOCUMENTATION +{\it This interface is obsolete and is no longer supported. +A much more versatile interface is provided by +\verb|create_aped_fun|.} + +If present, the \verb|contrib_flag| argument may have one of +the following values: +\begin{verbatim} + ___Value________________Meaning________________________ + MODEL_LINES_AND_CONTINUUM model includes lines and continuum + MODEL_LINES model includes line emission only + MODEL_CONTIN model includes continuum emission only + MODEL_CONTIN_PSEUDO model includes pseudo-continuum only + MODEL_CONTIN_TRUE model includes true continuum only +\end{verbatim} + +If a \verb|line_list| is specified the computed spectrum +includes line emission only from the specified lines. + +The model spectrum is generated by loading emissivity data from the +spectroscopy database, interpolating to the temperature-density +grid specified by the model (see {\tt load\_model} and {\tt +edit\_model}) and computing the emission-measure weighted sum. +More precisely, each bin $[\lambda_{\rm lo}, \lambda_{\rm hi})$ +in the result has flux + +\begin{eqnarray} +F(\lambda_{\rm lo}, \lambda_{\rm hi}) &=& +\sum_m N_m \sum_Z X_m(Z) \sum_{q=0}^{Z-1} X_m(Z,q; T_m, n_m) \times\nonumber\\ +& & \sum_k^{N(Z,q)} +\varepsilon_{Zqk}(\lambda_{\rm lo}, \lambda_{\rm hi}; T_m, n_m, z_m) +~{\rm photon}\ {\rm cm}^{-2} {\rm s}^{-1} +\end{eqnarray} + +where + +\begin{equation} +\varepsilon_{Zqk}(\lambda_{\rm lo}, \lambda_{\rm hi}; T, n, z) = +\varepsilon_{Zqk}(T,n) \int_{\lambda_{\rm lo}}^{\lambda_{\rm hi}} +\D\lambda~ +\phi(\lambda - (1 + z)\lambda_{Zqk}). +\end{equation} + +In the expression for the flux in each bin, we have summed over model +components $m$, each with normalization $N_m = \int n_e n_H~\D V /(4\pi D^2)$, +temperature $T_m$, density $n_m$, redshift $z_m$, elemental abundances +$X_m(Z)$ and ionization balance fraction $X_m(Z,q; T_m, n_m)$. Each ion $q$ +of element $Z$ has $N(Z,q)$ emission lines $\lambda_{Zqk}$. The +contribution of each emission line to a given spectral bin is determined by +integrating the appropriate (Doppler shifted) line profile function +$\phi(\lambda)$ over the width of the specified bin. The emissivity values +$\varepsilon_{Zqk}(T,n)$ are computed by interpolating the emissivities +contained in the spectroscopy database files. + +To save the computed spectrum to a file, +\begin{verbatim} + flux = model_spectrum (lo, hi); + writecol ("spectrum.out", lo, hi, flux); +\end{verbatim} +\end{isisfunction} + +\begin{isisfunction} +{mt\_calc\_model} %name +{Compute the spectrum for a given {\tt Model\_Type}} %purpose +{emis[] = mt\_calc\_model (Model\_Type, lo, hi[, contrib\_flag [,line\_list]])} %usage +{mt\_def\_model, mt\_list\_model,mt\_load\_model, mt\_save\_model,create\_aped\_fun} +This function is almost identical to \verb|model_spectrum| except +that the model is specified by a \verb|Model_Type| instance +instead of the internal model component table. + +See \verb|model_spectrum| for details. +\end{isisfunction} + +\begin{isisfunction} +{mt\_create\_from\_struct} %name +{Create a {\tt Model\_Type} object from an appropriate {\tt Struct\_Type}} %purpose +{Model\_Type= mt\_create\_from\_struct (Struct\_Type)} %usage +{mt\_def\_model, mt\_list\_model,mt\_load\_model, mt\_save\_model, create\_aped\_fun} + +This function is similar to \verb|mt_def_model| except that it +works with a single structure whose fields are arrays. + +\end{isisfunction} + +\begin{isisfunction} +{mt\_def\_model} %name +{Define a {\tt Model\_Type} using an array of structures} %purpose +{Model\_Type = mt\_def\_model (Struct\_Type[])} %usage +{mt\_create\_from\_struct, mt\_calc\_model, mt\_list\_model,mt\_load\_model, mt\_save\_model,create\_aped\_fun} + +This function is almost identical to \verb|define_model| except +that the model definition creates a \verb|Model_Type| instance +instead of being stored in the internal model component table. + +See \verb|define_model| for details. +\end{isisfunction} + +\begin{isisfunction} +{mt\_list\_model} %name +{List components of a {\tt Model\_Type}} %purpose +{mt\_list\_model (Model\_Type)} %usage +{mt\_calc\_model, mt\_def\_model, mt\_load\_model, mt\_save\_model,create\_aped\_fun} + +This function is almost identical to \verb|list_model| except +that the model is specified by a \verb|Model_Type| instance +instead of the internal model component table. + +See \verb|list_model| for details. +\end{isisfunction} + +\begin{isisfunction} +{mt\_load\_model} %name +{Load an ASCII model file into a {\tt Model\_Type}} %purpose +{Model\_Type = mt\_load\_model (file)} %usage +{mt\_calc\_model, mt\_def\_model, mt\_list\_model, mt\_save\_model, create\_aped\_fun} + +This function is almost identical to \verb|load_model| except +that the model is loaded into a \verb|Model_Type| instance +instead of the internal model component table. + +See \verb|load_model| for details. +\end{isisfunction} + +\begin{isisfunction} +{mt\_save\_model} %name +{Save a {\tt Model\_Type} in an ASCII model file} %purpose +{mt\_save\_model (Model\_Type, file)} %usage +{mt\_calc\_model, mt\_def\_model, mt\_list\_model, mt\_load\_model, create\_aped\_fun} + +This function is almost identical to \verb|save_model| except +that the model is specified by a \verb|Model_Type| instance +instead of the internal model component table. + +See \verb|save_model| for details. +\end{isisfunction} + +\begin{isisfunction} +{save\_model} %name +{save model parameters to a file} %purpose +{save\_model ("file");} %usage +{load\_model, mt\_save\_model} + +{\it This interface is obsolete and is no longer supported. +A much more versatile interface is provided by +\verb|create_aped_fun|.} + +The model is saved in an ASCII file using the format described in +{\tt load\_model}. +\end{isisfunction} + +\begin{isisfunction} +{use\_delta\_profile} %name +{Use a delta-function line profile shape in the theoretical spectrum} %purpose +{use\_delta\_profile} %usage +{use\_thermal\_profile, create\_aped\_fun} + +When a delta-function line profile shape is specified, all of the flux +from a spectral line centered at wavelength $\lambda_0$ is added to +the single spectral bin $k$ which contains $\lambda_0$ ($\lambda_{\rm +lo}^k \le \lambda_0 < \lambda_{\rm hi}^k$). + +\end{isisfunction} + +\begin{isisfunction} +{use\_thermal\_profile} %name +{Use a thermal line profile shape in the theoretical spectrum} %purpose +{use\_thermal\_profile} %usage +{use\_delta\_profile, create\_aped\_fun} +When a thermal line profile shape is specified, the contribution +to each spectral bin $[\lambda_{\rm lo}, \lambda_{\rm hi})$ from +a spectral line with intensity $I_0$ centered at wavelength +$\lambda_0$ is +\begin{equation} +{\rm I}(\lambda_{\rm lo},\lambda_{\rm hi}) = {I_0 \over \sigma \sqrt{2\pi}} + \int_{\lambda_{\rm lo}}^{\lambda_{\rm hi}} \D\lambda~ + \exp\left[- { (\lambda-\lambda_0)^2 \over 2 \sigma^2} \right] +\end{equation} +where +\begin{equation} +\sigma \equiv {\lambda_0 \over c} \left( {1 \over 2}v_{\rm turb}^2 + {kT \over +m(Z)}\right)^{1/2} +\end{equation} +$T$ is the temperature and $m(Z)$ is the atomic mass of the emitting +ion (which has proton number $Z$). $v_{\rm turb}$ is the RMS turbulent +velocity width in the emitting plasma. +\end{isisfunction} + +\newpage +\section{Generic Plot Functions} +\label{sec:plot-functions} + +\isisx provides common plotting functionality through intrinsic functions +which try to relieve some of the burden of selecting plot ranges, +colors, axis labeling, etc. These intrinsic functions also provide +access to most selected plot customization features (colors, etc.) +with additional support to track details of multiple plots which may +be open simultaneously. + +A plot device can be opened using {\tt open\_plot}, {\tt +rplot\_counts}, {\tt +multiplot} or one of the other {\tt *plot*} functions such as {\tt +plot\_data\_counts} or {\tt hplot}. Several plot devices are supported +(see the \pgplot\ documentation for details). The default plot +device may be specified using either the {\sc PGPLOT\_DEV} +environment variable or the {\tt plot\_device()} function. If no +default plot device is specified, the user will be prompted to +select a device. Note that some plot devices have limited +functionality; some devices do not support color, others do not +support selective erasure of sub-regions of the plot window, etc. +See the \pgplot\ documentation for information on the supported +plot devices and their capabilities. + +\isisx supports use of multiple, simultaneous plot windows and devices and +multiple panes per plot window. If a plot window contains +multiple panes, the plot focus automatically moves to the next +pane each time a new plot is created. Each plot window maintains +its own format parameters, initialized using generic default +values {\it once} when the plot device is opened. These format +parameters and some of the commands used to set them are: + +\begin{verbatim} +______Function(s)__________________Purpose____________ + [xy]range, limits Set axis ranges + xlin, xlog Set axis type (log or linear) + label Set axis labels + title Set plot title + color, set_data_color Set plot line color + linestyle Set line style (solid, dashed, etc) + pointstyle Set point style (dot, circle, etc) + connect_points Set point connect style + (points only or points + line) + plot_unit Select histogram plot x-axis units + errorbars Toggle plotting of histogram errorbars + plot_bin_density, Select histogram plot type + plot_bin_integral +\end{verbatim} + +{\it All format parameter values are retained for the life of +the associated plot window.} + +Axis ranges in a given plot default to display the full range +of the first data set plotted. Axis ranges may be set explicitly +using the {\tt xrange} and {\tt yrange} functions; the {\tt +limits} command forces the next plot to display the full range of +the data. + +The size and shape of the plot can be controlled either by using using +the {\tt resize} function or, in X-windows, by interactively resizing +the plot window as you would any other window. Plot annotations are +set using {\tt xylabel}. Plot text appears in Roman font by default. +Within a text string, the font can be changed (temporarily) by using +the escape sequences $\backslash${\tt fn} (``normal''), +$\backslash${\tt fr} (roman), $\backslash${\tt fi} (italic), and +$\backslash${\tt fs} (script). Additionally, plot annotations +may be written in a convenient \LaTeX-style format (see +\verb|latex2pg|) + +Histogram data from the internal list of data-sets is plotted +using the functions {\tt [o]plot\_data\_*} and {\tt +[o]plot\_model\_*} described in \S\ref{sec:highres} (see also +\verb|rplot_counts|). By default, over-plots automatically change the +color or line-style. The user can over-ride this feature by +specifying the plot style explicitly or by disabling the feature +using {\tt plot\_auto\_color}. Data-sets can be plotted with or +without errorbars (see {\tt errorbars}. {\tt [o]hplot} provides +an alternate interface for plotting histograms defined by a set of +\slang\ variables. + +Arrays of points may be plotted with or without connecting lines and +with or without different symbols for individual data points (see {\tt +[o]plot} and {\tt connect\_points}). Images may be plotted using +\verb|plot_image|. + +For low-level plotting functionality not otherwise provided by +\isisx intrinsics, direct interactive access to most of the \pgplot\ +subroutine library is available (see \S\ref{chap:pgplot-module}). + +The default plot format may be controlled by modifying fields +of the intrinsic structure {\tt \_isis\_plot} defined in +Table \ref{defaultplot-tbl}: +\index{Plot!changing default format} +\index{changing default plot format} +\index{\_isis\_plot@{\tt \_isis\_plot}} +\begin{table}[ht] \caption{\isisx Default Plot Format} +\label{defaultplot-tbl} +\begin{tabular}{|l|c|p{3in}|} +\hline +Field Name & Default Value & Definition \\ +\hline + x\_unit & {\sc U\_ANGSTROM} & Energy or wavelength unit used for plotting spectra; + supported values are {\sc U\_ANGSTROM}, {\sc U\_NANOMETER}, + {\sc U\_KEV}, {\sc U\_EV}, {\sc U\_HZ} \\ + use\_bin\_density & 0 & (boolean) 0/1 means spectra are plotted + as bin-integral/bin-density values \\ + use\_errorbars & 0 & 0 means errorbars off, N means plot every Nth errorbar\\ + logx/logy & 0 & (boolean) 0/1 means linear/log axis \\ + pointstyle & -1 & pointstyle; see {\tt pointstyle()} \\ + linestyle & 1 & line style; see {\tt linestyle()} \\ + color & 1 & line color; see {\tt color()} \\ + char\_height & 1 & character height \\ + ebar\_term\_length & 0 & length of errorbar terminals \\ + \hline +\end{tabular} +\end{table} +For example, to change the plot defaults to have spectra plotted as +bin-density values in keV energy units, add the lines +\begin{verbatim} + _isis_plot.use_bin_density = 1; + _isis_plot.x_unit = U_KEV; +\end{verbatim} +to your \verb|.isisrc| file so that your selected plot format defaults +will be automatically applied when \isisx starts. + +\begin{isisfunction} +{charsize} %name +{change the character size used in plot labels} %purpose +{charsize (size)} %usage +{color, label, xylabel} +\index{Plot!character size} +{\tt size} is the normalized character height (1.0 is the default). + +Because of an apparent bug in the PGPLOT library, setting +the character size to a value significantly larger than 1.0 +may cause the plot axis labels to fall off the edge of the plot. +To workaround this bug, adjust the plot viewport to create +wider plot borders: +\begin{verbatim} + % The plot device should be open before the viewport + % size is changed + () = open_plot (device); + + % Make the viewport somewhat smaller than the default + % The numbers give xmin, xmax, ymin, ymax in normalized + % device coordinates which range from 0-1. + variable v = get_outer_viewport(); + v.xmin = 0.2; + v.xmax = 0.8; + v.ymin = 0.2; + v.ymax = 0.8; + set_outer_viewport(v); + + % Now create a plot using larger characters: + charsize(2); + plot_data_counts(1); +\end{verbatim} +\end{isisfunction} + +\begin{isisfunction} +{close\_plot} %name +{Close a plot window} %purpose +{close\_plot[(window\_id)]} %usage +{open\_plot, window} +The window index is the value returned when a new plot device is opened with +{\tt open\_plot}; also, in X-windows, each window frame is normally labeled +with the window index. If window\_id is absent, the currently active plot +window is closed. Note that when generating a Postscript file, the output +file must be explicitly closed in order to generate output, otherwise +an empty file may be generated. +\end{isisfunction} + +\begin{isisfunction} +{color} %name +{change the plot color} %purpose +{color (color\_index)} %usage +{line\_or\_color} +\index{Plot!colors} +With the default 16-color configuration of \pgplot, the color indices +correspond to {\tt red=2, green=3, blue=4, light\_blue=5, purple=6, +yellow=7, orange=8, grey=15}. This mapping may be redefined using functions +in the supplied \pgplot\ module; see the \pgplot\ documentation for further +details. +\end{isisfunction} + +\begin{isisfunction} +{connect\_points} %name +{Specify whether or not data points are connected by a line} %purpose +{connect\_points (flag)} %usage +{pointstyle, linestyle} + +By default, data points are connected by a line ({\tt flag} = 1; set {\tt +flag} = 0 to omit the connecting line; set {\tt flag} = -1 to +omit the points and draw the line only. The default is a solid line; an +alternate line style may be selected using {\tt linestyle}. +\end{isisfunction} + +\begin{isisfunction} +{cursor} %name +{read plot coordinates from the cursor} %purpose +{cursor( [ \&x, \&y [, \&ch]])} %usage +{xylabel} +With no arguments present, the cursor coordinates are +printed to the screen each time the mouse cursor +is clicked in the plot window. Press 'q' to quit. + +The cursor movement keys may be used for finer positioning control. + +The coordinates of the first mouse click or keypress and may also be +returned in variables specified as function arguments. Because the +{\it addresses} of the variables x,y and ch are used, it is necessary +to declare the variables before using them with the {\tt cursor} +function, even in interactive mode. + +Caveat: {\it This function does not work as expected if the plot window is +divided into sub-panes.} + +\begin{verbatim} + + cursor; % print cursor coordinates on each mouse-click + + variable x, y, ch; % declare variables; + cursor (&x, &y); % assign x, y the coordinates of + % each mouse-click. +\end{verbatim} +\end{isisfunction} + +\begin{isisfunction} +{cursor\_box} %name +{read corners of a box from plot cursor} %purpose +{(xmin, xmax, ymin, ymax) = cursor\_box ();} %usage +{cursor} +This function prompts the user to draw a box with the mouse cursor in a +currently open plot window. The box is be oriented so that its sides are +parallel to the edges of the plot window. The x-y coordinates of the box +corners are returned. +\end{isisfunction} + +\begin{isisfunction} +{dup\_plot} %name +{open a new plot device using parameters copied from an existing plot} %purpose +{new\_id = dup\_plot (["device" [,window\_id]])} %usage +{open\_plot, window} +This function initializes a new plot device with formatting parameters taken +from an existing plot (e.g. number of plot panes, axis ranges, character size, +line style, etc.). If no plot device is specified, a default device is used +or prompted for (see {\tt open\_plot} for details). If no plot window is +specified ({\tt window\_id}) , the parameters of the current plot device are +duplicated. This is sometimes useful in generating a hardcopy version of a +screen plot which required extensive formatting. +\end{isisfunction} + +\begin{isisfunction} +{erase} %name +{erase a plot window} %purpose +{erase[(window\_id)]} %usage +{open\_plot, window} +\index{clear@{\tt clear}} +\index{clear the plot window|see{{\tt erase}}} +\index{Plot!clear the plot window} +\index{Plot!erase the plot window} +This function is also aliased to {\tt clear}. +The plot window to erase is specified by giving the integer index of the +plot window. The window index is the value returned when a new plot device +is opened with {\tt open\_plot}; also, in X-windows, each window frame is +normally labeled with the window index. If window\_id is absent, the active +pane of the currently active plot window is erased. If the current device +does not support selective erasure of a sub-pane, the entire window will +be erased (probably - it depends on the device). +\end{isisfunction} + +\begin{isisfunction} +{errorbars} %name +{Specify the plotting of histogram errorbars} %purpose +{errorbars (N [,length])} %usage +{plot\_data\_counts} +Error bars are not plotted by default ({\tt N} = 0); +to plot every Nth errorbar, set \verb|N > 0|. +The optional second argument controls the length of errorbar +terminals. The default is 0.0 (no terminals); a value +of \verb|length=1.0| gives reasonably sized terminal bars. +Currently, error bars are available only on histogram plots; +the \pgplot\ module functions may be used to get error bars +on other kinds of plots. +\end{isisfunction} + +\begin{isisfunction} +{get\_outer\_viewport} %name +{Get current viewport location} %purpose +{Struct\_Type = get\_outer\_viewport ()} %usage +{set\_outer\_viewport, multiplot} + +Use this function to get the current location of the +outer viewport in normalized device coordinates. +See \verb|set_outer_viewport| for details. + +\end{isisfunction} + +\begin{isisfunction} +{get\_plot\_info} %name +{Get information about the current plot format} %purpose +{Struct\_Type = get\_plot\_info ()} %usage +{plot\_open, plot\_close, get\_plot\_options, set\_plot\_options} + +This function returns a structure of the form +\begin{verbatim} + variable p = struct + { + xmin, xmax, xlog, + ymin, ymax, ylog, + line_width, + line_color + }; +\end{verbatim} +which provides the current plot limits (\verb|xmin, xmax|, +\verb|ymin, ymax|) and the current line width and line color. +The boolean values \verb|xlog| and \verb|ylog| are non-zero +if the corresponding axis is log-scale. + +If no plot device is open, the function returns NULL. +\end{isisfunction} + +\begin{isisfunction} +{get\_plot\_options} %name +{Get information about the current plot format} %purpose +{Struct\_Type = get\_plot\_options ()} %usage +{plot\_open, plot\_close, get\_plot\_info, set\_plot\_options} + +Most plot options that are used internally by isis are returned +as fields of a structure. + +\begin{verbatim} +isis> p = get_plot_options; +isis> print(p); + xmin = -3.40282e+38 % axis ranges + xmax = 3.40282e+38 + ymin = -3.40282e+38 + ymax = 3.40282e+38 + xlabel = % axis labels + ylabel = + tlabel = % title + xopt = BCNST % axis label styles + yopt = BCNST + logx = 0 % boolean + logy = 0 + color = 1 + line_style = 1 + line_width = 1 + frame_line_width = 1 + point_style = -1 + connect_points = 1 % boolean + char_height = 1 + point_size = 1 + ebar_term_length = 0 % length of error-bar terminator + use_errorbars = 0 % boolean + use_bin_density = 0 % boolean +\end{verbatim} + +\end{isisfunction} + +\begin{isisfunction} +{hplot} %name +{[o]plot a histogram defined by \slang\ arrays} %purpose +{[o]hplot (Struct\_Type | binlo, binhi, value [,line\_style])} %usage +{plot, plot\_data\_counts, window} +\index{ohplot@{\tt ohplot}} +\index{Plot!of arrays} +This function plots or over-plots a histogram described by +three 1-D \slang\ arrays of size N. +\begin{verbatim} +Example: + edit_model; % specify spectrum model parameters + + (lo, hi) = linear_grid (1.0, 20.0, 6000); % generate a grid + flux = model_spectrum (lo, hi); % compute bin values + + hplot (lo,hi,flux); % plot +\end{verbatim} + +When a single \verb|Struct_Type| argument is given, it should +have fields \verb|bin_lo|, \verb|bin_hi|, \verb|value|. +For example: +\begin{verbatim} + d = get_data_counts (1); + hplot (d); +\end{verbatim} + +\end{isisfunction} + +\begin{isisfunction} +{label} %name +{label plot axes} %purpose +{label ("xlabel", "ylabel", "title")} %usage +{xlabel, ylabel, title, xylabel, latex2pg} +\index{Plot!axis labels} +Specifies text strings to be used for the plot title and axis labels. +To add a plot title only, use {\tt title}. +\end{isisfunction} + +\begin{isisfunction} +{latex2pg} %name +{Translate strings from \LaTeX format to PGPLOT format} %purpose +{String\_Type = latex2pg (String\_Type)} %usage +{xylabel, xlabel, ylabel, title, label} +\index{Plot!\LaTeX strings} + +This function simplifies creating plot annotations which contain +Greek symbols, superscripts and subscripts. It translates strings +written in a convenient \LaTeX-style format into a format which is +understood by PGPLOT. For example: +\begin{verbatim} + ____LaTeX_format_____ ____PGPLOT_format____ + 1.24 \\x 10^{-14} 1.24 \x 10\u-14\d + \\A^{-1} \A\u-1\d + 2s~^2S_{1/2} 2s \u2\dS\d1/2\u + e^{i\\pi} + 1 = 0 e\ui\gp\d + 1 = 0 +\end{verbatim} +Note that two backslash `\verb|\|' symbols must be used to denote +font changes, Greek symbols and other special symbols. +\end{isisfunction} + +\begin{isisfunction} +{limits} %name +{Use the plot data to determine axis limits for the next plot} %purpose +{limits} %usage +{xrange, yrange} +\index{Plot!axis ranges} +This function re-sets the current pane of the current plot window so that +the XY ranges of the next plot will cover the full-range of data. This +function is equivalent to {\tt xrange; yrange;} +\end{isisfunction} + +\begin{isisfunction} +{line\_or\_color} %name +{control interpretation of line style indices} %purpose +{line\_or\_color (choice)} %usage +{color, linestyle} + +If {\tt choice =0}, line style indices indicate line {\it type} (e.g. solid, +dashed, dotted, etc.). If {\tt choice !=0}, line style indices indicate line +{\it color} (this is the default). +\end{isisfunction} + +\begin{isisfunction} +{linestyle} %name +{change the plot linestyle} %purpose +{linestyle (linestyle\_index)} %usage +{line\_or\_color} +\index{Plot!line style} +The available line-style indices are (1) full line, (2) dashed, +(3) dot-dash, (4) dotted, (5) dash-dot-dot-dot. +See the \pgplot\ documentation for more information. +\end{isisfunction} + +\begin{isisfunction} +{multiplot} %name +{Subdivide the current plot-device window into horizontal panes} %purpose +{multiplot (relative\_sizes)} %usage +{open\_plot, mpane, window} +\index{Plot!subwindows} +This function supports subdividing a plot window into horizontal +panes which share a common X-axis. The argument to {\tt multiplot} +is an integer array which gives the relative sizes of the plot +panes in order, from top to bottom. + +Example: +\begin{verbatim} + multiplot ([3,1]); % top pane is 3x as wide as the bottom pane + multiplot (1); % Restore subdivided plot to a single pane. +\end{verbatim} +\end{isisfunction} + +\begin{isisfunction} +{mpane} %name +{Select a specific pane in a multiplot} %purpose +{mpane (pid)} %usage +{multiplot} +\index{Plot!subwindows} +This function selects a specific pane within a multiplot (a set +of plot panes sharing a common X-axis). + +Example: +\begin{verbatim} + x=[1:100]; + multiplot ([1,1,2]); % a 3-pane multiplot + plot(x,x); % plot in pane 1 (the top one) + plot(x,x); % plot in pane 2 + + mpane(1); % move back to the top pane + oplot(x,x^2); % over-plot in pane 1 + + mpane(3); % move to the bottom pane + plot(x,x); + oplot(x,x^2-x); + multiplot(1); % revert to a single pane format +\end{verbatim} +\end{isisfunction} + +\begin{isisfunction} +{open\_plot} %name +{open a new plot window} %purpose +{window\_id = open\_plot (["device" [, nxpanes, nypanes]])} %usage +{close\_plot, window, dup\_plot, plot, hplot, plot\_data, plot\_model, plot\_elev, multiplot} +\index{Plot!devices} +\index{Plot!postscript output} +\index{Plot!hardcopy} +\index{Plot!panes} + +The first argument specifies the name of plot device. If +device = "?" or is blank or absent, the user is prompted to +supply the device name. The default device is that specified +by the \verb|PGPLOT_DEV| environment variable; if that +environment variable is not set, the default device is +\verb|NULL|. See the description of the \pgplot\ command +\verb|pgopen| for full details on the device specification +string. + +The remaining two optional arguments (\verb|nxpanes|, +\verb|nypanes|) give the number of X and Y subdivisions for the +window. The return value gives the integer index of plot device +just opened. + +\vspace*{\baselineskip} +{\bf Postscript:~~}\\ A good way to generate postscript plots is to write a +\slang\ script using an {\tt open\_plot} command which specifies the output +postscript file name and the postscript device using the device string (see +the examples below). + +\vspace*{\baselineskip} +{\bf GIF and other formats:~~}\\ If the appropriate drivers are included +when \pgplot\ is installed, plots may be generated in a wide range of +formats. For example, to generate a GIF image, open the appropriate plot +device (e.g. {\tt open\_plot("plot.gif/gif")}), generate the plot as usual +and then close the plot device ({\tt close\_plot}). + +\vspace*{\baselineskip} +{\bf X-windows:~~}\\ +Under X-windows, the default initial size of the plot +window is controlled by the Xresource +\begin{verbatim} + pgxwin.Win.geometry. +\end{verbatim} +If \isisx is run on a machine with a small screen, the default +plot window size should probably be set to something smaller than the +\pgplot\ default size of $867\times 669$ pixels. Otherwise, when a plot +window is opened, it might fill the entire screen. To make the default +window half as large, insert the line +\begin{verbatim} + pgxwin.Win.geometry: 432x333 +\end{verbatim} +in \verb|~/.Xdefaults|, then use +\begin{verbatim} + xrdb ~/.Xdefaults +\end{verbatim} +to have the X window manager read the modified .Xdefaults file. It may also +be necessary to kill and re-start the existing pgxwin server (e.g. by +re-opening the plot window) before the geometry change will take effect. + +Another useful Xresource is {\tt pgxwin.Win.maxColors}. Because each plot +window reserves 100 colors, opening several plot windows may quickly exhaust +the available colors on the display, leading to color flashing or causing +the entire screen to turn black upon opening a plot window. This problem may +be alleviated by setting {\tt pgxwin.Win.maxColors} to a smaller value, e.g. +\index{color flashing} +\index{color flashing!black screen} +\begin{verbatim} + pgxwin.Win.maxColors: 16 +\end{verbatim} +See the \pgplot\ documentation for full details: +\begin{verbatim} + http://astro.caltech.edu/~tjp/pgplot/xwdriv.html +\end{verbatim} +If the display turns black because it ran out of colors, one can usually +recover by moving the mouse cursor to a different window and perhaps +clicking the mouse in that window (if the X-window configuration uses +click-to-focus). Another symptom of running out of colors is the notorious +color-flashing which occurs as the mouse cursor moves across window +boundaries. These problems are sometimes less severe with newer systems +that have larger color-spaces (e.g. 24 bit monitors). + +\begin{verbatim} +Examples: + +% a single pane X-window +() = open_plot; % assuming PGPLOT_DEV = "/xwin" + +% a color postscript plot with 2 panes in a file "myfile.ps" +() = open_plot("myfile.ps/cps",2,1); + +% a different style of plot with 2 sub-panes +% the top pane is 3X as wide as the bottom pane +() = open_plot ("/xw"); +multiplot ([3,1]) + +% A function like this can be used to simplify plotting +% data and residuals in the XSPEC style: +% [the ISIS function rplot_counts() does this] + +public define plot_count_residuals (h, dev) +{ + multiplot ([3,1]); + + errorbars (1); + plot_data_counts (h); + oplot_model_counts (h); + + errorbars (0); + yrange; + _rplot_counts(h); +} + +% e.g. To use this function to plot data set 1 in an X-window +% (see the figure) type + + isis> plot_count_residuals (1, "/xw"); + +\end{verbatim} +\end{isisfunction} + +\begin{figure}[ht] +\putfig{figures/residuals} +\caption{Example of plotting count data and fit-residuals.} +\label{fig:resid} +\end{figure} + +\begin{isisfunction} +{plot} %name +{[o]plot x-array vs. y-array} %purpose +{[o]plot (x, y, [line\_style | symbol\_array])} %usage +{open\_plot, window, pointstyle, connect\_points} +\index{oplot@{\tt oplot}} +\index{Plot!of arrays} + +Given two 1-D \slang\ arrays of size N, this function will plot +or over-plot x vs. y. The oplot function behaves like plot if +no plots have already been drawn. If the third argument is a +single integer, it is interpreted as the the line-style {\tt +see line\_or\_color}. If the third argument is an integer +array of length N, it is interpreted as a list of plot symbols, +one for each point. +\begin{verbatim} +% Example: plot the line y=x for 1 <= x <= 10, labeling the points +% with the lower case letters 'a' through 'j' + x = [1:10]; + y = x; + sym = ['a':'j']; % sym[0] = integer ASCII code for 'a', etc. + plot (x,y,sym); +\end{verbatim} +\end{isisfunction} + +\clearpage + +\begin{isisfunction} +{plot\_auto\_color} %name +{Control automatic line-color/line-style changes} %purpose +{plot\_auto\_color (flag)} %usage +{set\_data\_color, line\_or\_color} +If {\tt flag} is non-zero, overplots automatically change line color or line +style, cycling through the available colors or styles (this is the default). +If {\tt flag} is zero, color or style changes must be specified explicitly. +\end{isisfunction} + +\begin{isisfunction} +{plot\_bin\_density} %name +{Plot data values as a density in each bin} %purpose +{plot\_bin\_density} %usage +{plot\_bin\_integral} +This function alters the plotted values for histogram plots only. By default, +histograms are plotted as bin-integral quantities. This mode specifies that +the input data bin values should be divided by the bin width and +exposure time for plotting +(recall that the input data values are assumed to be bin-integral quantities) +\end{isisfunction} + +\begin{isisfunction} +{plot\_bin\_integral} %name +{Plot data values integrated over each bin width} %purpose +{plot\_bin\_integral} %usage +{plot\_bin\_density} +This function alters the plotted values for histogram plots only. +If the format type is not specified, it is assumed to be +bin-integral. Because the input data values are assumed to +be bin-integral quantities, this mode specifies that the input +data bin-values are to be plotted unchanged. +\end{isisfunction} + +\begin{isisfunction} +{plot\_contour} %name +{display image contours} %purpose +{plot\_contour (img[] [, aspect [,x[], y[] [, c[] ]]])} %usage +{plot\_image, histogram2d} +\index{Plot!contours} +The image is a 2D array, \verb|img[y,x]|. +When the optional argument, \verb|aspect|, is non-zero, +the image dimensions determine the aspect-ratio of the plot. +Otherwise, the plot fills the plot window and the image +may be distorted. +The optional 1D array arguments \verb|x,y| provide +the coordinate grid for the X,Y axes. The +remaining optional argument, \verb|c[]|, +provides the contour levels to be plotted. +\end{isisfunction} + +\begin{isisfunction} +{plot\_device} %name +{specify default plot device} %purpose +{plot\_device (device\_string)} %usage +{open\_plot, window} +\index{Plot!default plot device} + +This default over-rides the current value of the {\sc PGPLOT\_DEV} +environment variable; {\tt device\_string} can be any valid \pgplot\ device +string; the list of available devices is determined by the configuration of +the \pgplot\ installation. See the \pgplot\ documentation for details. +\end{isisfunction} + +\begin{isisfunction} +{plot\_image} %name +{display an image} %purpose +{plot\_image (img[][, aspect [,x[], y[] [, amin, amax]]])} %usage +{plot\_contour, histogram2d, set\_palette, plot\_image\_ctrl} +\index{Plot!image} +The image is a 2D array, \verb|img[y,x]|. +When the optional argument, \verb|aspect|, is non-zero, +the image dimensions determine the aspect-ratio of the plot. +Otherwise, the plot fills the plot window and the image +may be distorted. +The optional 1D array arguments \verb|x,y| provide +the coordinate grid for the X,Y axes. The +two remaining optional arguments, \verb|amin, amax|, +specify the range of array values to be mapped +onto the chosen color table. Use \verb|set_palette()| +to select from a set of predefined color tables; +\verb|plot_image_ctrl| supports interactive control +over the color table, brightness and contrast. +\end{isisfunction} + +\begin{isisfunction} +{plot\_image\_ctrl} %name +{Adjust image color table, brightness and contrast} %purpose +{plot\_image\_ctrl ()} %usage +{histogram2d, set\_palette, plot\_image} +\index{Plot!image brightness, contrast} +This function supports interactive control +over the color table, brightness and contrast +used to display an image on the current plot device. +\end{isisfunction} + +\begin{isisfunction} +{plot\_quit} %name +{close all plot windows} %purpose +{plot\_quit} %usage +{open\_plot, close\_plot, window} +This function closes all currently open plot devices +\end{isisfunction} + +\begin{isisfunction} +{plot\_unit} %name +{specify X-coordinate units for plotting data histograms} %purpose +{plot\_unit (x\_unit)} %usage +{plot\_data, plot\_bin\_density} + +The default X-coordinate units are {\AA}ngstrom units. Supported +alternatives are selected by specifying one of the following strings +(case-insensitive): +\begin{verbatim} + Angstrom, A, nm, mm, cm, m + eV, keV, MeV, GeV, TeV, + Hz, kHz, MHz, GHz +\end{verbatim} +Note that altering the X-coordinate of the plot will also +change the Y-values plotted if the Y-axis is in units of +bin-density (because those values are being divided by the +bin-width). If plotting bin-integral values, the Y-axis values +are independent of the X-coordinate. +\end{isisfunction} + +\begin{isisfunction} +{pointstyle} %name +{change the symbol used to plot data points} %purpose +{pointstyle (symbol)} %usage +{[o]plot} +\index{Plot!symbol} +\begin{verbatim} + -1,-2 a single dot + -3..-31 a regular polygon with abs(symbol) + edges (style set by current fill style) + 0..31 standard marker symbols + 32..127 ASCII characters (in current font) + >127 a Hershey symbol number +\end{verbatim} +For further details, including lists of the standard marker symbols and the +Hershey plot symbols, see the \pgplot\ documentation. Note that the ASCII +value of a character is easily obtained in \slang: +\begin{verbatim} + ch = 'b'; % set ch to the ASCII code for 'b' + sym = Integer_Type [length(array)]; % make a symbol array + sym[*] = 'Q'; % and set all symbols to 'Q' +\end{verbatim} +\end{isisfunction} + +\begin{isisfunction} +{resize} %name +{resize the plot window} %purpose +{resize[ ([width\_in\_cm], [aspect\_ratio])]} %usage +{open\_plot, window} + +The aspect\_ratio is defined as height/width. +aspect=1.000 gives a square plot\\ +aspect=0.618 gives a horizontal rectangle\\ +aspect=1.618 gives a vertical rectangle\\ + +If width=0.0, the window will assume the largest available view +surface consistent with the argument aspect\_ratio. If no +arguments are given, the result is equivalent to {\tt resize (0.0, 0.618)}. +Note that the resize takes effect only when something is plotted +in the specified window and not at the moment the resize function +is called. +\end{isisfunction} + +\begin{isisfunction} +{set\_frame\_line\_width} %name +{Set line width for plot axes and axis grid labels} %purpose +{set\_frame\_line\_width (width)} %usage +{set\_line\_width} +\index{Plot!line width (frame)} + +Use this function to set the line width used to +draw the plot axes, the tick-mark +labels, the axis labels and the plot title. +By default, \verb|width=1|. + +\end{isisfunction} + +\begin{isisfunction} +{set\_line\_width} %name +{Set line width} %purpose +{set\_line\_width (width)} %usage +{set\_frame\_line\_width} +\index{Plot!line width} + +Use this function to set the line width used to +plot points, curves and error-bars. +By default, \verb|width=1|. + +\end{isisfunction} + +\begin{isisfunction} +{set\_outer\_viewport} %name +{Set viewport location} %purpose +{set\_outer\_viewport (Struct\_Type v)} %usage +{get\_outer\_viewport, multiplot} + +Use this function to specify the outer viewport of the plot in +normalized device coordinates. The coordinates are specified +using a structure of the form +\begin{verbatim} + v = struct {xmin, xmax, ymin, ymax} +\end{verbatim} + +For a simple plot, the ``outer viewport'' has the same meaning +as the viewport discussed in the PGPLOT documentation for e.g. +PGSVP. For a multiplot containing several plot panels sharing +a common X-axis, the ``outer viewport'' is the outermost box +that contains all of the plot panels. + +\end{isisfunction} + +\begin{isisfunction} +{set\_palette} %name +{Select image color table} %purpose +{set\_palette (id)} %usage +{plot\_image, plot\_image\_ctrl} +\index{Plot!color table} + +Use this function to choose from five predefined color tables: +\begin{verbatim} + ___id______Color_Table___ + 1 grey scale + 2 rainbow + 3 heat + 4 iraf + 5 aips +\end{verbatim} + +\end{isisfunction} + +\begin{isisfunction} +{set\_plot\_options} %name +{Modify the current plot format} %purpose +{set\_plot\_options (Struct\_Type)} %usage +{plot\_open, plot\_close, get\_plot\_info, get\_plot\_options} + +\end{isisfunction} + +\begin{isisfunction} +{title} %name +{Set plot title} %purpose +{title ("title string")} %usage +{xlabel, ylabel, label, xylabel, latex2pg} +\index{Plot!title} + +Specifies a string to use as the plot title. To +simultaneously label both axes and provide a title use the {\tt label} +function. +\end{isisfunction} + +\begin{isisfunction} +{window} %name +{specify the active plot device} %purpose +{window (window\_id);} %usage +{open\_plot} +\index{Plot!windows} +Plotting commands refer to the active plot device. Use this function to +specify which device is active. This function is useful primarily during an +interactive session for switching between different plot windows within +X-windows. This functionality is not necessarily available with all plot +devices or all combinations of plot devices. +\end{isisfunction} + +\begin{isisfunction} +{xinterval} %name +{read endpoints of x-interval from plot cursor} %purpose +{(xmin, xmax) = xinterval ();} %usage +{cursor} + +\index{yinterval@{\tt yinterval}} +This function is useful for selecting X-intervals from a plot in interactive +mode. \verb|yinterval| is the analogous command for the y-axis. +\end{isisfunction} + +\begin{isisfunction} +{xlabel} %name +{Set plot x-axis label} %purpose +{xlabel ("string")} %usage +{ylabel, label, title, xylabel, latex2pg} +\index{ylabel@{\tt ylabel}} + +Specifies a string to use as the X-axis label. To simultaneously +label both axes and provide a title use the {\tt label} function. + +\end{isisfunction} + +\begin{isisfunction} +{xlin} %name +{Change the x-axis to linear scale} %purpose +{xlin} %usage +{xlog} +\index{Plot!axis scaling} +\index{ylin@{\tt ylin}} +{\tt ylin} is the analogous command for the y-axis +\end{isisfunction} + +\begin{isisfunction} +{xlog} %name +{Change the x-axis to log scale} %purpose +{xlog} %usage +{xlin} +\index{Plot!axis scaling} +\index{ylog@{\tt ylog}} + +{\tt ylog} is the analogous command for the y-axis +When log scale is specified for a given coordinate axis, points with +non-positive values of that coordinate are ignored when computing the full +range of the data. For example, consider a function defined on the set of x +coordinates [-5, -3, -2, 0, 2, 4, 5, 10, 15]. When plotted using a log +x-axis, the full range of data is considered to extend from log10(2) to +log10(15); the non-positive coordinate points are ignored. This command +affects the plot appearance only; it does {\it not} replace the internal +data values with their logarithms. +\end{isisfunction} + +\begin{isisfunction} +{xrange} %name +{set the X-axis plot limits for the next plot} %purpose +{xrange[ ([xmin], [xmax])]} %usage +{xlin, xlog} +\index{Plot!axis ranges} +\index{yrange@{\tt yrange}} + +If either argument is absent, the corresponding value will be +derived from the data when the next plot is generated. +\verb|yrange| is the analogous command for the Y-axis, except that +\verb|yrange| sets the Y-axis plot limits to the range of data +inside the current X-axis plot limits rather than the full range +of the entire data set. + +\end{isisfunction} + +\begin{isisfunction} +{xylabel} %name +{place a text label at an arbitrary x,y plot location} %purpose +{xylabel (x,y,label, [angle [,justify]])} %usage +{xlabel, ylabel, title, label, latex2pg, cursor} + +The optional \verb|angle| argument gives the rotation angle in degrees +CCW [default = 0.0]. The optional \verb|justify| argument +positions the text relative to the cursor location; +\verb|justify|=0.0 for text to the right of the cursor [default], +\verb|justify|=0.5 for text centered on cursor, +\verb|justify|=1.0 for text to the left of the cursor. + +In interactive mode, it may be helpful to read the +(x,y) coordinates with the mouse via the {\tt cursor} command. + +\begin{verbatim} +Example: + variable x,y; + cursor (&x, &y); + xylabel (x, y, "Fe XVII"); +\end{verbatim} + +A more general \slang\ script which uses the {\tt cursor} command to select +points and then writes appropriate {\tt xylabel()} commands to a file (with +explicit X-Y coordinates filled in) might greatly simplify some tedious plot +annotation tasks, such as labeling emission lines in an observed spectrum. +\end{isisfunction} + +\newpage +\section{Fitting Functions to Data} +\label{sec:fitting-data} + +To use high resolution spectral data to infer physical conditions +in an emitting plasma, measurements of the strength and shape of +observed features are often compared to theoretical predictions. +To facilitate measurement of the position, strength, size and +shape of spectral features, \isisx supports fitting models to +data. A few simple functions such as Gaussians and polynomials +are provided by \isisx and many others are available from the +\xspec\ module (\S\ref{chap:xspec-module}). \isisx also provides +the ability to automatically generate customized multi-component +spectral models using the spectroscopy database (see +\verb|create_aped_fun|). Multiple user-defined fit-functions are +also supported (see {\tt add\_compiled\_function}, {\tt +add\_slang\_function}). Furthermore, using the ISIS intrinsic +variable \verb|Isis_Active_Dataset|, one can write user-defined +functions which evaluate differently for different datasets. For +example, its possible to simulataneously fit a Gaussian to one +dataset and a Lorentzian to another. + +Models may be fit to either flux-corrected data or count-data. +Extending the standard forward-folding fit algorithm used in \xspec, +the \isisx implementation supports the treatment of some classes of +non-linear instrument response (such as event pileup -- see +\S\ref{sec:pileup}) and also supports application of a user-defined +photon redistribution function (RMF) implmemented in software (see +{\tt load\_rmf} and, for an example implementation, see +\verb|src/rmf_delta.c| in the \isisx distribution). + +The \isisx implementation of forward-folding ``solves'' equations +of the form +\begin{equation} + C(h) = B(h) + t \int \D E~{\cal F}\Bigl(R(h,E),\ A(E),\ s(E)\Bigr) +\label{eq:model-counts} +\end{equation} +where $C(h)$ is the number of counts obtained in detector-bin $h$, +$t$ is the effective exposure time, $E$ is the incident photon energy, and +$s(E)$ is the incident source flux at energy $E$. The instrument response +is represented by an effective-area function $A(E)$ (e.g. the ARF) +and a redistribution function $R(h, E)$ (e.g. the RMF). The +instrumental background in detector-bin $h$ is given by $B(h)$. + +All the functions on the right-hand side of equation +(\ref{eq:model-counts}) may be user-defined. In particular, the +function ${\cal F}$ may be user-defined; for brevity, we refer to +this function as the {\it kernel}, although this usage is somewhat +inconsistent with standard mathematical terminology. In the +standard implementation of forward-folding, +\begin{equation} + {\cal F}\left(R,\ A,\ s\right) = R(h,E)A(E)s(E). +\end{equation} +This is the form used in \xspec\ and is the default kernel used in +\isisx. When multiple responses are assigned to a single data set (using +{\tt assign\_rsp}), \isisx uses +\begin{equation} + {\cal F}\left(R,\ A,\ s\right) = \sum_i R_i(h,E)A_i(E)s(E), +\end{equation} +where the sum extends over all responses. This latter form is +suitable for analysis of HRC/LETGS data, where multiple dispersion +orders are summed together in the data, but where responses for +individual dispersion orders are available. This form is also +applicable to the analysis of CCD data where significant response +variation is present across the spectral extraction region (e.g. +for ACIS-I observations of extended sources); in this case, the +ARFs must be weighted according to the surface-brightness +distribution of the source. Davis (2001) showed that event pileup +in CCD detectors is a non-linear process which can be described by +a considerably more complex function ${\cal F}$. Davis's +implementation of this pileup kernel is available in \isisx and +may be accessed using the {\tt set\_kernel} and {\tt +print\_kernel} functions (see \S\ref{sec:pileup}). Similarly, +user-defined fit-kernels may be accessed using the {\tt +load\_kernel} function. + +{\tt ignore}, {\tt notice} and {\tt xnotice} are used to indicate +which data bins are to be included in the fit. {\tt ifit\_fun} or +{\tt fit\_fun} define and modify the form of the fit function. +{\tt list\_par} displays a list of current fit parameters. +Parameter values can be set using {\tt edit\_par}, {\tt set\_par} +or {\tt load\_par}; allowed ranges for each parameter value are +enforced during the fitting iteration. The {\tt renorm\_*} +functions simplify finding the initial parameter values by +automatically adjusting the normalization of the model. Parameters +may be fixed at known values or allowed to vary to improve the +model fit (see {\tt freeze, thaw}). Parameter values may also be +tied to together (see {\tt tie, untie}). Parameter values may even +be defined as functions of other parameters and, optionally, as +functions of user-defined functions (see \verb|set_par_fun|). + +The {\tt eval\_*} functions evaluate the model using the current +parameter set. Once the fit data is specified and the model and +initial parameter values are defined, the {\tt fit\_*} functions +compute the best fit model parameters and {\tt save\_par} saves +the parameter values to an ASCII file. {\tt [o]plot\_model} +displays plots of the best fit model. Single parameter confidence +limits can be computed using {\tt [v]conf}. + +{\tt get\_cfun} and {\tt get\_cfun2} evaluate the underlying +differential (unbinned) fit function at a specified set of +points; these values may then be plotted using {\tt [o]plot} +(See \S \ref{sec:plot-functions}). + +While the bin coordinates in the input data may use any of several +supported physical units, all fit parameters are defined using +Angstrom bin coordinates and {\it all internal calculations are +done in Angstrom bin coordinates}. Function values are +interpreted as the integral, over the bin width, of an underlying +``differential'' function. + +The intrinsic variable {\tt Fit\_Verbose} controls the amount of +information printed to the screen during the fit iterations. In +verbose mode ({\tt Fit\_Verbose} $>$ 0), the fit routine prints out +the values of the variable parameters at each iteration along with +the current $\chi^2$ value and convergence tolerance. In silent +mode ({\tt Fit\_Verbose} $<$ 0), only fatal error messages are +printed. The default verbose level is {\tt Fit\_Verbose}=0, but +this may be set in the {\tt \$HOME/.isisrc} configuration file. +\index{Fit\_Verbose@{\tt Fit\_Verbose}} + +By default, the instrumental response (RMF/ARF) is applied when fitting, if +these functions are available. + +Functions may be fitted to ``scatter data'' [randomly ordered +sets of (X,Y) pairs] using the \verb|array_fit| function. + +\begin{isisfunction} +{\_par} %name +{get the value of a fit parameter} %purpose +{par = \_par (idx)} %usage +{get\_par, set\_par, set\_par\_fun} + +This function is identical to \verb|get_par| but is normally +used only when defining fit-parameters as functions of other +parameters. +\end{isisfunction} + +\begin{isisfunction} +{add\_compiled\_function} +{Add a user-defined fit function} +{add\_compiled\_function (library\_name, function\_name [, option\_string])} +{del\_function, list\_functions, add\_slang\_function, set\_function\_category} +\index{User-defined!fit-function (compiled)} + +{\it Note: this function is available only on systems with ELF +support. } See the \verb|userfun| example from the \isisx web +page and the \verb|modules/xspec/src| directories in the \isisx +distribution for detailed examples of how to implement +user-defined fit functions in C; \slang\ fit-functions are also +supported (See {\tt add\_slang\_function}). An unlimited number +of user-defined functions are supported and fit functions may +have an unlimited number of parameters. + +The first argument, \verb|library_name|, gives the name of the +shared library file (.so). The section argument, +\verb|function_name|, gives the name of the subroutine that +evaluates the fit-function (string \verb|<31| characters). The +optional third argument, \verb|option_string|, is a string +which is passed to the user-module initialization routine. +To avoid future problems, +parameter names should avoid using \slang\ special characters. + +For example, suppose the user-defined fit-function is a power law ($f(x) = +Ax^p$) and is defined by a subroutine called {\tt plaw}, with parameters +{\tt norm} and {\tt power}). Further, suppose this subroutine is contained +in a dynamically linked library file called {\tt mylib.so}. + +The {\tt plaw} function may be accessed at run-time using +\begin{verbatim} + isis> add_compiled_function ("mylib.so", "plaw"); +\end{verbatim} +assuming that {\tt mylib.so} exists somewhere in the \isisx module search +path (see e.g. {\tt ISIS\_MODULE\_PATH}). + +For user-defined operator models implemented in C, the +\verb|Isis_User_Source_t| structure should be initialized with +the \verb|category| field set to \verb|ISIS_FUN_OPERATOR|. +\end{isisfunction} + +\begin{isisfunction} +{add\_slang\_function} +{Add a user-defined fit function} +{add\_slang\_function (name, par\_name\_array [, norm\_indexes])} +{del\_function, list\_functions, add\_compiled\_function, set\_function\_category, set\_param\_default\_hook} +\index{User-defined!fit-function (S-Lang)} +\index{Operator models!fit-function (S-Lang)} +\index{Convolution models!fit-function (S-Lang)} + +The first argument, \verb|name|, is the name that will be used +in the expression supplied to \verb|fit_fun|; it should be +\verb|<= 31| characters long. The corresponding \slang\ +function name must have a suffix `\verb|_fit|' appended. The +second argument, \verb|par_name_array|, is an array of strings, +each \verb|<= 31| characters in length, containing the function +parameter names. The optional third argument, +\verb|norm_indexes|, is an integer array specifying the +zero-based array indices of the parameters which should be +interpreted as normalization coefficients. Note that parameter +names should be valid \slang\ identifiers. + +Physical units for each fit parameter may be specified by +appending the units to the parameter name string, enclosed in +square brackets (``\verb|[]|''). For example, +\begin{verbatim} + add_slang_function ("foo", ["kT [keV]", "Mdot [Msun/yr]"]); +\end{verbatim} +defines a function of two parameters, \verb|kT| measured in +units of keV and \verb|Mdot| measured in units of solar masses +per year. + +Defining new fit-functions in \slang\ is simpler than in C but, +because the function evaluations are performed in an +interpreted language, the execution time may be noticeably +slower, depending on the implementation. Remember that, in the +interpreter, implicit array operations are {\it much} faster +than explicit loops over array indices. + +For example, suppose the user-defined fit-function is a power +law ($f(x) = ax^b$) and is defined by a \slang\ function called +{\tt plaw\_fit}, with adjustable parameters {\tt norm} = "$a$" += {\tt par[0]} and {\tt power} = "$b$" = {\tt par[1]}. The +\slang\ function "{\tt plaw\_fit}" which computes the +bin-values might look like this: +\begin{verbatim} +define plaw_fit (lo, hi, par) +{ + variable norm, p, result; + + norm = par[0]; + p = par[1] + 1; + result = norm * (hi^p - lo^p) / p; % integral over bin-width + + return result; +} +\end{verbatim} + +All user-defined, additive and multiplicative \slang\ +fit-functions must follow this basic form; the function +interface for operator models is slightly different (see +below). The three input array arguments may have any valid +variable names, but the arguments will be supplied in the order +indicated; bin lower-edge first, bin upper-edge second and +parameter array third. The user-defined function must return a +single array providing the bin-integrated function value in +each bin. Note that, for clarity, error-checking has been +omitted from this example. + +Thus defined, this {\tt plaw} function may be made available to +the fit-engine at run-time using +\begin{verbatim} + add_slang_function ("plaw", ["norm","power"]); +\end{verbatim} +Parameter names must be listed in the order they appear in the parameter +array which is passed to the subroutine. The \slang\ function +may also be specified using a reference: +\begin{verbatim} + add_slang_function ("plaw", &plaw_fit, ["norm","power"]); +\end{verbatim} +In this case, the function may have any name. To provide +a differential version of the same function (as opposed to +the usual binned version), provide an array of two function +references: +\begin{verbatim} + add_slang_function ("plaw", [&plaw_binned, &plaw_diff], ["norm","power"]); +\end{verbatim} +The differential version should have an interface of the form +\begin{verbatim} + define plaw_diff (x, p) + { + % compute the differential value f(x) + return f; + } +\end{verbatim} + +To use this new \slang\ function in fitting data, one should use +the fit invocation-name with the usual syntax: here, one might +use +\begin{verbatim} + isis> fit_fun ("plaw(1) + plaw(2)"); +\end{verbatim} +to sum two instances of the {\tt plaw} function. + +When one of the parameters is called {\tt "norm"} +(case-insensitive), it will be treated as the only +normalization parameter. Alternatively, the zero-based array +indicies of those parameters to be treated as normalizing +coefficients should be listed using the optional third +parameter {\tt norm\_indexes}. If no parameter is called {\tt +"norm"} and no list is given, none of the function parameters +will be adjusted by {\tt renorm\_*}. + +Default parameter values and ranges may be specified using a +separate \slang\ function (see \verb|set_param_default_hook|). + +User-defined fit-functions may also access global data, allowing +one to write functions which require a significant amount of data +to generate the desired result. In particular, one might load a +table model from a file, and then use those data to compute model +values. For example, consider a file containing the following +S-Lang code: + +\begin{verbatim} +require ("xspec"); +static variable X_lo, X_hi, Value; + +define fast_wabs_init (x) +{ + x = _A(x); + X_lo = x[[:-2]]; + X_hi = x[[1:]]; + variable y = eval_fun2 (&wabs, X_lo, X_hi, 1.0); + + % rebin assumes bin-integrated quantities + Value = y * (X_hi - X_lo); +} + +fast_wabs_init ( 10.0^[-3:1.3:0.001] ); + +define fast_wabs_fit (lo, hi, par) +{ + variable y = rebin (lo, hi, X_lo, X_hi, Value); + y /= hi - lo; + + return y^(par[0]); +} + +add_slang_function ("fast_wabs", ["NH_22"]); + +provide ("fast_wabs"); +\end{verbatim} + +When this file is loaded, it evaluates the XSPEC absorption model +\verb|wabs| for a unit absorbing column and a fixed standard grid, +storing the result in the global variables \verb|X_lo|, +\verb|X_hi| and \verb|Value|. It also defines a new fit-function +called \verb|fast_wabs|. When called, this fit-function +interpolates the saved \verb|wabs| values onto the specified grid +and rescales the result to match the current value of absorbing +column. This is considerably faster than the current XSPEC default +implementation which repeatedly recomputes the optical depth +contribution from each element, even though the abundances of the +absorbing gas remain fixed. + +Operator models differ from additive and multiplicative models +in that they operate on the result of another function. For +example, the Gaussian smoothing operator \verb|gsmooth|, can be +invoked using the syntax +\begin{verbatim} + fit_fun ("gsmooth (1, mekal(1))"); +\end{verbatim} +This example computes a spectrum using the \verb|mekal| model +and then convolves it with a Gaussian using the \verb|gsmooth| +operator. Although isis fit-functions can take an arbitrary +number of additional arguments of any type, ``operator'' models +represent an important special case because they correspond +closely to the ``convolution'' models long provided by XSPEC. +For historical reasons, \isis\ handles operator models in a +rather special way. + +To implement an operator model in S-Lang, the S-Lang function +should be defined with an interface of the form +\begin{verbatim} + define my_operator_fit (lo, hi, par, fun_value) +\end{verbatim} +where the first three arguments are the same as for additive +and multiplicative functions and the last argument +\verb|fun_value| is a S-Lang array containing the computed +function to which the operator will be applied. Before use, +operator models implemented in S-Lang must be labeled as +operator models by calling the \verb|set_function_category| +function: +\begin{verbatim} + add_slang_function ("my_operator", ["a", "b"]); + set_function_category ("my_operator", ISIS_FUN_OPERATOR); +\end{verbatim} + +In general, \isis\ fit-functions may take an arbitrary number +of parameters. This feature makes it possible to encode quite +complicated functional relationships into one or more suitably +defined ISIS fit-functions that work cooperatively. The +usefulness of this feature is perhaps best illustrated by a +concrete example. + +This example corresponds closely to the design of the +nonthermal spectral models for \isis +\footnote{{\tt +http://space.mit.edu/home/houck/software/slang/modules/nonthermal/}}. +In that module, the goal is to compute a variety of nonthermal +photon emission spectra that arise from a given nonthermal +particle distribution function. Several +parameterizations of the particle distribution function are +available and each photon emission process carries additional +process-specific parameterizations. A natural way to express +this relationship is to specify a \verb|pdf| as an argument +to each spectral model: +\begin{verbatim} + sync (1, pdf(1)) + invc (1, pdf(1)) + ntbrem (1, pdf(1)) +\end{verbatim} +This syntax means that the \verb|sync| function will be +computed for the distribution function specified by \verb|pdf|, +and so on. + +The implementation is complicated by the fact that, for +performance reasons, the particle distribution function is best +implemented in a compiled language such as C. Without getting +into the details of the implementation, the important point is +that one can select the appropriate C subroutine to compute the +PDF by creating a \slang\ function \verb|pdf| that returns the +name of the PDF that is to be evaluated, along with the +parameters for that PDF. + +To make this connection, the fit-function \verb|pdf| should +return two objects -- a string specifying the name of the +particle distribution function plus the associated parameter +vector: +\begin{verbatim} +private define pdf (l,h,p) +{ + return ("pdf", p); +} +add_slang_function ("pdf", &pdf, ["a", "b", "c"]); +\end{verbatim} +Note that the wrapper function does nothing with the spectral +grid arrays \verb|(l,h)|. The only purpose of this model is +to enable passing a parameter array on to the named PDF. +Each different particle distribution should have a similar +wrapper that returns the relevant model name and list of +parameter values. + +The \verb|sync| function can then be defined to make use of +these additional parameters: +\begin{verbatim} +private define sync (l,h,p) +{ + variable pdf_name, pdf_pars; + (pdf_name, pdf_pars) = (); + return compute_sync (l, h, p, pdf_name, pdf_pars); +} +add_slang_function ("sync", &sync, ["norm", "B"]); +\end{verbatim} +Note that the \verb|sync| function could also be defined +like so: +\begin{verbatim} + define sync (pdf_name, pdf_pars, l, h,p) + { + ... + } +\end{verbatim} +This definition is functionally identical to the previous one. + +For a similar example, see {\it e.g.} \verb|create_aped_line_profile| +and \verb|create_aped_line_modifier|. +\end{isisfunction} + +\begin{isisfunction} +{add\_slang\_statistic} %name +{Add a user-defined S-Lang fit-statistic} %purpose +{add\_slang\_statistic (name, \&stat, \&report)} %usage +{set\_fit\_statistic, load\_fit\_statistic} +\index{User-defined!fit-statistic (S-Lang)} + +The first argument is the name of the fit-statistic. The next +two arguments are addresses of \slang\ functions to compute the +fit-statistic and to print the statistic value, respectively. + +The function which computes the fit-statistic named \verb|"stat"| +should be named \verb|stat_function| and should have the +interface +\begin{verbatim} + (vec, stat) = stat_function (data, model, weights) +\end{verbatim} +where \verb|data| and \verb|model| and arrays of equal length +containing the data and model values and where \verb|weights| +is an array of the same size containing the statistical weight +of each data point. If $\sigma$ is the uncertainty in the +$i^{th}$ data point, the weight is usually $1/\sigma^2$. +The function returns the value of the fit-statistic, \verb|stat|, +as well as a vector, (\verb|vec|), containing the contribution to the statistic +from each bin. + +The function which prints the fit-statistic named \verb|"stat"| +should be named \verb|stat_report| and should have the +interface +\begin{verbatim} + report_string = stat_report (stat, npts, nvpars) +\end{verbatim} +where \verb|stat| is the value of the fit-statistic, +\verb|npts| is the number of data points being fitted, and +\verb|nvpars| is the number of variable fit-parameters. +The function returns a string which will be printed at +the appropriate time. Note that this string may contain +newline characters (\verb|\n|) allowing it to span multiple +lines of output. + +\begin{verbatim} +For example: + +% First, define the two functions: +static define mychi_function (y, fx, w) +{ + variable v = (y - fx)^2 * w; + return (v, sum (v)); +} + +static define mychi_report (stat, npts, nvpars) +{ + variable s = sprintf (" My Chisqr = %0.4g\n", stat); + return s; +} + +% Add the statistic to the internal list: +add_slang_statistic ("mychi", &mychi_function, &mychi_report); + +% Tell ISIS to use the new fit statistic: +set_fit_statistic ("mychi"); +\end{verbatim} +\end{isisfunction} + +\begin{isisfunction} +{alias\_fun}%name +{Derive a new fit-function from an existing one}%purpose +{alias\_fun (name, new\_name [; \_\_qualifiers])}%usage +{add\_slang\_function, cache\_fun}% +\index{Rename a fit-function} +\index{Rename function parameters} +\index{Change parameter defaults} + +To derive a new fit-function with the same properties as an +existing fit-function, but with a different name, just do +\begin{verbatim} + alias_fun (old_name, new_name); +\end{verbatim} + +Several qualifiers support changing the parameter names +or their default settings: +\begin{verbatim} + names = array of parameter name strings +values = array of default parameter values +freeze = array of integer flags indicating the default freeze state + min = array of default minimum values + max = array of default maximum values +params = array of {name, value, freeze, min, max} lists +\end{verbatim} + +\begin{verbatim} +EXAMPLE: + alias_fun ("egauss", "FeKa"; + names= ["area [ph/s/cm^2]", "E [keV]", "sigma [keV]"], + values=[ 0.01, 6.4, 0.5 ], + freeze=[ 0, 1, 0 ], + min= [ 0, 5.8, 1e-6 ], + max= [ 1, 7, 2 ]); +\end{verbatim} + +\end{isisfunction} + +\begin{isisfunction} +{array\_fit} %name +{Fit a function y=F(x) to data consisting of (X,Y) pairs} %purpose +{(pars, stat) = array\_fit (x, y, wt, pars, par\_min, par\_max, \&fun)} %usage +{set\_fit\_method, set\_fit\_statistic, fit\_counts, fit\_flux} + +Use this function to fit a function y = F(x) to data consisting of +(X,Y) pairs. +\begin{verbatim} + __Input_Parameters__ __Definition___ + x, y Input data arrays of equal length. + + wt Optional weights for the input Y values; + If wt = NULL, all Y values receive wt=1. + + pars Input array of initial parameter values + + par_min, par_max Input arrays of allowed parameter ranges. + If either value is NULL, the corresponding + bound extends to infinity. + + fun_ref Reference to a S-Lang function with + interface y = f(x, pars) + +\end{verbatim} + +If the fit succeeds, the function returns an array (\verb|pars|) +best-fit parameter values and the corresponding value of the fit-statistic +(\verb|stat|). If the fit fails, the return values are +\verb|pars=NULL| and \verb|stat=0|. + +For example, to fit a line to scatter data using equal weights +on the data points and with unlimited ranges for the fit-parameters: +\begin{verbatim} +% supply a linear fit-function +define fun (x, pars) +{ + return pars[0] + x * pars[1]; +} + +% fit the data (providing initial parameter values in `pars') +(best, stat) = array_fit (x, y, NULL, pars, NULL, NULL, &fun); +\end{verbatim} + +\end{isisfunction} + +\begin{isisfunction} +{bin\_center} %name +{Bin-center utility fit-function} %purpose +{bin\_center(id)} %usage +{bin\_center\_en, bin\_width, gauss, Lorentz, poly, delta} + +Utility fit-function which evaluates to the wavelength [{\AA}ngstrom] at bin-center. + +\end{isisfunction} + +\begin{isisfunction} +{bin\_center\_en} %name +{Bin-center utility fit-function} %purpose +{bin\_center\_en(id)} %usage +{bin\_center, gauss, Lorentz, poly, delta} + +Utility fit-function which evaluates to the energy [keV] at bin-center. + +\end{isisfunction} + +\begin{isisfunction} +{bin\_width} %name +{Bin-width utility fit-function} %purpose +{bin\_width(id)} %usage +{bin\_width\_en, bin\_center, gauss, Lorentz, poly, delta} + +Utility fit-function which evaluates to the bin-width in {\AA}ngstrom. + +\end{isisfunction} + +\begin{isisfunction} +{bin\_width\_en} %name +{Bin-width utility fit-function} %purpose +{bin\_width\_en(id)} %usage +{bin\_width, bin\_center, gauss, Lorentz, poly, delta} + +Utility fit-function which evaluates to the bin-width in keV. + +\end{isisfunction} + +\begin{isisfunction} +{blackbody} %name +{Blackbody fit-function} %purpose +{blackbody(id)} %usage +{gauss, Lorentz, poly, delta} + +The blackbody function has two variable parameters, the +temperature ($kT$) in keV and the normalization ($N$). + +\begin{equation} + B (E_i^{\rm lo}, E_i^{\rm hi}) = 8.0525~ + {N \over \left(kT\right)^4}~ + \int_{E_i^{\rm lo}}^{E_i^{\rm hi}}\D E~{E^2 \over e^{E/kT} - 1} +\end{equation} + +The normalization is the same as that used by \xspec, with $N = +L_{39}/D_{10}^2$ where $L_{39}$ is the source luminosity in units +of $10^{39}$ erg~s${}^{-1}$ and $D_{10}$ is the source distance in +units of 10 kpc. + +\end{isisfunction} + +\begin{isisfunction} +{cache\_fun}%name +{Create a caching fit-function}%purpose +{caching\_name = cache\_fun (name, lo, hi [; \_\_qualifiers]);}%usage +{add\_slang\_function, alias\_fun}% +\index{Optimization!caching fit-function values} +\index{Caching fit-function values} + +In some fitting applications (e.g confidence limit searches), +computationally expensive model components may be repeatedly +evaluated for a single set of parameters. In these +circumstances, it may be more efficient to temporarily cache +the most recent model result to avoid the expense of +re-computing it. + +Use the \verb|cache_fun| intrinsic to create a caching version +of any fit-function that has at least one parameter. The +caching version computes the associated function on the +provided wavelength grid and saves the result until the next +time a parameter value changes. When the cacheing version is +called N times with the same parameters, the underlying +function will be evaluated only once, on the first call -- the +next N-1 calls will be handled by rebinning the cached result. + +Note that the caching version will not extrapolate the model +beyond the bounds of the specified wavelength grid; any attempt +to do so will generate an error. + +The \verb|mult| qualifier should be used when caching +multiplicative models. It ensures that the bin-averaged model +value is used. Without this qualifier, the rebinned model is +bin-integrated. + +The \verb|suffix| qualifier can be used to label different +caching versions of a single underlying function. + +\begin{verbatim} +EXAMPLE: + +isis> (lo,hi) = linear_grid(1,20,2000); +isis> variable caching_tbabs_name = cache_fun ("tbabs", lo, hi; mult); +isis> fit_fun ("$caching_tbabs_name(1) * mekal(1)"$); +isis> list_par; +tbabs_cache(1) * mekal(1) + idx param tie-to freeze value min max + 1 tbabs_cache(1).nH 0 0 1 0 100000 + 2 mekal(1).norm 0 0 1 0 1e+10 + 3 mekal(1).kT 0 0 1 0.0808 79.9 keV + 4 mekal(1).nH 0 1 1 1e-05 1e+19 cm-3 + 5 mekal(1).Abundanc 0 1 1 0 1000 + 6 mekal(1).redshift 0 1 0 0 10 + 7 mekal(1).switch 0 1 1 0 1 +isis> +\end{verbatim} + +\end{isisfunction} + +\begin{isisfunction} +{conf} %name +{Compute single-parameter confidence limits} %purpose +{(low, high) = conf(param\_index [, level [, tolerance]])} %usage +{fconf, vconf, fit\_counts, fit\_flux, conf\_joint} +\index{Confidence Limits!single parameter} + +By default, 90\% confidence limits are computed. The optional +second argument may be used to specify the confidence level. It +may be set to one of the values 0, 1 or 2 indicating 68\%, 90\% or +99\% confidence levels respectively. Use \verb|fconf| to specify +a particular value of $\Delta\chi^2$. + +The tolerance parameter may be used to control how precisely the +confidence limit is to be determined; the search for the parameter +value at the specified confidence limit will continue until +\begin{equation} + \chi^2(x_{\rm limit}) - (\chi^2(x_{\rm best-fit}) + \delta\chi^2_{\rm +limit}) < {\rm tolerance} * \delta\chi^2_{\rm limit} +\end{equation} +where $\delta\chi^2_{\rm limit}$ is the change in $\chi^2$ corresponding +to the specified confidence limit. The default \verb|tolerance| is +$10^{-3}$. + +If an improved fit is found during the confidence limit search, +the function updates the internal parameters with the new best-fit +parameter values and returns {\tt low = high}. Otherwise the +internal parameter table is not modified. + +One can also refer to parameters by name: +\begin{verbatim} + (lo, hi) = conf ("gauss(2).area"); +\end{verbatim} + +If it has been defined, the function +\verb|isis_fit_improved_hook| is called immediately before each +fit during the confidence limit search. This function must be +of the form +\begin{verbatim} + Integer_Type status = isis_fit_improved_hook (); +\end{verbatim} +A non-zero return value causes the algorithm to behave as +though a new best-fit parameter value has been detected. If +the return value is zero, the algorithm proceeds normally. This +hook was added to support distributed computation of +single-parameter confidence limits. It provides a mechanism to +signal slave processes that the confidence limit search should +be re-started from the beginning using a new initial set of +parameters. + +\end{isisfunction} + +\begin{isisfunction} +{conf\_grid} %name +{Generate a parameter grid for computing confidence contours} %purpose +{Struct\_Type = conf\_grid (index, min, max, num)} %usage +{conf\_map\_counts, conf\_map\_flux, plot\_conf, save\_conf, load\_conf} +\index{Confidence Limits!parameter grid} + +For example: +\begin{verbatim} + px = conf_grid ("gauss(1).center", 11.43, 12.95, 64); + py = conf_grid ("gauss(1).sigma", 0.01, 0.04, 64); + s = conf_map_counts (px, py); +\end{verbatim} +or, using parameter indices: +\begin{verbatim} + px = conf_grid (2, 11.43, 12.95, 64); + py = conf_grid (3, 0.01, 0.04, 64); + s = conf_map_counts (px, py); +\end{verbatim} + +\end{isisfunction} + +\begin{isisfunction} +{conf\_joint} %name +{Compute two-parameter joint confidence limits} %purpose +{Struct\_Type = conf\_joint (Struct\_Type[, delta\_chisqr])} %usage +{conf\_map\_counts, conf\_map\_flux, plot\_conf, save\_conf, load\_conf} +\index{Confidence Limits!joint} + +By default, this routine extracts 68\% joint confidence limits +for two degrees of freedom, corresponding to a chi-square +difference of 2.30. Use the optional argument to supply an +alternate delta-chisqr value. + +The confidence limits are extracted by interpolating values from +the 2D chi-square map generated by \verb|conf_map_counts| or +\verb|conf_map_flux|. Therefore, a +finer chi-square map grid will usually allow extracting more +accurate confidence limit values. The documentation for +\verb|conf_map_counts| specifies the form of the input structures. + +The return value is a structure which contains the X and Y +parameter ranges corresponding to the specified joint +confidence limit. + +\begin{verbatim} +Example: + s = conf_map_counts (px, py); + jlim = conf_joint (s); + + => jlim = struct {xmin, xmax, ymin, ymax} +\end{verbatim} + +\end{isisfunction} + +\begin{isisfunction} +{conf\_map\_counts} %name +{Generate a 2D chi-square map for counts data} %purpose +{Struct\_Type = conf\_map\_counts (Struct\_Type x, Struct\_Type y [, info])} %usage +{conf\_grid, plot\_conf, save\_conf, load\_conf, conf\_map\_flux} +\index{Confidence Limits!2D maps} +\index{Confidence Limits!2D maps, log axes} + +This function maps the chi-square space by stepping two +fit-parameters over a specified range. In combination +with \verb|set_par_fun|, one can also generate confidence +contour plots which include fairly arbitrary coordinate +transformations (e.g. contours drawn vs. the log of the +parameter rather than the parameter value itself). + +The parameter indices and an associated uniform grid of values +should be specified using a structure of the form: +\begin{verbatim} + Struct_Type = struct {index, min, max, num}; +\end{verbatim} +where \verb|index| gives the parameter index and the remaining +three fields specify the grid. The simplest way to generate +this struct is to use \verb|conf_grid|. + +The optional third argument is a structure whose fields provide +references to functions which can be used during confidence +contour calculation to customize recovery from failed fit +attempts, save parameters in a custom format and to mask out +parameter regions to avoid during the calculation. +This argument may have the form +\begin{verbatim} + info = struct {fail, save, mask} +\end{verbatim} +Note that the struct need only include those fields +which are actually used. + +The return value is a structure containing a 2D array of +chi-square values and other information. It has the form: +\begin{verbatim} + s = struct {chisqr, px, py, best, px_best, py_best}; +\end{verbatim} + +Because confidence maps can be quite cpu-intensive to compute, it +may be useful to save the resulting map to a FITS file using +\verb|save_conf|. It can then be reloaded later using +\verb|load_conf|. + +Use \verb|[o]plot_conf| to plot and over-plot the confidence +contour map. + +\begin{verbatim} +Example: + + px = conf_grid (2, 11.96, 12.04, 64); + py = conf_grid (3, 0.015, 0.035, 64); + s = conf_map_counts (px, py); + +% This yields: + +print(s); + chisqr = Double_Type[64,64] + px = Struct_Type + py = Struct_Type + best = 11.0525 + px_best = 12.0046 + py_best = 0.0216003 +\end{verbatim} + +To customize the computation of the confidence contour map, +perhaps by writing out additional information for each map +element, one can provide a definition for the \verb|save| +field of the \verb|info| structure mentioned above. +The save hook should be a function of the form +\begin{verbatim} + define save_hook (p) +\end{verbatim} +where the \verb|p| argument passed to this function is the +information structure returned by the corresponding fit-function, +e.g. \verb|fit_counts| or \verb|fit_flux|. The hook will be called +once each time a new chi-square value is saved in the confidence +contour map. For example, to write out an ASCII table containing +the chi-square value at every map element plus all the fit +parameters, one could do the following: +\begin{verbatim} + +% First, open the output file, saving the file pointer +% in a global variable + +variable fp = fopen ("contour_info.txt", "w"); +if (fp == NULL) + exit(1); + +% Define the hook function so that it writes out the +% current value of the fit-statistic and all the fit-parameters: +define save_hook (p) +{ + variable pars = get_params(); + + () = fprintf (fp, "%15.6e", p.statistic); + foreach (pars) + { + variable x = (); + () = fprintf (fp, " %15.6e", x.value); + } + () = fputs ("\n", fp); +} + +% set the save hook to point to your function: +variable info = struct {fail, save, mask} +info.save = &save_hook; + +% compute the confidence map, simultaneously generating +% the ASCII file opened above +variable map = conf_map_counts (px, py, info); + +% close the ASCII file +() = fclose(fp); +\end{verbatim} + +In mapping out the behavior of chi-square it may happen that the +chosen fit algorithm fails to converge at some points in the +parameter space. Sometimes this is merely a reflection of the +fact that the chi-square space is complex and finding the minimum +at any given point may be difficult. Unfortunately, such +convergence failures may cause the routine to take an inordinately +long time to map out the behavior of chi-square and may also +degrade the quality of the resulting map. + +To provide a way to recover from these convergence failures +without restarting the chi-square mapping process, ISIS provides +a failure recovery hook via \verb|info.fail|, analogous +to the above \verb|save_hook| example. +The \verb|fail| field should provide a reference to +a function of the form +\begin{verbatim} + define fail_hook (p1, p2, best_pars, try_pars, fit_info); +\end{verbatim} +where +\begin{verbatim} + p1, p2 = the indices of the 2 parameters being mapped + best_pars = an array of parameter-info structures + defining the current best-fit parameter set. + (see get_par_info() for details) + try_pars = an array of parameter-info structures + defining where a fit failed to converge. + (see get_par_info() for details) + fit_info = the fit_info structure returned + by the failed call to fit_counts() or fit_flux(). +\end{verbatim} +The referenced function will be called whenever \verb|fit_counts| or +\verb|fit_flux| fails. This function should attempt to determine +the best fit given the array \verb|try_pars| as the initial +parameter state. On return, it should update the \verb|statistic| +field of the \verb|fit_info| structure. + +For example, in using the pileup model, it often happens that, the +\verb|minim| algorithm is good at getting close to the best fit +even when given a relatively poor initial guess, but is relatively +slow to improve on a ``close'' solution. In contrast, although +\verb|marquardt| may require a relatively good initial guess, it +excels at efficiently optimizing a good initial guess. To use the +strengths of both methods, one might use \verb|minim| as the +primary algorithm when mapping the chi-square space, but use +\verb|marquardt| to recover if \verb|minim| fails. + +To do that, one could use a failure-recovery hook like this: +\begin{verbatim} + define fail_hook (p1, p2, best_pars, try_pars, fit_info) + { + variable save_method = get_fit_method (); + + set_fit_method ("marquardt"); + () = fit_counts (&fit_info); + + set_fit_method (save_method); + } + + info.fail = &fail_hook; +\end{verbatim} + +One way to speed computation of confidence contour maps +using computationally expensive models is to mask out +regions of the parameter space which can be ignored. +The \verb|mask| hook provides this capability by providing +a reference to a function of the form +\begin{verbatim} + define mask_hook (p1, p2) +\end{verbatim} +As arguments, this function should take the coordinates +of a point in the parameter space of interest. If +a fit should be done at this point, the function should +return a non-zero value. If a fit should not be done, +the function should return zero. + +To compute confidence contours for one or more derived quantities, +one can use \verb|set_par_fun| to define the appropriate +transformation. Here is an unrealistic example which serves to +illustrate the idea. + +To compute confidence contours on a log-log plot, we +introduce a function to supply the coordinate transformation: +\begin{verbatim} + define transform_fit (l,h,p) + { + return 1; + } + add_slang_function ("transform", ["log_norm", "log_kT"]); + + fit_fun ("mekal(1)*transform(1)"); + + set_par("transform(1).log_norm", -3.0); + set_par("transform(1).log_kT", 0.5); + set_par_fun ("mekal(1).norm", "10^transform(1).log_norm)"); + set_par_fun ("mekal(2).kT", "10^transform(1).log_kT"); +\end{verbatim} +The fit-parameter table is then: +\begin{verbatim} +mekal(1)*transform(1) + idx param tie-to freeze value min max + 1 mekal(1).norm 0 1 0.001 0 1e+10 +#=> 10^transform(1).log_norm + 2 mekal(1).kT 0 1 3.162278 0.0808 79.9 +#=> 10^transform(1).log_kT + 3 mekal(1).nH 0 1 1 1e-05 1e+19 + 4 mekal(1).Abundanc 0 1 1 0 1000 + 5 mekal(1).Redshift 0 1 0 0 10 + 6 mekal(1).Switch 0 1 1 0 1 + 7 transform(1).log_norm 0 0 -3 0 0 + 8 transform(1).log_kT 0 0 0.5 0 0 +\end{verbatim} + +With this definition, one can now compute confidence contours +using the logarithmic parameters (of \verb|transform|) +rather than the linear parameters (of \verb|mekal|). + +\end{isisfunction} + +\begin{isisfunction} +{conf\_map\_flux} %name +{Generate a 2D chi-square map for flux-corrected data} %purpose +{Struct\_Type = conf\_map\_flux (Struct\_Type x, Struct\_Type y [, info])} %usage +{conf\_grid, plot\_conf, save\_conf, load\_conf} +\index{Confidence Limits!2D maps} + +This function is identical to \verb|conf_map_counts| except that it +applies to flux-corrected data. See \verb|conf_map_counts| for +details. +\end{isisfunction} + +\begin{isisfunction} +{vconf} %name +{Compute single-parameter confidence limits} %purpose +{(low, high) = vconf(param\_index [, level, [, tolerance]])} %usage +{conf, fconf, fit\_counts, fit\_flux, conf\_joint} +\index{Confidence Limits!single parameter} + +This is the verbose form of {\tt conf}: on each iteration +it prints the current parameter value, chi-square and the change in +chi-square away from the initial value. +\end{isisfunction} + +\begin{isisfunction} +{vfconf} %name +{Compute single-parameter confidence limits} %purpose +{(low, high) = fconf(param\_index [, dchisqr, [, tolerance]])} %usage +{conf, fconf, fit\_counts, fit\_flux, conf\_joint} +\index{Confidence Limits!single parameter} +This is the verbose form of {\tt fconf}: on each iteration +it prints the current parameter value, chi-square and the change in +chi-square away from the initial value. +\end{isisfunction} + +\begin{isisfunction} +{del\_function} +{Delete a user-defined fit function} +{del\_function ("function")} +{add\_compiled\_function, add\_slang\_function,list\_functions} +{\it Note: this function is available only on systems with ELF support. } +Only user-defined functions may be deleted. +\end{isisfunction} + +\begin{isisfunction} +{delta} %name +{Delta-function line profile (for fitting)} %purpose +{delta(id)} %usage +{gauss, Lorentz, poly, bin\_center, bin\_width } + +This fit-function corresponds to a delta-function in that it +contributes flux only to the single spectral bin which contains +the specified wavelength. + +\end{isisfunction} + +\begin{isisfunction} +{edit\_par} %name +{edit fit parameters} %purpose +{edit\_par (["filename"])} %usage +{load\_par} + +This function allows the user to edit the current set of fit +parameters in a text editor. The text editor is specified by the {\sc +EDITOR} environment variable; if the environment variable is not set, +{\tt vi} is used. When using {\tt emacs}, the {\tt emacsclient} +feature (of {\tt emacs}) may be used to avoid invoking a new {\tt +emacs} process for each edit. + +If a filename is specified, the model is saved in that file, +otherwise, a temporary file is generated and is deleted when editing +is finished. If the {\sc TMPDIR} environment variable is set, the +temporary file created for editing will be placed in the indicated +directory. Otherwise, the temporary file will be placed in the current +directory. +\end{isisfunction} + +\begin{isisfunction} +{egauss} %name +{Gaussian line profile function [energy grid]} %purpose +{egauss(id)} %usage +{gauss} + +Because multiple Gaussians are allowed in a single fit, the {\tt id} +parameter is used as a label to distinguish multiple instances of a +particular function type. The function value assigned to each bin is the +area under the Gaussian curve which lies inside the bin: + +\begin{equation} +{\rm gauss}(E_a,E_b) = {A \over \sigma \sqrt{2\pi}} + \int_{E_a}^{E_b} \D E~ + \exp\left[-{ (E-E_0)^2 \over 2\sigma^2} \right] +\end{equation} +where $A$ is the total area (e.g. photons/s/cm${}^2$) under the Gaussian centered +at $E_0$ with width $\sigma$. +\end{isisfunction} + +\begin{isisfunction} +{eval\_counts} %name +{evaluate the fit-model using the current parameters} %purpose +{s = eval\_counts([response\_type] [,\&info\_struct])} %usage +{fit\_counts, renorm\_counts, ignore, notice, rebin, [un]assign\_arf, [un]assign\_rmf, eval\_stat\_counts} + +This function evaluates the fit-model and compares it with the +counts data to compute the fit-statistic. This is often useful +for checking the accuracy of initial parameter values before +searching for the best fit values. + +See {\tt fit\_counts} for details. + +\end{isisfunction} + +\begin{isisfunction} +{eval\_flux} %name +{evaluate the fit-model using the current parameters} %purpose +{s = eval\_flux([response\_type][, \&info\_struct])} %usage +{fit\_flux, factor\_rsp, renorm\_flux, ignore, notice, rebin, [un]assign\_arf, [un]assign\_rmf} + +Analogous to {\tt eval\_counts} except that the model is compared +with the flux-corrected histogram (see \verb|flux_corr|). See +{\tt fit\_flux} for details. + +\end{isisfunction} + +\begin{isisfunction} +{eval\_fun} %name +{Evaluate the fit-function on a user-defined grid} %purpose +{y = eval\_fun (lo, hi)} %usage +{get\_cfun, get\_cfun2, fit\_fun, eval\_fun2} + +This function evaluates the current fit-function on the specified +histogram grid \verb|(lo, hi)|. +\begin{verbatim} +Example: + (lo, hi) = linear_grid (1,20,2000); % define a grid + y = eval_fun (lo, hi); % get function values +\end{verbatim} +Note that \verb|eval_fun| returns the fit-function integrated over +the width of the specified bins. + +If the current fit-function evaluates differently for different +datasets, it is necessary to specify the dataset index to use when +evaluating the fit-function. Do this by setting the +\verb|Isis_Active_Dataset| index before calling \verb|eval_fun|. +\end{isisfunction} + +\begin{isisfunction} +{eval\_fun2} %name +{Evaluate a fit-function on a user-defined grid} %purpose +{y = eval\_fun2 (handle, lo, hi [, params [, args...]])} %usage +{get\_cfun, fit\_fun, eval\_fun, fitfun\_handle, list\_par} + +Use \verb|eval_fun2| to evalute a particular fit-function on a +given histogram grid \verb|(lo, hi)| using a given vector of +function parameters. The fit-function to be evaluated may be +specified by name (\verb|"gauss"|), by reference +(\verb|&gauss|) or by giving the handle returned by +\verb|fitfun_handle|. +\begin{verbatim} +Example: + (lo, hi) = linear_grid (1,20,2000); % define a grid + + % define parameters [area, center, sigma] + pars = [100.0, 12.0, 0.025]; + + % evaluate the function giving its name + y = eval_fun2 ("gauss", lo, hi, pars); + + % evaluate the function giving a reference + y = eval_fun2 (&gauss, lo, hi, pars); + + % evaluate the function giving a reference + handle = fitfun_handle ("gauss"); + y = eval_fun2 (handle, lo, hi, pars); +\end{verbatim} +For repetitive function evaluations it is somewhat more +efficient to refer to the function using a handle. + +The function parameters should be given in the order in which +they are listed by \verb|list_par|. If the specified +fit-function has no parameters, the fourth argument may be +omitted or may be either \verb|NULL| or an array of length +zero. + +Any additional arguments will be passed on to the fit-function. +For example, if the specified fit-function is an operator +function the operator will be applied to the vector given in +the last argument. +\begin{verbatim} +Example: + y = eval_fun2 ("gsmooth", lo, hi, pars, arg); +\end{verbatim} + +Note that \verb|eval_fun2| returns the fit-function integrated +over the width of the specified bins. +\end{isisfunction} + +\begin{isisfunction} +{eval\_stat\_counts} %name +{Evaluate the (counts) fit-statistic using the current parameters} %purpose +{Struct\_Type = eval\_stat\_counts()} %usage +{eval\_stat\_flux, fit\_counts} + +This function recomputes the fit-statistic for the counts data +without re-evaluating the current model. + +This necessarily assumes that the model has already been +computed on the correct grid. Note that the model stored +internally will be inconsistent if the data have been modified +since the last model evaluation (e.g. if the data were rebinned +or if different data bins have been ignored or noticed). If +the stored model is inconsistent, the computed statistic value +will also be inconsistent. + +\end{isisfunction} + +\begin{isisfunction} +{eval\_stat\_flux} %name +{Evaluate the (flux) fit-statistic using the current parameters} %purpose +{Struct\_Type = eval\_stat\_flux()} %usage +{eval\_stat\_counts, fit\_counts} + +This function recomputes the fit-statistic for the +flux-corrected data without re-evaluating the current model. + +This necessarily assumes that the model has already been +computed on the correct grid. Note that the model stored +internally will be inconsistent if the data have been modified +since the last model evaluation (e.g. if the data were rebinned +or if different data bins have been ignored or noticed). If +the stored model is inconsistent, the computed statistic value +will also be inconsistent. + +\end{isisfunction} + +\begin{isisfunction} +{exclude} %name +{Exclude datasets from the fit} %purpose +{exclude (data\_list)} %usage +{include, ignore, notice} + +This function is similar to \verb|ignore| except that it +allows one to exclude a dataset from a fit without changing +which bins are currently noticed. + +For example, suppose you want to fit a narrow wavelength +range in 3 datasets simultaneously. After noticing those +wavelength ranges and ignoring everything else, you might +want to try excluding one or more datasets from the fit, +but you don't want to lose the noticed wavelength ranges. +This interaction would look something like +\begin{verbatim} + % ... try fitting all 3 at once ... + xnotice ([1:3], 12.4, 13.5); + + % -- now fit dataset 2 alone -- + exclude (1,3); + + % -- re-include dataset 1, with 12.4-13.5 angstroms + % still noticed, etc. + include (1); +\end{verbatim} + +\end{isisfunction} + +\begin{isisfunction} +{fconf} %name +{Compute single-parameter confidence limits} %purpose +{(low, high) = fconf(param\_index [, dchisqr, [, tolerance]])} %usage +{conf, fconf, fit\_counts, fit\_flux, conf\_joint} + +This form of \verb|conf| allows specifying a particular value +of $\Delta\chi^2$ appropriate for the desired confidence limit. +By default, \verb|dchisqr = 2.71|, and 90\% confidence limits are +computed. + +One can also refer to parameters by name: +\begin{verbatim} + (lo, hi) = fconf ("gauss(2).area"); +\end{verbatim} +\end{isisfunction} + +\begin{isisfunction} +{fit\_counts} %name +{search for best fit parameters} %purpose +{s = fit\_counts ([response\_type][,\&info\_struct])} %usage +{eval\_counts, renorm\_counts, ignore, notice, freeze, thaw, +rebin, [un]assign\_arf, [un]assign\_rmf, fit\_flux, fit\_search, set\_post\_model\_hook} + +By default, this function fits the current model to the counts +data by folding the model through the instrument response. If no +instrument response has been assigned, an ideal instrument is +assumed. If no errors occurred during the fit, the return status +is zero, otherwise the return value is -1. + +The two optional arguments may appear in any order. + +The optional \verb|Struct_Type| argument should provide the address of +a structure: +\begin{verbatim} + variable info_struct = struct {statistic, num_variable_params, num_bins} +\end{verbatim} +On return, the struct fields contain the value of the $\chi^2$ +fit-statistic ({\tt statistic}), the number of variable fit +parameters ({\tt num\_variable\_params}) and the number of data +bins ({\tt num\_bins}). + +The {\tt response\_type} option specifies what instrument +responses should be applied. Supported options are +\verb|Ideal_ARF|, \verb|Ideal_RMF|, \verb|Ideal_ARFRMF|, +\verb|Ideal_RMFARF|, \verb|Assigned_RMF|, +\verb|Assigned_ARFRMF|, \verb|Assigned_RMFARF|. +As indicated above, the default is \verb|Assigned_RMFARF|. + +When folding models through the instrument response, the spectral +model will be computed on the ARF grid. Furthermore, the model +will normally be evaluated only over those wavelength ranges that +can contribute to a noticed data bin, as determined by the +available RMF (user-defined fit-kernels may change this behavior). +For example, consider the case of a dispersed spectrum produced by +a diffraction grating. If a single small wavelength range in the +data is noticed for fitting, higher order contributions from +outside this range will also be included in the predicted counts +as long as the RMF includes the higher order contributions. Note +that this means that the spectral model will be computed for all +wavelength ranges which contribute to higher-order contamination, +even if those wavelength ranges correspond to regions of the data +that are currently being ignored for purposes of finding the best +fitting model. + +Four minimization algorithms are available: {\tt lmdif} and +{\tt marquardt} are Levenberg-Marquardt algorithms with +numerical derivatives; {\tt minim} and {\tt subplex} are +variants of the Nelder-Mead simplex algorithm. The latter +approach may require more function evaluations to find the +minimum, but may be less likely to become stuck in a local +minimum. + +Either can be used to search for the best-fit model parameters. +Aside from cases where the fit-function evaluation itself might +fail, it is possible for the fitting algorithm to fail either +because a minimum fit-statistic was not found within a reasonable +number of iterations (see Bevington \& Robinson (1992) for more +details). If the fit algorithm fails, make sure that the initial +parameter values are reasonably close to a good fit and that the +current parameter values haven't run into the specified +upper/lower range limits. Then, try repeating the fit with fewer +variable parameters (see {\tt freeze}, {\tt thaw}). See also {\tt +Fit\_Verbose}. + +When the S-Lang function \verb|isis_prefit_hook| is defined in +the Global namespace, isis will execute this function +immediately before the fit-function is evaluated for the +noticed datasets. For example, one might use this hook together +with \verb|set_eval_grid_method| to specify a default method +for constructing the grid upon which the model will be +evaluated: +\begin{verbatim} + public define isis_prefit_hook () + { + message ("called prefit hook"); + set_eval_grid_method (MERGED_GRID, all_data); + } +\end{verbatim} +With this definition of the hook, the \verb|MERGED_GRID| +method will be used whenever multiple datasets are fitted +simultaneously. See \verb|set_eval_grid_method| for +more details. + +\end{isisfunction} + +\begin{isisfunction} +{fit\_flux} %name +{search for best fit parameters} %purpose +{s = fit\_flux ([response\_type][, \&info\_struct])} %usage +{eval\_flux, renorm\_flux, factor\_rsp, ignore, notice, freeze, thaw, rebin, [un]assign\_arf, [un]assign\_rmf, fit\_counts, fit\_search} + +Analogous to \verb|fit_counts| except that the model is +compared with the flux-corrected histogram (see +\verb|flux_corr|) using the current fit-statistic. By +definition, the model for the flux-corrected histogram is +\begin{equation} + F(h) = \int dE R(h,E) s(E), +\end{equation} +where $E$ is the incident photon energy, $s(E)$ is the model +spectrum, $R(h,E)$ is the redistribution function or RMF and +$h$ is the detector channel. Note that this definition is +independent of the assigned fit-kernel. When a fit-kernel +supports flux-correction, that operation should be consistent +with this definition for $F(h)$. + +When the assigned redistribution function includes the effective +area, an error will be generated. Use \verb|factor_rsp| to +factor such a response matrix, $R(h,E)$ into an effective area +function, $a(E)$ and a normalized redistribution function, +$r(h,E)$ satisfying $R(h,E) = r(h,E)a(E)$. If an effective area +function, $A(E)$ has also been assigned, it may be modified to +include the $a(E)$ factor so that the product, $R(h,E)A(E)$ is +preserved. For example: +\begin{verbatim} + A = load_arf ("arf.fits"); % arf.fits provides A(E) + R = load_rmf ("rsp.fits"); % RMF includes additional area factor `a' + a = factor_rsp (R); % factor R(h,E) -> r(h,E)*a(E) + + % To preserve the product, A*R = (A*a)*r = A'*r + % replace A with A' = A*a: + + A_struct = get_arf(A); + a_struct = get_arf(a); + A_struct.value *= a_struct.value; + put_arf (A, A_struct); +\end{verbatim} +\end{isisfunction} + +\begin{isisfunction} +{fit\_fun} %name +{define a fit function without prompting for parameters} %purpose +{fit\_fun("function\_string")} %usage +{get\_fit\_fun, ifit\_fun, Lorentz, gauss, load\_par, set\_par, set\_par\_fun} + +The function definition string must be a valid \slang\ expression +containing only constant expressions and \isisx intrinsic +fit-functions. For example, to fit a sum of two Gaussians +use +\begin{verbatim} + isis> fit_fun("gauss(1) + gauss(2)"); +\end{verbatim} +The integer indices specify different instances of the Gaussian +fit-function. By default, a single fit-function is applied +to all currently noticed bins in all loaded datasets. + +Fit-function parameters may be defined as functions of other +fit-parameters (see \verb|set_par_fun|). + +Fit-functions may also take additional arguments (see +\verb|add_slang_function|). + +A fit-function which evaluates differently for different datasets +may be defined using the \isisx intrinsic variable +\verb|Isis_Active_Dataset|. For example: +\begin{verbatim} + public define my_complicated_function () + { + if (Isis_Active_Dataset == 1) + { + return gauss(1) + gauss(2); + } + else if (Isis_Active_Dataset == 2) + { + return Lorentz(1) + Lorentz(2); + } + } + + fit_fun ("my_complicated_function()"); +\end{verbatim} +When \verb|my_complicated_function()| is evaluated for dataset 1, +it will return a sum of Gaussians; when evaluated for dataset 2, +it will return a sum of Lorentzians. In effect, each dataset has +been assigned a different fit-function. Here, we have assumed that +exactly two datasets are loaded and are listed as dataset 1 and +dataset 2 in the internal table (see \verb|list_data|). + +The ability to retain parameter values from previous fits is a useful +feature which may help minimize re-entering parameter values. For example, +suppose the initial fit-model is defined as the sum of two Lorentzians: +\begin{verbatim} + isis> fit_fun("Lorentz(1) + Lorentz(2)"); +\end{verbatim} +After seeing the resulting fit, one might decide to try a Lorentzian +plus a Gaussian, +\begin{verbatim} + isis> fit_fun("Lorentz(1) + gauss(2)"); +\end{verbatim} +Seeing that result, one might decide the first fit was better; +on returning to that fit-function: +\begin{verbatim} + isis> fit_fun("Lorentz(1) + Lorentz(2)"); +\end{verbatim} +the coefficients for Lorentz(2) will have retained their +values from the first attempt. This feature can simplify trying +different combinations of functions to produce an +acceptable model fit. + +It is important to remember that, because the fit-function value +is interpreted as the value of an integral over the width of each bin, some +syntactically correct combinations of intrinsic fit-functions +are not analytically consistent. For example, the function definition +\begin{verbatim} +"Lorentz(1) * Lorentz(2) + 4.0 * poly(1)", +\end{verbatim} +is syntactically correct, but analytically inconsistent because +\begin{eqnarray*} +\text{"Lorentz(1) * Lorentz(2)"} &\equiv& +\left(\int_{\lambda_{\rm lo}}^{\lambda_{\rm hi}} L(1)~\D\lambda\right) \times +\left(\int_{\lambda_{\rm lo}}^{\lambda_{\rm hi}} L(2)~\D\lambda'\right) \nonumber\\ +&\not=& \int_{\lambda_{\rm lo}}^{\lambda_{\rm hi}} L(1) L(2)~\D\lambda +\end{eqnarray*} + +Utility functions {\tt bin\_width} and {\tt bin\_center} are +available to support fitting and evaluating bin-averaged and +bin-centered functions. + +\end{isisfunction} + +\begin{isisfunction} +{fitfun\_handle} %name +{Obtain a handle for a given fit-function} %purpose +{handle = fitfun\_handle ("name")} %usage +{eval\_fun2} + +See \verb|eval_fun2| for a usage example. + +\end{isisfunction} + +\begin{isisfunction} +{fit\_search} %name +{Search the fit-parameter space} %purpose +{best = fit\_search (num, \&ref [,"dir" [,save\_all]])} %usage +{fit\_counts, eval\_counts, fit\_flux, eval\_flux, save\_par, fit\_search\_info} + +Use this function to automate the process of exploring the +fit-parameter space. The first argument specifies the number of +Monte-Carlo trials. The second argument provides a reference to a +function which will be used to test each randomly generated +parameter set. This function may simply evaluate the model for +that parameter set or it may search for the best fit given that +starting point. The optional third argument provides a directory +in which to save parameter sets which improve the fit. + +For each Monte-Carlo trial, random parameter values are selected +from within the [\verb|min|, \verb|max|) range for each parameter. +The test function, \verb|ref|, is then applied using those +parameter values. When the result yields the best fit so far, the +resulting parameters are saved (if the test function performs a +fit, the best-fit parameters are saved -- not the initial guess). + +If \verb|dir| has been specified, the saved parameters are also +written to a new file in that directory. Additional output +information may recorded in a user-defined format by defining an +\verb|isis_save_par_hook| which uses the \verb|fit_search_info| +function (See \verb|save_par| and \verb|fit_search_info| for more +information). If \verb|save_all| is non-zero, parameter files +for all fit-trials will be saved in a subdirectory of the +specified directory. + +For example, to carry out 100 Monte-Carlo trials fitting counts +data, saving each successive best-fit in a sub-directory called +"trials": +\begin{verbatim} + stat = fit_search (100, &fit_counts, "trials"); +\end{verbatim} +Each improved parameter set will be saved in files named +\begin{verbatim} + trials/best.0 + trials/best.1 + trials/best.2 + etc. +\end{verbatim} + +To carry out 50 Monte-Carlo trials simply evaluating +flux-corrected data (not attempting to find the best fit for each +trial), and without saving any parameter files to disk: +\begin{verbatim} + stat = fit_search (50, &eval_counts); +\end{verbatim} +\end{isisfunction} + +\begin{isisfunction} +{fit\_search\_info} %name +{Retrieve results of the most recent fit} %purpose +{Struct\_Type = fit\_search\_info ()} %usage +{save\_par, fit\_search, fit\_counts} + +As \verb|fit_search| continues, the info structure +for the most recent fit is saved internally. +This structure may be retrieved by calling \verb|fit_search_info|. +This function is primarily intended for use in conjunction +with \verb|isis_save_par_hook|. See \verb|save_par| +for more information. + +\end{isisfunction} + +\begin{isisfunction} +{fit\_verbose\_info\_hook} %name +{Print verbose status information during a fit} %purpose +{fit\_verbose\_info\_hook (statistic, params[], param\_names[])} %usage +{set\_post\_model\_hook, fit\_counts} + +When \verb|Fit_Verbose| is positive, the \slang\ functions +\verb|open_fit_verbose_hook|, \verb|fit_verbose_info_hook| and +\verb|close_fit_verbose_hook| are called. No arguments are +passed to \verb|open_fit_verbose_hook| and +\verb|close_fit_verbose_hook| and none are returned from either +function. Before the first function evaluation, +\verb|open_fit_verbose_hook| is called to perform any required +initializations (such as opening an output file). After each +function evaluation, \verb|fit_verbose_info_hook| is called +with the names and values of all the parameters and the value +of the fit-statistic. + +By default, the fit statistic and the parameter names and +values are printed to \verb|stdout|. + +Users may provide alternate definitions of these functions in +the \verb|Global| namespace to print the parameter values to a +file or to perform any other suitable task. + +For example, to print the parameter values into a file, one +could provide the following function definitions (which, for +brevity, omit all error checking): + +\begin{verbatim} +% Use a private, file-global variable to hold the file pointer. +private variable Fp = NULL; + +public define open_fit_verbose_hook () +{ + Fp = fopen ("fit_verbose_log.txt", "a"); +} + +public define close_fit_verbose_hook () +{ + () = fclose (Fp); +} + +define write_par (name, value) +{ + () = fprintf (Fp, "%15.8e = %s\n", value, name); +} + +public define fit_verbose_info_hook (stat, values, names) +{ + () = fprintf (Fp, "%11.4e = %s\n", stat, Fit_Statistic); + array_map (Void_Type, &write_par, names, values); +} +\end{verbatim} + +\end{isisfunction} + +\begin{isisfunction} +{freeze} %name +{freeze one or more fit parameters} %purpose +{freeze (par\_list)} %usage +{thaw, tie, untie} +\index{Fitting!freezing parameters} + +{\tt par\_list} may be either a single parameter index or an +integer array of indices. +\begin{verbatim} + freeze(3); % freeze param 3 + freeze([1:4]); % freeze params 1,2,3,4 +\end{verbatim} + +One can also refer to parameters by name: +\begin{verbatim} + freeze ("gauss(2).area"); +\end{verbatim} + +\end{isisfunction} + +\begin{isisfunction} +{gainshift} %name +{Kernel for introducing a gain shift} %purpose +{set\_kernel (data\_index, "gainshift")} %usage +{set\_kernel, fit\_fun} + +This kernel applies a linear transformation of the form +\begin{verbatim} + E' = E/slope - intercept +\end{verbatim} +to the energy grid of the model counts spectrum. The parameters +of the linear transformation are fittable. Aside from the +energy grid transformation, this kernel performs the same +forward-fold computation as the standard fit kernel. The energy +grid of any associated background spectrum is not modified; +the background associated which each detector channel remains +fixed. Flux-correction is not supported. + +\end{isisfunction} + +\begin{isisfunction} +{gauss} %name +{Gaussian line profile function [wavelength grid]} %purpose +{gauss(id)} %usage +{Lorentz, voigt, poly, delta, bin\_width, bin\_center} + +Because multiple Gaussians are allowed in a single fit, the {\tt id} +parameter is used as a label to distinguish multiple instances of a +particular function type. The function value assigned to each bin is the +area under the Gaussian curve which lies inside the bin: + +\begin{equation} +{\rm gauss}(\lambda_a,\lambda_b) = {A \over \sigma \sqrt{2\pi}} + \int_{\lambda_a}^{\lambda_b} \D\lambda~ + \exp\left[-{ (\lambda-\lambda_0)^2 \over 2\sigma^2} \right] +\end{equation} +where $A$ is the total area (e.g. photons/s/cm${}^2$) under the Gaussian centered +at $\lambda_0$ with width $\sigma$. +\end{isisfunction} + +\begin{isisfunction} +{get\_convolved\_model\_flux} %name +{load convolved model values into a \slang\ structure} %purpose +{Struct\_Type =~get\_convolved\_model\_flux~(hist\_index)} %usage +{get\_model\_flux, get\_data\_flux, factor\_rsp} + +This function returns a structure with three array fields, +{\tt bin\_lo}, {\tt bin\_hi} and {\tt value}: +\begin{verbatim} +hist_index = integer index of spectrum in internal list + s.bin_lo = bin left edge [Angstrom] + s.bin_hi = bin right edge [Angstrom] + s.value = bin value [photons/sec/cm^2] +\end{verbatim} +Use this function to load the convolved model flux for data set +{\tt hist\_index} into \slang\ array variables. + +The value returned by \verb|get_convolved_model_flux| is +\begin{equation} + F(h) = \int dE R(h,E) S(E) +\end{equation} +where the integral extends over the full energy range, ensuring +that the instrumental redistribution is fully accounted for. + +Keep in mind that, when the RMF is not unit-normalized, the +value computed by \verb|eval_flux| may not be directly +comparable with the integral of $S(E)$ over the bin-width. In +such cases, one may wish to consider using \verb|factor_rsp| to +factor the RMF into a unit-normalized redistribution function +and a wavelength-dependent normalization factor. This +normalization factor might then be shifted into the ARF. + +For example: +\begin{verbatim} + rmf = load_rmf ("un_normalized_rmf.fits"); + arf = load_arf ("arf.fits"); + + % factor out a normalized RMF: + new_arf_index = factor_rsp (rmf); + + % shift the norm factor into the ARF: + factor = get_arf (new_arf_index); + arf_struct = get_arf (arf); + arf_struct.value *= factor.value; + put_arf (arf, arf_struct); +\end{verbatim} + +\end{isisfunction} + +\begin{isisfunction} +{get\_cfun} %name +{get the y-values of the differential fit-function} %purpose +{y = get\_cfun (x\_array)} %usage +{eval\_fun, fit\_fun} + +Given an array of x-coordinate values {\tt x\_array}, this function returns +an array containing the corresponding (unbinned) values of the currently +defined fit-function. See also {\tt [o]plot} +\begin{verbatim} +Example: + x = [8.5 : 10.2 : 0.001]; % define an x-grid + y = get_cfun (x); % get function values + + oplot(x, get_cfun(x)); % another usage example +\end{verbatim} + +Note that, if the current fit-function evaluates differently for +different datasets, it is necessary to specify the dataset index +to use when evaluating the fit-function. Do this by setting the +\verb|Isis_Active_Dataset| index before calling \verb|eval_fun|. +\end{isisfunction} + +\begin{isisfunction} +{get\_cfun2} %name +{Evaluate a differential fit-function on a user-defined grid} %purpose +{y = get\_cfun2 (handle, x, [, params])} %usage +{get\_cfun, fit\_fun, eval\_fun2, fitfun\_handle, list\_par} + +Use \verb|get_cfun2| to evalute a particular fit-function on +a particular wavelength grid using a given vector of +function parameters. The fit-function to be evaluated may be +specified by name (\verb|"voigt"|), by reference +(\verb|&voigt|) or by giving the handle returned by +\verb|fitfun_handle|. +\begin{verbatim} +Example: + e = [0.9:1.1:1.e-3]; % define a grid + + % define parameters [norm, energy, fwhm, vtherm] + pars = [1.0, 1.0, 0.02, 1.e3]; + + % evaluate the function giving its name + y = get_cfun2 ("voigt", _A(e), pars); + + plot(e, reverse(y)); +\end{verbatim} +For repetitive function evaluations it is somewhat more +efficient to refer to the function using a handle +(e.g. see \verb|eval_fun2|). + +The function parameters should be given in the order in which +they are listed by \verb|list_par|. If the specified +fit-function has no parameters, the corresponding argument may be +omitted or may be either \verb|NULL| or an array of length +zero. +\end{isisfunction} + +\begin{isisfunction} +{get\_fit\_fun} %name +{Get the current fit-function definition} %purpose +{s = get\_fit\_fun ()} %usage +{fit\_fun, get\_par\_info, get\_par, get\_params, get\_fun\_components} + +If no fit-function has been defined, this function returns NULL. + +\begin{verbatim} +For example: + + isis> get_fit_fun; + NULL + isis> fit_fun ("gauss(1) + poly(1)"); + isis> s = get_fit_fun(); + isis> print(s); + gauss(1) + poly(1) + isis> +\end{verbatim} + +\end{isisfunction} + +\begin{isisfunction} +{get\_fun\_components} %name +{Get the names of the components of the current fit-function} %purpose +{names[] = get\_fun\_components ()} %usage +{get\_fit\_fun, fit\_fun, get\_par\_info, get\_par, get\_params, get\_fun\_params} + +If no fit-function has been defined, this function returns NULL. +For example: +\begin{verbatim} + isis> fit_fun ("gauss(1) + wabs(1)*mekal(1) + gauss(1)"); + isis> s=get_fun_components(); + isis> print(s); + "gauss(1)" + "mekal(1)" + "wabs(1)" +\end{verbatim} + +This function can be used in scripts together with other other +information retrieval functions to automatically access all +details about the current fit function. Continuing the example, +one might do something like: + +\begin{verbatim} + isis> p = get_params (get_fun_params(s[0])); + isis> p; + Struct_Type[3] + isis> print(p[0]); + name = gauss(1).area + index = 1 + value = 1 + min = -1.79769e+308 + max = 1.79769e+308 + freeze = 0 + tie = 0 + is_a_norm = 1 + fun = NULL +\end{verbatim} + +\end{isisfunction} + +\begin{isisfunction} +{get\_fun\_params} %name +{get the parameter indices for a given fit-function} %purpose +{y = get\_fun\_params ("gauss(1)")} %usage +{fit\_fun, get\_params, set\_params} + +For example: +\begin{verbatim} + fit_fun ("gauss(1) + poly(1)"); + isis> p = get_fun_params ("poly(1)"); + isis> print(p); + 4 + 5 + 6 + isis> v = get_params(p); + isis> print(v[0]); + name = poly(1).a0 + index = 4 + value = 1 + min = -1.79769e+308 + max = 1.79769e+308 + freeze = 0 + tie = 0 + is_a_norm = 1 + fun = NULL +\end{verbatim} + +\end{isisfunction} + +\begin{isisfunction} +{get\_kernel} %name +{Determine the fit-kernel assigned to a dataset} %purpose +{s = get\_kernel (hist\_index)} %usage +{load\_kernel, print\_kernel,set\_kernel, list\_kernels} + +Note that the value returned by this function is accurate only +after the kernel has been assigned and the current fit-function +has been evaluated at least once. + +If the fit-kernel is uninitialized, an error will be generated. If +the fit-kernel has been initialized, but has been changed since +the last time the fit-function was evaluated, the value returned +by this function will not reflect the change. +\end{isisfunction} + +\begin{isisfunction} +{get\_model\_counts} %name +{load binned model values into a \slang\ structure} %purpose +{Struct\_Type = get\_model\_counts(hist\_index)} %usage +{get\_data\_counts} + +This function returns a structure with three array fields, +{\tt bin\_lo}, {\tt bin\_hi} and {\tt value}: +\begin{verbatim} +hist_index = integer index of spectrum in internal list + s.bin_lo = bin left edge [Angstrom] + s.bin_hi = bin right edge [Angstrom] + s.value = bin value [counts] +\end{verbatim} +Use this function to load the binned model counts for data set +{\tt hist\_index} into \slang\ array variables. + +The model counts are computed using +\begin{equation} + C(h) = B(h) + t \int dE {\cal F}\left(R(h,E),A(E),S(E)\right) +\end{equation} +where $B(h)$ is the background spectrum, $t$ is the exposure +time, ${\cal F}$ is the fit-kernel, $R(h,E)$ is the RMF, $A(E)$ +is the ARF and $S(E)$ is the model for the incident photon +spectrum. Note that the model includes any background +contribution which has been assigned. +\end{isisfunction} + +\begin{isisfunction} +{get\_model\_flux} %name +{load binned model values into a \slang\ structure} %purpose +{Struct\_Type =~get\_model\_flux~(hist\_index)} %usage +{get\_data\_flux, factor\_rsp} + +This function returns a structure with three array fields, +{\tt bin\_lo}, {\tt bin\_hi} and {\tt value}: +\begin{verbatim} +hist_index = integer index of spectrum in internal list + s.bin_lo = bin left edge [Angstrom] + s.bin_hi = bin right edge [Angstrom] + s.value = bin value [photons/sec/cm^2] +\end{verbatim} +Use this function to load the binned model flux for data set +{\tt hist\_index} into \slang\ array variables. + +The value returned by \verb|get_model_flux| is +\begin{equation} + F(h) = \int dE S(E) +\end{equation} +where the integral extends over the energy width of bin $h$. + +\end{isisfunction} + +\begin{isisfunction} +{get\_num\_pars} %name +{get the number of parameters in the current fit model} %purpose +{n = get\_num\_pars ()} %usage +{get\_par, set\_par, list\_par, save\_par, get\_num\_pars, get\_par\_info} +This function is useful in scripts which may need to loop over +all parameters of the current model. +For example, to print information for each fit parameter, use: +\begin{verbatim} + variable n, i; + + n = get_num_pars (); + _for (1, n, 1) + { + i = (); + print(get_par_info (i)); + } +\end{verbatim} +\end{isisfunction} + +\begin{isisfunction} +{get\_par} %name +{get the value of a fit parameter} %purpose +{par = get\_par (idx)} %usage +{set\_par, list\_par, save\_par, , get\_num\_pars, get\_par\_info, get\_fit\_fun} +Given the index ({\tt idx}) of a fit parameter, one can retrieve its +value in a \slang\ variable. The indices of current fit parameters +may be determined using {\tt list\_par}. + +One can also refer to parameters by name: +\begin{verbatim} + x = get_par ("gauss(1).area"); +\end{verbatim} +\end{isisfunction} + +\begin{isisfunction} +{get\_params} %name +{Copy fit-parameter information into an array of structs} %purpose +{Struct\_Type[] = get\_params ([list])} %usage +{set\_params, set\_par, get\_fit\_fun} + +This function returns an array of structs: +\begin{verbatim} +isis> fit_fun ("gauss(1)"); +isis> list_par; +gauss(1) + idx param tie-to freeze value min max + 1 gauss(1).area 0 0 1 0 0 + 2 gauss(1).center 0 0 12 0 0 + 3 gauss(1).sigma 0 0 0.025 0 0 +isis> x=get_params; +isis> print(x[2]); + name = gauss(1).sigma + index = 3 + value = 0.025 + min = -1.79769e+308 + max = 1.79769e+308 + freeze = 0 + tie = 0 + is_a_norm = 0 + fun = NULL +\end{verbatim} + +\end{isisfunction} + +\begin{isisfunction} +{get\_par\_info} %name +{get all information on a fit parameter} %purpose +{s = get\_par\_info (idx)} %usage +{get\_num\_pars, get\_par, set\_par, list\_par, save\_par, get\_fit\_fun} +Given the index ({\tt idx}) of a fit parameter, one can retrieve +the associated information from the internal parameter table; this +information is returned as fields of a \slang\ structure. +The indices of current fit parameters +may be determined using {\tt list\_par}. +For example: +\begin{verbatim} +isis> s=get_par_info(2); +isis> print(s); + name = gauss(1).center + index = 2 + value = 16.0269 + min = 15.95 + max = 16.03 + freeze = 1 + tie = 0 + fun = NULL +\end{verbatim} +If non-NULL, the \verb|fun| parameter contains the expression string specified +by \verb|set_par_fun|. + +One can also refer to parameters by name: +\begin{verbatim} + x = get_par_info ("gauss(1).area"); +\end{verbatim} +\end{isisfunction} + +\begin{isisfunction} +{ifit\_fun} %name +{define a fit function with interactive prompting for parameters} %purpose +{ifit\_fun ("function\_string")} %usage +{fit\_fun, plot\_bin\_density, get\_cfun} + +This function reads cursor positions from an existing bin-{\it density} plot +of a data-set and uses those coordinates to compute initial guesses for +parameters of the specified function. +\begin{verbatim} +Example: + plot_bin_density; % MUST plot bin-density to use ifit_fun + ignore ([1:12]); % ignore all data, then next step will + % notice a single region for fitting + xnotice(1, 6,7); % select the data interval for fitting + xrange(6,7); % set the plot x-limits to the same interval + yrange(y1,y2); % set the plot y-limits appropriately + plot_data_flux (1); + % point and click to define fit params + ifit_fun("Lorentz(1) + Lorentz(2) + poly(1)"); + + eval_flux; % evaluate the model using those params + oplot_convolved_model_flux(1); % over-plot the model +\end{verbatim} +\end{isisfunction} + +\begin{isisfunction} +{ignore} %name +{Ignore a wavelength range when fitting} %purpose +{ignore (hist\_index\_list [, lambda\_lo, lambda\_hi])} %usage +{ignore\_en, notice, xnotice, exclude, include} + +{\tt hist\_index\_list} may be either a single histogram index or an integer +array of indices. All data bins are noticed by default. If either of the +wavelength range arguments are missing, the limiting value is taken from the +input data. Therefore, omitting both range arguments ignores the entire +wavelength range. + +\begin{verbatim} +Example: + ignore ([1:4]); % ignore data sets 1,2,3,4 + ignore ([2:4], 10, 11); % ignore 10 <= lambda < 11 for + % data sets 2,3 and 4. + ignore ([ [1:4], [6:8] ]); % ignore data sets 1-4 and 6-8 +\end{verbatim} + +Note that when fitting data using an ARF and RMF the RMF is used +to determine which model bins contribute to the noticed data bins. +Use \verb|ignore_en| to ignore an energy range in keV. + +\end{isisfunction} + +\begin{isisfunction} +{ignore\_en} %name +{Ignore an energy range when fitting} %purpose +{ignore\_en (hist\_index\_list [, E\_lo, E\_hi])} %usage +{ignore, notice\_en, xnotice\_en, exclude, include} + +This is an alternate form of the \verb|ignore| function that +takes an energy range in keV instead of a wavelength range. +See \verb|ignore| for details. + +\end{isisfunction} + +\begin{isisfunction} +{ignore\_list} %name +{Ignore a list of bins when fitting} %purpose +{ignore\_list (hist\_index, list)} %usage +{ignore, notice\_list, xnotice, exclude, include} + +This is an alternate form of the \verb|ignore| function that +takes a list of bin indices instead of a wavelength range. +For example: +\begin{verbatim} + % to ignore bins with < 10 counts + d = get_data_counts(1); + ignore_list (1, where(d.value < 10.0)); +\end{verbatim} +Note that the list of bin indices refers to the internal +data which is stored in increasing wavelength order. + +See \verb|ignore| for details. + +\end{isisfunction} + +\begin{isisfunction} +{include} %name +{Include a list of datasets in the fit} %purpose +{include (data\_list)} %usage +{exclude, ignore, notice\_en, xnotice\_en} + +See \verb|exclude| for details. + +\end{isisfunction} + +\begin{isisfunction} +{list\_fit\_methods} +{List the currently defined fit methods} +{list\_fit\_methods} +{load\_fit\_method, load\_fit\_statistic, add\_slang\_statistic} + +\end{isisfunction} + +\begin{isisfunction} +{list\_free} +{List all free parameters} +{list\_free ([arg])} +{list\_par, set\_par, get\_par} + +The optional argument is used to redirect the output. If +\verb|arg| is omitted, the output goes to \verb|stdout|. If +\verb|arg| is of type \verb|Ref_Type|, it the output string is +stored in the referenced variable. If \verb|arg| is a file name, +the output is stored in that file. If \verb|arg| is a file +pointer (\verb|File_Type|) the output is written to the +corresponding file. + +This function lists all free fit parameters; it is equivalent +to \verb|list_par(1)|. See \verb|list_par| for details. + +\end{isisfunction} + +\begin{isisfunction} +{list\_functions} +{List the currently defined fit functions} +{list\_functions} +{add\_compiled\_function, add\_slang\_function, del\_function} + +The generated listing gives the name of each function. + +\begin{verbatim} +Example: +isis> list_functions; +Lorentz bin_width egauss pileup +Powerlaw blackbody gauss poly +isis> +\end{verbatim} + +See \S\ref{chap:xspec-module}) for information on accessing +\xspec\ source models. +\end{isisfunction} + +\begin{isisfunction} +{list\_kernels} %name +{list the available fit-kernels} %purpose +{list\_kernels} %usage +{set\_kernel, get\_kernel, load\_kernel} + +\begin{verbatim} +Example: +isis> list_kernels; +"pileup" +"std" +\end{verbatim} +\end{isisfunction} + +\begin{isisfunction} +{list\_par} %name +{list current fit function and parameters} %purpose +{list\_par ([arg])} %usage +{list\_free, edit\_par, set\_par, get\_par, save\_par, set\_par\_fun} + +The optional argument is used to redirect the output. If +\verb|arg| is omitted, the output goes to \verb|stdout|. If +\verb|arg| is of type \verb|Ref_Type|, it the output string is +stored in the referenced variable. If \verb|arg| is a file name, +the output is stored in that file. If \verb|arg| is a file +pointer (\verb|File_Type|) the output is written to the +corresponding file. + +The parameter listing looks like this: +\begin{verbatim} +gauss(1) + poly(1) + idx param tie-to freeze value min max + 1 gauss(1).area 0 0 103.6 0 0 + 2 gauss(1).center 0 0 12.1 10 13 + 3 gauss(1).sigma 0 0 0.022 0.001 0.1 + 4 poly(1).a0 0 0 1.2e4 0 0 + 5 poly(1).a1 0 1 0 0 0 + 6 poly(1).a2 0 1 0 0 0 +\end{verbatim} + +The first line defines the form of the fit-function. The parameter index +{\tt idx} may be used to refer to individual fit parameters (see {\tt +set\_par}). {\tt freeze = 1 (0)} indicates that the corresponding parameter +value is frozen (variable). If two parameter values are tied together, the +connection is indicated in the {\tt tie-to} column. For example, if +parameter 1 has {\tt tie-to = 5}, that means the value of parameter 1 is +tied to the value of parameter 5; if parameter 5 changes, parameter 1 will +follow the change exactly. If {\tt min=max=0}, the corresponding parameter +value is unconstrained. + +In input parameter files (see \verb|load_par|), lines beginning +with a `\verb|#|' are mostly ignored and may be used to include +comments. Exceptions to this rule are ``special'' comment +lines which are used to support additional functionality such +as, e.g. writing some parameters as functions of other +parameters (see \verb|set_par_fun|). Note that, aside from +these special cases, comment lines are not loaded by +\verb|load_par| and will not be preserved if file is later +overwritten by \verb|save_par|. + +\end{isisfunction} + +\begin{isisfunction} +{lmdif} %name +{Variant of Levenberg-Marquardt minimization algorithm} %purpose +{set\_fit\_method ("lmdif")} %usage +{marquardt, minim, subplex, set\_fit\_method} + +The \verb|lmdif| Levenberg-Marquardt algorithm is the default +minimization algorithm used in fitting models to data. This +algorithm was derived under the assumption that the function to +be minimized is the Chi-square fit-statistic. For details on +the derivation, see e.g. Bevington and Robinson (1992). + +The only optional parameter is the relative error tolerance +used to determine whether or not the algorithm has converged. +For help, use: +\begin{verbatim} +set_fit_method ("lmdif;help"); +\end{verbatim} + +\end{isisfunction} + +\begin{isisfunction} +{load\_conf} %name +{Load a 2D chi-square map from a FITS file} %purpose +{Struct\_Type = load\_conf (file)} %usage +{conf\_map\_counts, save\_conf, plot\_conf} +\index{Confidence Limits!loading 2D Maps} + +This function reads a 2D confidence map from a FITS file +previously created by \verb|save_conf|. + +For example, +\begin{verbatim} + % Create and save a confidence map: + map = conf_map_counts (px, py); + save_conf (map, "map.fits"); + % reload the map: + copy = load_conf ("map.fits"); +\end{verbatim} +See \verb|conf_map_counts| for details. + +\end{isisfunction} + +\begin{isisfunction} +{load\_fit\_method} %name +{load a user-defined fit-method} %purpose +{status = load\_fit\_method ("library.so", "name")} %usage +{set\_fit\_method, add\_to\_isis\_module\_path} +\index{User-defined!minimization algorithm} + +See \verb|math/marq.c| in the \isisx distribution for an +example of how to implement a user-defined fit-method. +To add a new method called {\tt newfit} which has been +compiled into a shared library (e.g. {\tt libnewfit.so}), +use +\begin{verbatim} + ret = load_fit_method ("libnewfit.so", "newfit"); +\end{verbatim} + +The return value is (0/-1) to indicate success/failure. +\end{isisfunction} + +\begin{isisfunction} +{load\_fit\_statistic} %name +{load a user-defined fit-statistic} %purpose +{status = load\_fit\_statistic ("library.so", "name")} %usage +{set\_fit\_statistic, add\_to\_isis\_module\_path, add\_slang\_statistic} +\index{User-defined!fit-statistic (compiled)} + +To add a new method called {\tt newstat} which has been +compiled into a shared library (e.g. {\tt libnewstat.so}), +use +\begin{verbatim} + ret = load_fit_statistic ("libnewstat.so", "newstat"); +\end{verbatim} + +The return value is (0/-1) to indicate success/failure. +\end{isisfunction} + +\begin{isisfunction} +{load\_kernel} %name +{load a user-defined fit-kernel} %purpose +{ret = load\_kernel ("library\_name", "init\_name" [, "init\_args"])} %usage +{set\_kernel, print\_kernel, list\_kernels, add\_to\_isis\_module\_path} +\index{User-defined!fit-kernel} + +See \verb|src/pileup_kernel.c| in the \isisx distribution for an +example of how to implement a user-defined fit-kernel. +Assuming such a fit-kernel has been implemented with an +initialization function called {\tt my\_kernel\_init} and +compiled into a shared library (e.g. {\tt libmy\_fit\_kernel.so}), +the user-defined fit-kernel may be dynamically linked to \isisx +by using + +\begin{verbatim} + ret = load_kernel ("libmy_fit_kernel.so", "my_kernel_init"); +\end{verbatim} + +The return value is (0/-1) to indicate success/failure. The +optional string argument provides a mechanism to supply parameters +which may be required at the time of the kernel's initialization. +\end{isisfunction} + +\begin{isisfunction} +{load\_par} %name +{load fit function and parameters from a file} %purpose +{load\_par ("filename")} %usage +{list\_par, save\_par, edit\_par, set\_par, get\_par} +Use this function to define a fit-function and its parameter values +by reading an ASCII file. See {\tt list\_par} for file format details. +\end{isisfunction} + +\begin{isisfunction} +{Lorentz} %name +{Lorentzian line profile function} %purpose +{Lorentz(id)} %usage +{gauss, voigt, poly, delta, bin\_width, bin\_center} + +The {\tt id} parameter identifies a particular instance of a Lorentzian +profile; multiple instances are allowed in a single fit. The function value +assigned to each bin is the area under the Lorentzian curve which lies +inside the bin: +\begin{equation} +{\rm Lorentz}(x_a,x_b) = {A \over \pi} + \int_{x_a}^{x_b} \D x~ + { {\Gamma/2} \over { \left(x - x_0\right)^2 + + \left(\Gamma/2\right)^2 } } +\end{equation} +where $A$ is the total area (e.g. photons/s/cm${}^2$) under the Lorentzian centered +at $x_0$ with full-width at half-maximum $\Gamma$. +\end{isisfunction} + +\begin{isisfunction} +{marquardt} %name +{Levenberg-Marquardt minimization algorithm} %purpose +{set\_fit\_method ("marquardt")} %usage +{lmdif, minim, subplex, set\_fit\_method} + +The \verb|lmdif| Levenberg-Marquardt algorithm is the default +minimization algorithm used in fitting models to data. This +algorithm was derived under the assumption that the function to +be minimized is the Chi-square fit-statistic. For details on +the derivation, see e.g. Bevington and Robinson (1992). + +The algorithm supports several optional parameters: +\begin{verbatim} + __Option__ __Default__ __Purpose__ + max_loops 50 Max number of iterations + tol 1.e-4 Fractional chisqr acceptance tolerance + delta 1.e-6 Initial numerical derivative step size +jump_factor 10.0 Lambda adjustment factor +\end{verbatim} + +Other than \verb|max_loops|, these parameters normally +need not be changed. +\end{isisfunction} + +\begin{isisfunction} +{minim} %name +{Variant of Nelder-Mead Simplex minimization algorithm} %purpose +{set\_fit\_method ("minim")} %usage +{subplex, lmdif, marquardt, set\_fit\_method} + +This is the \verb|MINIM| algorithm from the Applied Statistics +Journal of the Royal Statistical Society. For details, see +Nelder \& Mead, The Computer Journal, Jan 1965. The code was +obtained from \verb|http://lib.stat.cmu.edu/apstat/47|. + +To see a list of optional parameters, use +\begin{verbatim} + set_fit_method ("minim;help"); +\end{verbatim} + +\end{isisfunction} + +\begin{isisfunction} +{Minimum\_Stat\_Err} +{Defines the minimum valid uncertainty for counts data} +{(intrinsic global variable)} +{load\_data, define\_counts, define\_flux, fit\_counts, fit\_flux} + +When input data values are to be treated as counts, isis +attempts to validate the uncertainty values, requiring them all +to be greater than or equal to \verb|Minimum_Stat_Err|, where +\verb|Minimum_Stat_Err| has a default value of 1. + +For example, defining a single-bin counts dataset with has +bin value \verb|1.e-5| and uncertainty \verb|1.e-8|: +\begin{verbatim} +isis> define_counts (1.0, 2.0, 1.e-5, 1.e-8); +1 +isis> print(get_data_counts(1).err); +1 +\end{verbatim} +Note that isis replaced the \verb|1.e-8| uncertainty value +because it was inconsistent with default expectations for this +kind of data. + +To force isis to retain positive counts-uncertainty values +smaller than unity, define a minimum (positive) allowable uncertainty +value using \verb|Minimum_Stat_Err|: +\begin{verbatim} +isis> Minimum_Stat_Err=1.e-20; +isis> define_counts (1.0, 2.0, 1.e-5, 1.e-8); +2 +isis> print(get_data_counts(2).err); +1e-08 +\end{verbatim} +Here, isis kept the \verb|1.e-8| uncertainty value. + +When input data is to be treated as flux, this kind of +filtering does not take place: +\begin{verbatim} +isis> define_flux (1, 2, 1.e-5, 1.e-8); +1 +isis> print(get_data_flux(1).err); +1e-08 +\end{verbatim} +Uncertainties for flux values must be positive. + +\end{isisfunction} + +\begin{isisfunction} +{notice} %name +{Notice a wavelength range when fitting} %purpose +{notice (hist\_index\_list [, lambda\_lo, lambda\_hi])} %usage +{notice\_en, ignore, xnotice, exclude, include} + +Because all data bins in all data sets are noticed by default, +this function is most useful when some datasets or wavelength +ranges have been previously {\tt ignore}ed. One can notice a +particular wavelength range and simultaneously ignore wavelengths +outside that range using {\tt xnotice} (for ``exclusive-notice''). +If either of the wavelength range arguments are missing, the +limiting value is taken from the input data; therefore, omitting +both range values is equivalent to noticing the entire wavelength +range. + +Note that when fitting data using an ARF and RMF, the RMF is used to +determine which model bins contribute to the noticed data bins. +\end{isisfunction} + +\begin{isisfunction} +{notice\_en} %name +{Notice an energy range when fitting} %purpose +{notice\_en (hist\_index\_list [, E\_lo, E\_hi])} %usage +{notice, ignore\_en, xnotice\_en, exclude, include} + +This is an alternate form of the \verb|notice| function that +takes an energy range in keV instead of a wavelength range. +See \verb|notice| for details. +\end{isisfunction} + +\begin{isisfunction} +{notice\_list} %name +{Notice a list of bins when fitting} %purpose +{notice\_list (hist\_index, list)} %usage +{notice, ignore\_list, xnotice, exclude, include} + +This is an alternate form of the \verb|notice| function that +takes a list of bin indices instead of a wavelength range. +For example: +\begin{verbatim} + % to notice bins with > 10 counts + d = get_data_counts(1); + ignore(1); + notice_list (1, where(d.value > 10.0)); +\end{verbatim} +Note that the list of bin indices refers to the internal +data which is stored in increasing wavelength order. + +See \verb|notice| for details. + +\end{isisfunction} + +\label{pileup-help} +\begin{isisfunction} +{pileup} %name +{Pileup kernel used to model photon pileup in CCDs} %purpose +{set\_kernel (data\_index, "pileup[;option=value;...]")} %usage +{set\_kernel, fit\_fun} + +The pileup kernel includes the effects due to event pileup within +a single CCD frame-time and is described in detail in Davis +(2001). + +Valid options for the pileup kernel include: +\begin{verbatim} + nterms=value Max number of piled photons + fracexpo=value Fraction exposure for ARF + verbose=value verbose level +\end{verbatim} + +See the printed manual for a brief usage example. + +The pileup kernel provides an implementation of the +\verb|print_kernel| function to provide statistics on the nature +of the pileup fit. +\begin{verbatim} +For example: + + isis> print_kernel(1); + 1: 0.211913 0.929297 + 2: 0.029725 0.0673295 + 3: 0.00277968 0.00325211 + 4: 0.000194952 0.000117811 + 5: 1.09384e-05 3.41426e-06 + *** pileup fraction: 0.0707029 + +\end{verbatim} + +This says that 21\% of the frames contained a single photon in the +pileup region, 3 percent were contained 2 photons, etc. The 3rd +column indicates that 93 percent of the events were single photon +events, 7 percent were due to 2 photons, etc. + +The ACIS frame time in seconds is determined as follows. If +the \verb|EXPTIME| keyword is present in the spectrum file +header, its value is taken as the frame time; otherwise, if the +\verb|TIMEDEL| keyword is present, the frame time is taken as +\verb|TIMEDEL-0.04104|. If neither of these keywords is +present, the frame time is assumed to be 3.2 sec. Use +\verb|set\_frame\_time| to specify the frame time explicitly. + +The most computationally expensive aspect of the pileup model +involves convolution of real-valued sequences using the FFT. By +default, \isis\ uses an FFT algorithm which is very general but +not particularly fast. If you plan to make heavy use of the +pileup kernel, you may wish to obtain the specialized and +highly optimized FFT library, \verb|djbfft|, available from +\verb|http://cr.yp.to/djbfft.html|. To use this library, first +download and install it, then install \isis\ using the +\verb|--with-djbfft| configure option to supply the path to the +\verb|djbfft| library. Informal benchmarks on an AMD Athlon +cpu show that the pileup model using the \verb|djbfft| library +runs about five times faster than with the default FFT. + +\end{isisfunction} + +\begin{isisfunction} +{poly} %name +{polynomial fit function} %purpose +{poly(id)} %usage +{gauss, Lorentz, delta, bin\_width, bin\_center} + +The {\tt id} parameter identifies a particular instance of a polynomial; +multiple instances are allowed in a single fit. The function value assigned +to each bin is the area under the polynomial curve (of order $\le$ 2) which +lies inside the bin: +\begin{eqnarray} +{\rm poly}(x_a,x_b) &=& \int_{x_a}^{x_b} \D x~ + \left( a_0 + a_1 x + a_2 x^2\right) \nonumber\\ +&=& \delta x \left[ a_0 + {a_1 \over 2} \left(x_b + x_a\right) + + {a_2 \over 3} \left(x_b^2 + x_b x_a + x_a^2\right) \right] +\end{eqnarray} +where $\delta x \equiv x_b - x_a$. Notice that poly($x_a,x_b$) has units of +area (e.g. photons/s/cm${}^2/bin$), consistent with the definition of the other fit +functions {\tt gauss} and {\tt Lorentz}), so that $a_0$ has units of a +density (e.g. photons/s/cm${}^2$/\AA). By setting the coefficients appropriately, this +function can also serve as both a linear function and a constant. +\end{isisfunction} + +\begin{isisfunction} +{Powerlaw} %name +{power-law fit function} %purpose +{Powerlaw (id)} %usage +{gauss, Lorentz, add\_slang\_function, add\_compiled\_function} + +The {\tt id} parameter identifies a particular instance of a power-law; +multiple instances are allowed in a single fit. The function value assigned +to each bin is the area under the power-law curve which +lies inside the bin: +\begin{equation} +{\rm Powerlaw}(E_1,E_2) = \int_{E_1}^{E_2} \D e~A e^\alpha +\end{equation} +for $e$ in keV. Notice that Powerlaw($E_1,E_2$) has units of +area (e.g. photons/s/cm${}^2$/bin), consistent with the +definition of the other fit functions {\tt gauss} and {\tt +Lorentz}). +\end{isisfunction} + +\begin{isisfunction} +{plot\_conf} %name +{Plot 2D chi-square confidence contours} %purpose +{[o]plot\_conf (Struct\_Type[, line[, dchisqr\_array]])} %usage +{save\_conf, load\_conf, conf\_map\_counts, conf\_map\_flux} +\index{Confidence Limits!contour plots} + +By default, this function plots 1-sigma (68.3\%), 2-sigma (90\%) +and 3-sigma (99\%) chi-square confidence contours for 2 degrees of +freedom. To plot different contours, supply their delta-chisqr +values using the optional array argument. The first argument is +the return value of \verb|conf_map_counts| or +\verb|conf_map_flux|. If not otherwise specified, the axis limits +of these confidence contour plots are determined by the +\verb|Struct_Type| arguments used to generate the confidence map. +The current implementation does not support plotting sub-regions +of confidence maps. + +The first optional argument is a structure which specifies the +line style and has the form +\begin{verbatim} + line = struct {width, type}; +\end{verbatim} +See the \verb|linestyle| for a list of supported values of +\verb|line.type|. + +To overlay contours on an existing confidence contour plot, +use \verb|oplot_conf|. + +\begin{verbatim} +Example: + % generate conf. contours for dataset 1 + s1 = conf_map_counts (px, py); + + % generate conf. contours for dataset 2 + s2 = conf_map_counts (px2, py2); + + % provide X-Y ranges big enough to span both sets + % of contours + xrange (xmn, xmx); + yrange (ymn, ymx); + + % overlay conf. contours: + plot_conf (s1); + oplot_conf (s2); +\end{verbatim} + +\end{isisfunction} + +\begin{isisfunction} +{print\_kernel} %name +{Print kernel parameters} %purpose +{print\_kernel (hist\_index\_list)} %usage +{load\_kernel, set\_kernel} + +This function prints the current value of parameters associated with +the fit-kernel for each data-set in {\tt hist\_index\_list}. +Although the standard fit-kernel has no parameters, the +pileup-kernel does have a number of parameters. +User-defined fit kernels may provide this functionality as well -- +see \verb|src/pileup_kernel.c| in the \isisx distribution for an +implementation example. See also \S\ref{sec:pileup}. +\end{isisfunction} + +\begin{isisfunction} +{randomize} %name +{Randomize variable fit-parameters} %purpose +{randomize ([params])} %usage +{set\_par, get\_par, fit\_counts, fit\_flux, fit\_search} + +For each variable fit-parameter, this function randomly selects +a new value from within the specified \verb|[min, max)| range. +Note that if no parameter range has been specified, the +parameter is unconstrained and a random value will be selected +within the range $(-\infty,+\infty)$ -- this is probably not +what you want. + +\end{isisfunction} + +\begin{isisfunction} +{renorm\_counts} %name +{Automatically adjust fit normalization} %purpose +{s = renorm\_counts ([response\_type])} %usage +{renorm\_flux} + +This function automatically adjusts the normalization of the model +to improve the fit to the counts data. See {\tt fit\_counts} for +details. + +\end{isisfunction} + +\begin{isisfunction} +{renorm\_flux} %name +{Automatically adjust fit normalization} %purpose +{s = renorm\_flux ([response\_type])} %usage +{renorm\_counts} + +This function automatically adjusts the normalization of the model +to improve the fit to the flux-corrected data. See {\tt fit\_flux} for +details. + +\end{isisfunction} + +\begin{isisfunction} +{save\_conf} %name +{Save a 2D chi-square map as a FITS image} %purpose +{status = save\_conf (Struct\_Type, file)} %usage +{conf\_map\_counts, load\_conf, plot\_conf} +\index{Confidence Limits!saving 2D Maps} + +This function saves a 2D confidence map as a FITS image +with WCS coordinates defined using the corresponding +grid of fit-parameter values. The return value is 0 +for success, $<0$ for failure. + +For example, +\begin{verbatim} + % Create and save a confidence map: + map = conf_map_counts (px, py); + status = save_conf (map, "map.fits"); +\end{verbatim} +See \verb|conf_map_counts| for details. + +\end{isisfunction} + +\begin{isisfunction} +{save\_par} %name +{save fit function and parameters to a file} %purpose +{save\_par ("filename")} %usage +{load\_par, list\_par, edit\_par, set\_par, get\_par, fit\_search} + +The current fit function and parameter values may be saved in an ASCII file. +The allowed fit-ranges, and freeze/thaw/tie state is also saved. See {\tt +list\_par} for format details. {\tt load\_par} may be used to re-load the +file. + +If the function \verb|isis_save_par_hook| is defined in the +Global namespace, it will be called after the parameters have +been written out, but before the file is closed. The name of +the parameter file will be passed to \verb|isis_save_par_hook|, +which should return a string. If non-empty, this string will +be appended to the parameter file. + +This trivial example would record time of day in the parameter file: +\begin{verbatim} + public define isis_save_par_hook (filename) + { + return time(); + } +\end{verbatim} + +\verb|isis_save_par_hook| is probably most useful in conjunction +with \verb|fit_search| and \verb|fit_search_info|. In that case, +it might be used to automatically collect fit results into a table +with a custom format. + +For example: +\begin{verbatim} +define value_string (p) +{ + return sprintf ("%13.6e", p.value); +} + +define param_values_string () +{ + variable p, s; + + p = get_params (); + if (p == NULL) return ""; + + s = array_map (String_Type, &value_string, p); + + return strjoin (s, " "); +} + +public define isis_save_par_hook (fname) +{ + variable s, fp, info, stat = 0.0; + + % retrieve info on current best fit. + + info = fit_search_info(); + if (info != NULL) + stat = info.statistic; + + % generate a string 's' + + variable v = param_values_string (); + s = sprintf ("%s %12.4e %s\n", fname, stat, v); + + % append 's' to a log file + variable dir = path_dirname (fname); + + fp = fopen (dir + "/save_par.log", "a"); + if (fp == NULL) return NULL; + () = fputs (s, fp); + () = fclose (fp); + + % the returned string will be appended to the param file. + + return ""; +} +\end{verbatim} + +\end{isisfunction} + +\begin{isisfunction} +{set\_fit\_constraint} %name +{Impose a fit-constraint} %purpose +{set\_fit\_constraint (\&ref [, param\_names[])} %usage +{set\_fit\_method, set\_fit\_statistic, fit\_fun} + +In order to impose constraints on a fit in addition to the +usual bound-constraints on the fit-parameters (e.g. to impose +Lagrange multiplier constraints), one can provide a function +that modifies the fit-statistic computed during the fit. This +function may depend upon the fit statistic, any of the data +values, model parameters, or computed model values and may also +depend upon additional fit-parameters associated with the +constraint function itself. + +Use \verb|set_fit_constraint| to provide a reference to a +constraint function. The constraint function should accept +two parameters and should return a scalar-valued penalty. The +first input parameter is the scalar-valued fit statistic. The +second input parameter is an array of strings giving the names +of fit-parameters that are associated with the constraint +function. The parameters named in this array will appear as +fit-parameters of the form \verb|constraint(1).name|. If the +constraint function has no parameters, the second input +parameter should be \verb|NULL|. + +For example: +\begin{verbatim} + define a_constraint (stat, pars) + { + variable lam1, lam2, penalty; + + lam1 = par[0]; + lam2 = par[1]; + + penalty = lam1 * fcn1() + lam2 * fcn2(); + + return stat + penalty; + } + set_fit_constraint (&a_constraint, ["lambda1", "lambda2"]); +\end{verbatim} + +Note that, if the constraint function indicated in the first +argument is defined in the \verb|Global| namespace or in the +\verb|isis| namespace, it may not have the name +`\verb|constraint|'. The name `\verb|constraint|' may be used +only if the function is declared to be private: +\begin{verbatim} + private define constraint (stat, pars) + { + % ... compute the penalty ... + return stat + penalty; + } +\end{verbatim} + +To remove the fit-constraint use +\begin{verbatim} + set_fit_constraint (NULL); +\end{verbatim} + +\end{isisfunction} + +\begin{isisfunction} +{set\_fit\_method} %name +{select a fit-method} %purpose +{set\_fit\_method ("name[;options]")} %usage +{load\_fit\_method, set\_fit\_statistic, set\_fit\_constraint, randomize, lmdif, marquardt, minim, subplex} + +The \isisx distribution includes four fit methods, {\tt lmdif}, +{\tt marquardt}, {\tt minim} and {\tt subplex}. Control +parameters associated with the fit methods (such as convergence +tolerances) may be adjusted by supplying qualifers in the +method name string. For example, one might set the maximum +number of function evaluations performed by {\tt subplex} by +setting the {\tt maxnfe} option using +\begin{verbatim} + set_fit_method ("subplex;maxnfe=1000"); +\end{verbatim} +Similarly, one can limit the maximum number of iterations +performed by {\tt marquardt} using +\begin{verbatim} + set_fit_method ("marquardt;max_loops=100"); +\end{verbatim} +For a given fit method, the list of available control +parameters may be obtained using the {\tt help} qualifier: +\begin{verbatim} + set_fit_method ("marquardt;help"); +\end{verbatim} +Default parameter values may be restored using the {\tt +default} qualifier: +\begin{verbatim} + set_fit_method ("minim;default"); +\end{verbatim} + +Given a reasonably good initial guess and a +reasonably smooth $\chi^2$ space, {\tt lmdif} generally +converges to the best fit fairly quickly. In the ideal case, its +convergence is quadratic. In cases where the $\chi^2$ parameter +space is relatively complex (e.g. pileup), with many local minima, +{\tt minim} may be helpful because it is somewhat less likely to +become stuck in a local minimum. One possible strategy may +be to use {\tt minim} to find the neighborhood of the global +minimum and then use {\tt lmdif} to quickly find the best fit. + +In general, it is a good idea to thoroughly search the parameter +space to find the best fit. The {\tt randomize} function may be +helpful as part of a scripted Monte-Carlo search of the likely +parameter space (see also \verb|fit_search|). + +\end{isisfunction} + +\begin{isisfunction} +{set\_fit\_range\_hook} %name +{Control allowed fit-parameter value range} %purpose +{set\_fit\_range\_hook (\&function)} %usage +{set\_fit\_method, set\_fit\_constraint} + +When fitting models to data, fit-parameters may be constrained to +fall within a specified range. Each fit-method may supply its own +algorithm for enforcing these parameter ranges. To supply an +alternative algorithm, one can supply a S-Lang ``range-hook'' +function of the form +\begin{verbatim} + (new_par, new_min, new_max) = range_hook (par, min, max, idx) +\end{verbatim} +The arguments \verb|par|, \verb|min| and \verb|max| give +the parameter values and min/max ranges while the last +argument, \verb|idx|, gives the index of each parameter +as shown by \verb|list_par|. The \verb|idx| argument +is necessary because the range-hook is passed only those +parameters which are allowed to vary during the fit. +Frozen and tied parameters are not passed. + +To switch to the new range function, use e.g. +\begin{verbatim} + set_fit_range_hook (&range_hook); +\end{verbatim} +to revert to the default fit-range algorithm, use +\begin{verbatim} + set_fit_range_hook (NULL); +\end{verbatim} +Note that the range-hook function can also adjust the allowed +parameter value range (as well as the parameter value itself) +during the fit iteration. + +For example, the following function enforces the allowed +parameter range by setting out-of-range parameters to a randomly +chosen value from within the allowed range: +\begin{verbatim} +define enforce_ranges (p, pmin, pmax, idx) +{ + variable i, out_of_range; + out_of_range = where (p < pmin or pmax < p); + + foreach (out_of_range) + { + i = (); + p[i] = pmin[i] + urand() * (pmax[i] - pmin[i]); + } + + return (p, pmin, pmax); +} + +set_fit_range_hook (&enforce_ranges); +\end{verbatim} + +\end{isisfunction} + +\begin{isisfunction} +{set\_fit\_statistic} %name +{select a fit-statistic} %purpose +{set\_fit\_statistic ("name")} %usage +{load\_fit\_statistic, set\_fit\_constraint, set\_fit\_method} + +\isisx includes two built-in fit statistics, {\tt chisqr} and {\tt cash}. +User-defined fit-statistics are also supported and may be +implemented in {\tt C} or \slang. Control parameters associated +with the fit statistics (such as the chi-square weighting) may be +adjusted by supplying qualifers in the method name string. For a +given fit statistic, the list of available control parameters may +be obtained using the {\tt help} qualifier: +\begin{verbatim} + set_fit_statistic ("chisqr;help"); +\end{verbatim} +For example, one might set the variance used with the chi-square +statistic {\tt chisqr} by setting the {\tt sigma} option using +\begin{verbatim} + set_fit_statistic ("chisqr;sigma=gehrels"); +\end{verbatim} +Given data values $C_i \pm \sigma_i$ and model values $M_i$, +the chi-square statistic is defined to be +\begin{equation} + \chi^2 = \sum (C_i - M_i)^2 / \sigma_i^2 +\end{equation} +where the definition of $\sigma_i$ is one of the following: +\begin{verbatim} + data \sigma_i [default] + gehrels 1 + \sqrt(C_i + 0.75) + model \sqrt(M_i) + lsq 1 +\end{verbatim} +The Cash statistic is defined to be +\begin{equation} + S_{\rm cash} \equiv 2\sum_i (M_i - C_i) + + C_i \ln \left({C_i\over M_i}\right). +\end{equation} +See Cash (ApJ 228, 939) and the XSPEC manual for details. +\end{isisfunction} + +\begin{isisfunction} +{set\_function\_category} %name +{Specify the category to which a fit-function belongs} %purpose +{set\_function\_category (name, category)} %usage +{add\_slang\_function, add\_compiled\_function} + +Two categories of fit-functions are currently supported: +\begin{verbatim} + ___Category____ __Definition__ + ISIS_FUN_ADDMUL additive and multiplicative models + ISIS_FUN_OPERATOR operator or ``convolution'' models +\end{verbatim} +The default category is \verb|ISIS_FUN_ADDMUL|. + +See \verb|add_slang_function| and \verb|add_compiled_function| +for details on how to define the various types of +fit-functions. +\end{isisfunction} + +\begin{isisfunction} +{set\_kernel} %name +{Specify fit-kernel to use in forward-folding} %purpose +{set\_kernel (hist\_index\_list, "kernel\_name[;option=value;..]")} %usage +{load\_kernel, print\_kernel, get\_kernel, list\_kernels} + +The default fit kernel, equivalent to applying the ARF and RMF +in the usual way, is called "std". If the ARF and RMF are +unavailable, the response defaults to an identity matrix. The +pileup kernel, which includes the effects due to event pileup +within a single CCD frame-time and described in detail in Davis +(2001), is called "pileup" (See also \S\ref{sec:pileup}). + +The first argument, \verb|hist_index_list|, is a list of data +set indices which should use this kernel. The second argument, +\verb|kernel_name|, is the name of the kernel, which should be +\verb|<= 31| characters. This argument may also contain +values for kernel-specific options; for example: +\begin{verbatim} + set_kernel (3, "pileup;nterms=20;fracexpo=0.9"); +\end{verbatim} + +To determine what kernel options are supported, use the +\verb|help| option. For example: +\begin{verbatim} + isis> set_kernel (1, "pileup;help"); + Valid options for subsystem "pileup" include: + nterms=value Max number of piled photons + fracexpo=value Fraction exposure for ARF + verbose=value verbose level + isis> +\end{verbatim} + +Alternate fit-kernels may be defined by the user by creating a +shared library (.so file) with the necessary interface. This +shared library may be loaded using the {\tt load\_kernel} +function. + +\begin{verbatim} +Example: + % use the pileup kernel for data sets 4-6: + set_kernel ([4,5,6], "pileup"); + + % revert to the standard kernel for data set 5 + set_kernel (5, "std"); + set_kernel (5, NULL); % this form is also valid +\end{verbatim} + +\end{isisfunction} + +\begin{isisfunction} +{set\_par} %name +{set the value of a fit parameter} %purpose +{set\_par (idx, value [,freeze, [ min, max]])} %usage +{edit\_par, load\_par, get\_par, set\_par\_fun, set\_param\_expansion\_method} +\begin{verbatim} + idx parameter index or string identifier + value parameter value + freeze [optional] 1(0) if parameter is(is not) frozen + min, max [optional] allowed range for parameter value +\end{verbatim} + +If allowed ranges are not specified by the user or if +{\tt min}={\tt max}=0, the parameter value range is unlimited; +this is the default. + +One can also refer to parameters by name: +\begin{verbatim} + set_par ("gauss(1).area", 47.0); +\end{verbatim} + +Parameters may also be identified using expressions with +embedded wildcard characters. Both \slang\ regular expressions and +globbing expressions are supported. If a regular expression +string is to be used, then the string must either begin with +\verb|'^'| or end with \verb|'$'|. %$ +A globbing expression is frequently used for +matching filenames where \verb|`?'| represents a single +character and \verb|`*'| represents 0 or more characters. For +example, consider a model with many instances of similar +parameter names, such as: +\begin{verbatim} + "xpileup_n(1).G0_0" + "xpileup_n(1).G0_1" + "xpileup_n(2).G0_0" + "xpileup_n(2).G0_1" + . + . +\end{verbatim} +Using a globbing expression, one can use \verb|set_par| to set all +the \verb|G0_0| parameters to a specified value, e.g., +\begin{verbatim} + isis> set_par ("xpileup_n(?).G0_0", 0.5); + isis> set_par ("*.G0_1", 2.1); +\end{verbatim} + +\slang\ regular expression equivalents of the above are: +\begin{verbatim} + isis> set_par ("^xpileup_n(.)\\.G0_0$", 0.5); + isis> set_par (".*G0_1$", 2.1); +\end{verbatim} +(Note the presence of \verb|^| or \verb|$| %$ +to indicate the string represents a regular expression). + +Array arguments are supported. Consider: +\begin{verbatim} +isis> fit_fun ("gauss(1)"); +isis> list_par; +gauss(1) + idx param tie-to freeze value min max + 1 gauss(1).area 0 0 1 0 0 + 2 gauss(1).center 0 0 12 0 0 + 3 gauss(1).sigma 0 0 0.025 0 0 +isis> set_par ("gauss(1)", [ 2, 8, 0.03], [ 1, 0, 1], + [-1, 3, 0.004], [10, 20, 0.3]); +isis> list_par; +gauss(1) + idx param tie-to freeze value min max + 1 gauss(1).area 0 1 2 -1 10 + 2 gauss(1).center 0 0 8 3 20 + 3 gauss(1).sigma 0 1 0.03 0.004 0.3 +isis> +\end{verbatim} + +The function value may be specified as a function of other +fit-parameter values. For example: +\begin{verbatim} + set_par ("gauss(1).center", "gauss(2).center-3.0"); +\end{verbatim} +For details, see \verb|set_par_fun|. + +If parameter ranges have been specified and a value is provided +that falls outside those ranges, the default behavior is to +interrupt the S-Lang interpreter and print an error message. +For example: +\begin{verbatim} +isis> set_par (1, 1, 0, 0, 1); +isis> set_par (1,3); +*** Error: param 1 not set: value 3 lies outside [min, max] interval [0, 1] +S-Lang Error: Intrinsic Error: Error while executing _set_par +isis> +\end{verbatim} +In long-running scripts this behavior may be undesirable. An +alternative behavior may be specified by defining a function +named \verb|isis_set_par_hook| in the Global namespace. When +the value range error occurs, if this function exists, it is +passed a struct containing information on the relevant +parameter. This function may then return the struct after +modifying the range or value fields so that the +\verb|set_par()| operation can complete successfully. For +example, one might adjust the parameter range as follows: + +\begin{verbatim} +public define isis_set_par_hook (p) +{ + if (p.value <= p.min) p.min = 0.5 * p.value; + if (p.value >= p.max) p.max = 2.0 * p.value; + return p; +} +\end{verbatim} + +\end{isisfunction} + +\begin{isisfunction} +{set\_param\_default\_hook} %name +{Specify a function to set default parameter values and ranges} %purpose +{set\_param\_default\_hook (function\_name, hook [,args])} %usage +{add\_slang\_function, set\_function\_category} + +For a fit-function implemented in \slang, one can define +parameter defaults by providing an associated hook function. +The hook function should be a \slang\ function of the form +\begin{verbatim} + define param_default (i [,args]) +\end{verbatim} +where the first parameter is the zero-based array index and +\verb|args| is an optional list of user-defined arguments. The +optional arguments are specified when the hook function is +defined. The function must return four values, +\begin{verbatim} + return (value, freeze, min, max); +\end{verbatim} +providing defaults for (\verb|value|, \verb|freeze|, +\verb|min|, \verb|max|), in that order. Note that the parameter +range may be specified as \verb|NULL| to indicate that the +corresponding range is unlimited. + +To specify the hook function to be used with a given fit-function, +provide either a reference to the hook function (a \slang\ +\verb|Ref_Type|) +\begin{verbatim} + set_param_default_hook ("plaw", &plaw_param_default [,args]); +\end{verbatim} +or the name of the hook function (a \slang\ \verb|String_Type|) +\begin{verbatim} + set_param_default_hook ("plaw", "plaw_param_default" [,args]); +\end{verbatim} + +For a power-law fit-function, one might construct such a +parameter-default function as follows: +\begin{verbatim} + typedef struct {value, freeze, min, max} Param_Type; + + define set_default (x, value, freeze, min, max) + { + x.value = value; + x.freeze = freeze; + x.min = min; + x.max = max; + } + + variable Defaults = Param_Type[2]; + set_default (Defaults[0], 1.0, 0, 0.0, NULL); + set_default (Defaults[1], 0, 0, -5.0 , 1.0); + + define plaw_default_hook (i) + { + variable d = Defaults[i]; + return (d.value, d.freeze, d.min, d.max); + } + set_param_default_hook ("plaw", &plaw_default_hook); +\end{verbatim} +In this example, the normalization is constrained to be +positive, but has no default upper-limit. The power-law +exponent is, however, constrained to fall in the range [-5,1]. + +\end{isisfunction} + +\begin{isisfunction} +{set\_params} %name +{Reset all fit-parameter information using an array of structs} %purpose +{set\_params (Struct\_Type[])} %usage +{get\_params, set\_par} +See \verb|get_params| for more information. +\end{isisfunction} + +\begin{isisfunction} +{set\_par\_fun} %name +{Define a fit-parameter value using a function} %purpose +{set\_par\_fun (idx, expression\_string)} %usage +{set\_par, get\_par\_info, \_par, fit\_fun, conf\_map\_counts} +\index{Fitting!equality constraints} +\index{Fitting!inequality constraints} + +Fit parameters may be defined as functions of other fit-parameters +and may also depend on arbitrary functions. This has a number of +applications and can be used to couple fit-parameters in complex +ways, derive quantities of interest from fit-parameters, compute +confidence limits on derived quantities and also to introduce +arbitrary coordinate transformations in e.g. plots of confidence +contours. + +For example, to fit a sum of two Gaussians centered 4.3 Angstroms +apart use: +\begin{verbatim} +isis> fit_fun ("gauss(1) + gauss(2)"); +isis> set_par_fun ("gauss(2).center", "gauss(1).center + 4.3"); +isis> list_par; +gauss(1) + gauss(2) + idx param tie-to freeze value min max + 1 gauss(1).area 0 0 1 0 0 + 2 gauss(1).center 0 0 12 0 0 + 3 gauss(1).sigma 0 0 0.025 0 0 + 4 gauss(2).area 0 0 2.5 0 0 + 5 gauss(2).center 0 1 16.3 0 0 + #=> gauss(1).center + 4.3 + 6 gauss(2).sigma 0 0 0.025 0 0 +\end{verbatim} + +The constraint expression may also contain user-defined functions. +For example: +\begin{verbatim} + public define offset () + { + if (Isis_Active_Dataset == 2) + return 3.0; + else + return 2.5; + } + set_par_fun ("gauss(2).center", "gauss(1).center + offset()"); +\end{verbatim} +Here, the ISIS intrinsic variable \verb|Isis_Active_Dataset| is +used to define an offset which has the value 3.0 for dataset 2, +but is 2.5 for all other datasets. + +To delete the parameter-function definition, use +\begin{verbatim} + set_par_fun (index, NULL); +\end{verbatim} + +Note that \verb|list_par| shows that all parameters defined as +functions have \verb|freeze=1|. This does not mean that the +parameter's value is fixed during fit iteration. It merely +indicates that the parameter's value is derived from other +parameters and is not an independent variable during the fit. + +One can also use \verb|set_par_fun| to enforce inequality +constraints. The following example shows how to constrain one fit +parameter to be smaller than another: + +\begin{verbatim} + % Define a do-nothing fit function with a single parameter + define one_fit (lo, hi, par) + { + return 1.0; + } + add_slang_function ("one", "c"); + + % Include this do-nothing function in your spectral model + fit_fun ("one(1) * phabs(1) * (mekal(1) + mekal(2))"); + + % With this model, we have + % param 1 = c (the `dummy parameter') + % param 4 = kT_1 + % param 10 = kT_2 + + % Now, introduce the inequality constraint + % to require param 4 <= param 10: + + set_par_fun ("mekal(2).kT", "mekal(1).kT + one(1).c^2"); +\end{verbatim} + +With this definition, the value of parameter 10 will be computed +by adding a non-negative value, \verb|c^2|, to parameter 4, thereby +enforcing the constraint. + +Although one can also refer to parameters by index: +\begin{verbatim} + set_par_fun ("gauss(1).area", "_par(4) + _par(1)^2"); +\end{verbatim} +using names of the form \verb|fname(i).parname| is more robust, +because such names are unaffected by changes in the parameter +indexing. + +\end{isisfunction} + +\begin{isisfunction} +{subplex} %name +{Subplex minimization algorithm} %purpose +{set\_fit\_method ("subplex")} %usage +{lmdif, marquardt, minim, set\_fit\_method, set\_fit\_constraint} + +The subplex algorithm is a minimization algorithm used in +fitting models to data. A variant of the Nelder-Mead simplex +method, it is a general method for solving unconstrained +optimization problems. It is well suited for optimizing +objective functions that are noisy or are discontinuous at the +solution. The implementation used in \isis\ came from the +Netlib repository; for details, see \verb|www.netlib.org|. + +The algorithm has a number of options: +\begin{verbatim} + __Option__ __Default__ __Purpose__ + maxnfe 128N Max number of function evaluations + tol 1.e-4 Relative error tolerance + scale_factor 1.0 Parameter scale factor +\end{verbatim} + +By default, the \verb|maxnfe| is set to \verb|128N| where +\verb|N| is the number of number of fit parameters. + +\verb|scale_factor| is used to scale and provide initial +stepsizes for the simplex. For each parameter, the scale is +defined to be \verb|scale_factor| multiplied by the initial +parameter value. + +\verb|tol| is the relative error tolerance on the parameter +value. +\end{isisfunction} + +\begin{isisfunction} +{thaw} %name +{thaw one or more fit parameters} %purpose +{thaw (par\_list)} %usage +{freeze, tie, untie} +\index{Fitting!thawing parameters} + +{\tt par\_list} may be either a single parameter index or an integer array +of indices. Thawing a parameter allows the parameter to vary when searching +for the best fit to the data. +\begin{verbatim} + thaw(3); % thaw param 3 + thaw([1:4]); % thaw params 1,2,3,4 +\end{verbatim} + +One can also refer to parameters by name: +\begin{verbatim} + thaw ("gauss(1).area", "gauss(2).area"); +\end{verbatim} + +\end{isisfunction} + +\begin{isisfunction} +{tie} %name +{tie one or more fit parameters to a single parameter} %purpose +{tie (par, par\_list)} %usage +{untie, freeze, thaw} +\index{Fitting!tieing parameters} + +{\tt par\_list} may be either a single parameter index or an integer array +of indices. Tieing one or more parameters to a variable parameter causes the +tied parameters to vary as one. Tieing to a frozen parameter has the +opposite effect. +\begin{verbatim} + tie(2,3); % tie param 3 to the value of param 2 + tie(5, [1:4]); % tie params 1,2,3,4 to the value of + % param 5 +\end{verbatim} + +One can also refer to parameters by name: +\begin{verbatim} + tie ("gauss(1).area", "gauss(2).area"); +\end{verbatim} + +\end{isisfunction} + +\begin{isisfunction} +{untie} %name +{untie one or more fit parameters} %purpose +{untie (par\_list)} %usage +{tie, freeze, thaw} +{\tt par\_list} may be either a single parameter index or an +integer array of indices. +\begin{verbatim} + untie(2); % untie param 2 + untie([1:4]); % untie params 1,2,3,4 +\end{verbatim} + +One can also refer to parameters by name: +\begin{verbatim} + untie ("gauss(2).area"); +\end{verbatim} +\end{isisfunction} + +\begin{isisfunction} +{voigt} %name +{Voigt profile function} %purpose +{voigt(id)} %usage +{gauss, Lorentz} + +The Voigt profile is the convolution of the natural resonance +profile of an emitted line with the Maxwellian speed +distribution. The natural resonance profile is a Lorentzian +with full-width at half maximum, $\Gamma/4\pi$. The Maxwellian +speed distribution is a Gaussian with velocity width $v_0 = +(2kT/m)^{1/2}$, where $m$ is the ion mass and $T$ is the +temperature. + +The fit parameters are +\begin{verbatim} + norm [photons/s/cm^2] Normalization + energy [keV] Line-center energy + fwhm [keV] Gamma + vtherm [km/s] Maxwellian velocity width=sqrt(2kT/m) +\end{verbatim} + +The Voigt profile is unit-normalized so that the value of +the \verb|norm| parameter gives the area under the profile. + +Note that the \verb|fwhm| parameter name is misleading -- +\verb|fwhm|$=\Gamma$ but the true FWHM is $\Gamma/2\pi$. + +\end{isisfunction} + +\begin{isisfunction} +{xnotice} %name +{Notice a wavelength range when fitting} %purpose +{xnotice (hist\_index\_list [, lambda\_lo, lambda\_hi])} %usage +{ignore, notice} +{\tt hist\_index\_list} may be either a single histogram index or an +integer array of indices. +This command is equivalent to first ignoring the entire wavelength +range and then noticing the specified range. +\begin{verbatim} + % first ignore all bins, then notice the specified range. + isis> ignore(idx); + isis> notice(idx, lambda_lo, lambda_hi); +\end{verbatim} +Note that only the histograms explicitly mentioned in {\tt +hist\_index\_list} are affected; to ignore other histograms, use {\tt +ignore}. + +Note that when fitting data using an ARF and RMF, the RMF is used +to determine which model bins contribute to the noticed data bins. + +\end{isisfunction} + +\begin{isisfunction} +{xnotice\_en} %name +{Notice an energy range when fitting} %purpose +{xnotice\_en (hist\_index\_list [, E\_lo, E\_hi])} %usage +{xnotice, ignore\_en, notice\_en} + +This is an alternate form of the \verb|xnotice| function that +takes an energy range in keV instead of a wavelength range. +See \verb|xnotice| for details. + +\end{isisfunction} + +\begin{isisfunction} +{yshift} %name +{Kernel for introducing a wavelength shift} %purpose +{set\_kernel (data\_index, "yshift")} %usage +{set\_kernel, fit\_fun} + +This kernel adds a wavelength shift (not a Doppler shift!) to +the model counts spectrum. Any associated background spectrum +is not shifted. The size of the shift is a fittable parameter. +Aside from the wavelength shift, this kernel performs the same +forward-fold computation as the standard kernel. +Flux-correction is not supported. + +This kernel was added primarily to support analysis of +dispersed spectra of marginally resolved point sources using +\verb|combine_datasets|. + +\end{isisfunction} + +\section{Low-level PGPLOT Interface} +\label{chap:pgplot-module} + +\isisx provides provides interactive access to most of the +functions in the \pgplot\ subroutine library. Using \pgplot\ +functions directly provides finer control over plot formatting and +makes it possible to create complex, specialized plots. + +\section{Custom Plot Examples} + +The following script generates a plot called {\tt custom1.ps} (see Figure +\ref{fig:custom1}) + +\begin{figure}[ht] +\putfig{figures/custom1} +\caption{An example of plot customization using \pgplot\ functions with +\isisx intrinsic functions} +\label{fig:custom1} +\end{figure} + +\verbatiminput{scripts/custom1.sl} + +\clearpage + +The following script generates a plot called {\tt contour.ps} (see Figure +\ref{fig:custom1}) + +\begin{figure}[ht] +\putfig{figures/contour} +\caption{An example of contour plotting using \pgplot\ functions} +\label{fig:contour} +\end{figure} + +\verbatiminput{scripts/contour.sl} + +\clearpage + +\section{Supported Functions} + +The \pgplot\ functions are described in detail in the \pgplot\ +documentation; see +\begin{verbatim} + http://astro.caltech.edu/~tjp/pgplot/index.html +\end{verbatim} +Here, we provide a condensed listing of the supported +functions and the \slang\ syntax with which they may be invoked. + +Almost all of the functions implemented here have exactly the same +number of arguments as the \pgplot\ library functions. The main +difference is that array size arguments are not needed. Another +difference is that temporary workspace arguments are handled +transparently. For example, the library function {\tt PGHI2D} takes +12 arguments. The corresponding +\slang\ intrinsic \_pghi2d takes only 9 arguments since the 2 of the 12 +specify the dimensions of a 2D array, and 1 is a temporary workspace argument. + +Finally, some functions that return values via the argument list are +implemented as \slang\ functions that return multiple values. An example +of this is \_pgcurs which is prototyped in {\sc Fortran} as: +\begin{verbatim} + PGCURS (X, Y, CH) +\end{verbatim} +but used in \slang\ as: +\begin{verbatim} + (x,y,ch) = _pgcurs (); +\end{verbatim} +Also see \_pgband for another example. + +\vfill +\newpage + +\begin{center} +\begin{tabular}{|l|p{2.5in}|p{2.25in}|} +\hline +Name & Description & \slang\ Syntax \\ +\hline +\hline +PGARRO & draw an arrow & +\_pgarro (xfrom, yfrom, xto, yto) \\ +PGASK & control new page prompting & +\_pgask (flag) \\ +PGAXIS & draw an axis & +\_pgaxis (opt, x1, y1, x2, y2, v1, v2, step, nsub, dmajl, dmajr, fmin, disp, orient) \\ +PGBAND & read cursor position, with anchor & +\_pgband (mode, posn, xref, yref, x, y, \&xout, \&yout, \&ch) \\ +PGBBUF & begin batch of output (buffer) & +\_pgbbuf () \\ +PGBIN & histogram of binned data & +\_pgbin (x, data, center) \\ +PGBOX & draw labeled frame around viewport & +\_pgbox (xopt, xtic, nx, yopt, ytic, ny) \\ +PGCIRC & draw a circle, using fill-area attributes & +\_pgcirc (x, y, a) \\ +PGCLOS & close the selected graphics device & +\_pgclos () \\ +PGCONB & contour map of a 2D data array with blanking & +\_pgconb (data, i1, i2, j1, j2, c, tr, blank) \\ +PGCONF & fill between two contours & +\_pgconf (data, i1, i2, j1, j2, c\_lo, c\_hi, tr) \\ +PGCONL & label contour map of a 2D data array drawn by PGCONT & +\_pgconl (data, i1, i2, j1, j2, c, tr, label, intval, minint) \\ +PGCONS & contour map of a 2D data array (fast algorithm) & +\_pgcons (data, i1, i2, j1, j2, c, tr, nc) \\ +PGCONT & contour map of a 2D data array & +\_pgcont (data, i1, i2, j1, j2, c, tr, nc) \\ +PGCTAB & install the color table to be used by PGIMAG & +\_pgctab (l, r, g, b, contra, bright) \\ +PGCURS & read cursor position & +(x, y, ch) = \_pgcurs () \\ +PGDRAW & draw a line from the current pen position to a point & +\_pgdraw (x,y)) \\ +PGEBUF & end batch of output (buffer) & +\_pgebuf () \\ +PGEND & close all open graphics devices & +\_pgend () \\ +PGENV & set window and viewport and draw labeled frame & +\_pgenv (xmin, xmax, ymin, ymax, just, axis) \\ +PGERAS & erase all graphics from current page & +\_pgeras () \\ +PGERR1 & horizontal or vertical error bar & +\_pgerr1 (dir, x, y, e, t) \\ +PGERRB & horizontal or vertical error bar & +\_pgerrb (x, y, e, t) \\ +PGERRX & horizontal error bar & +\_pgerrx (x1, x2, y, len) \\ +PGERRY & vertical error bar & +\_pgerry (x, y1, y2, len) \\ +PGETXT & erase text from graphics display & +\_pgetxt () \\ +PGGRAY & gray-scale map of a 2D data array & +\_pggray (data, i1, i2, j1, j2, fg, bg, tr) \\ +PGHI2D & cross-sections through a 2D data array & +\_pghi2d (data[][], ix1, ix2, iy1, iy2, x[], ioff, bias, center) \\ +PGHIST & histogram of unbinned data & +\_pghist (dmin, dmax, nbins, flag) \\ +PGIDEN & write username, date, and time at bottom of plot & +\_pgiden () \\ +PGIMAG & color image from a 2D data array & +\_pgimag (data, i1, i2, j1, j2, a1, a2, tr) \\ +PGLAB & write labels for x-axis, y-axis, and top of plot & +\_pglab (xlabel, ylabel, toplabel) \\ +PGLCUR & draw a line using the cursor & +\_pglcur (x, y) \\ +PGLDEV & list available device types on standard output & +\_pgldev () \\ +PGLINE & draw a polyline (curve defined by line-segments) & +\_pgline (x, y) \\ +PGMOVE & move pen (change current pen position) & +\_pgmove (x, y) \\ +PGMTXT & write text at position relative to viewport & +\_pgmtxt (s, f, g, h, t) \\ +PGNCUR & mark a set of points using the cursor & +\_pgncur (x, y, symbol) \\ +\hline +\end{tabular} + +\begin{tabular}{|l|p{2.5in}|p{2.25in}|} +\hline +Name & Description & \slang\ Syntax \\ +\hline +\hline +PGOLIN & mark a set of points using the cursor & +\_pgolin (x, y, symbol) \\ +PGOPEN & open a graphics device & +id = \_pgopen (dev) \\ +PGPAGE & advance to new page & +\_pgpage () \\ +PGPANL & switch to a different panel on the view surface & +\_pgpanl (ix, iy) \\ +PGPAP & change the size of the view surface & +\_pgpap (w, a) \\ +PGPNTS & draw several graph markers, not all the same & +\_pgpt (x, y, symbol) \\ +PGPOLY & draw a polygon, using fill-area attributes & +\_pgpoly (x, y) \\ +PGPT & draw several graph markers & +\_pgpt (symbol) \\ +PGPTXT & write text at arbitrary position and angle & +\_pgptxt (x, y, angle, just, text) \\ +PGQAH & inquire arrowhead style & +(fill\_style, angle, barb\_fraction) = \_pgqah () \\ +PGQCH & inquire character height & +h = \_pgqch () \\ +PGQCIR & inquire color index range & +(lo, hi) = \_pgqcir () \\ +PGQCLP & inquire clipping status & +clp = \_pgqclp () \\ +PGQCOL & inquire color capability & +(ci1, ci2) = \_pgqcol () \\ +PGQHS & inquire hatching style & +(angle, sep, phase) = \_pgqhs () \\ +PGQITF & inquire image transfer function & +itf = \_pgqitf () \\ +%%% PGQTXT & Get bounding box for text at arbitrary position and angle & +%%% (xbox, ybox) = \_pgqtxt (x, y, angle, just, text) \\ +PGQCF & inquire character font & +cf = \_pgqcf () \\ +PGQCI & inquire color index & +ci = \_pgqci () \\ +PGQCS & inquire character height in a variety of units & +(xch, ych) = \_pgqcs (units) \\ +PGQFS & inquire fill-area style & +fs = \_pgqfs () \\ +PGQID & inquire current device identifier & +id = \_pgqid () \\ +PGQINF & inquire \pgplot\ general information & +value = \_pgqinf (item) \\ +PGQLS & inquire line style & +ls = \_pgqls () \\ +PGQLW & inquire line width & +lw = \_pgqlw () \\ +PGQNDT & inquire number of available device types & +n = \_pgqndt () \\ +PGQPOS & inquire current pen position & +(x, y) = \_pgqpos () \\ +PGQTBG & inquire text background color index & +tbci = \_pgqtbg () \\ +PGQVP & inquire viewport boundary coordinates & +(xmin, xmax, ymin, ymax) = \_pgqvp (units) \\ +PGQVSZ & inquire size of view surface & +(x1, x2, y1, y2) = \_pgqvsz (units) \\ +PGQWIN & inquire window boundary coordinates & +(xmin, xmax, ymin, ymax) = \_pgqwin () \\ +PGRECT & draw a rectangle, using fill-area attributes & +\_pgrect (xmin, xmax, ymin, ymax) \\ +PGSAH & set arrow-head style & +\_pgsah (fs, angle, style) \\ +PGSAVE & save PGPLOT attributes & +\_pgsave () \\ +PGSCF & set character font & +\_pgscf (ci) \\ +PGSCH & set character height & +\_pgsch (ch) \\ +PGSCI & set color index & +\_pgsci (ci) \\ +PGSCR & assign RGB color to color index & +\_pgscr (ci, r, g, b) \\ +PGSCL & scroll window & +\_pgscrl (dx, dy) \\ +PGSCRN & assign RGB color to color index by name & +ier = \_pgscrn (ci, name) \\ +PGSFS & set fill-area style & +\_pgsfs (fs) \\ +PGSHLS & assign HLS color to color index & +\_pgshls (ci, h, l, s) \\ +PGSHS & set hatching style & +\_pgshs (ang, s, p) \\ +PGSITF & set image transfer function & +\_pgsitf (i) \\ +PGSLCT & select an open graphics device & +\_pgslct (id) \\ +\hline +\end{tabular} + +\begin{tabular}{|l|p{2.5in}|p{2.25in}|} +\hline +Name & Description & \slang\ Syntax \\ +\hline +\hline +PGSLS & set line style & +\_pgsls (ls) \\ +PGSLW & set line width & +\_pgslw (lw) \\ +PGSTBG & set text background color index & +\_pgstbg (ci) \\ +PGSUBP & subdivide view surface into panels & +\_pgsubp (nx, ny) \\ +PGSVP & set viewport (normalized device coordinates) & +\_pgsvp (xmin, xmax, ymin, ymax) \\ +PGSWIN & set window & +\_pgswin (xmin, xmax, ymin, ymax) \\ +PGTBOX & draw frame and write (DD) HH MM SS.S labeling & +\_pgtbox (xopt, tic, nx, yopt, ytic, ny) \\ +PGTEXT & write text (horizontal, left-justified) & +\_pgtext (x, y, text) \\ +PGUNSA & restore PGPLOT attributes & +\_pgunsa () \\ +PGUPDT & update display & +\_pgupdt () \\ +PGVSIZ & set viewport (inches) & +\_pgvsiz (xmin, xmax, ymin, ymax) \\ +PGVSTD & set standard (default) viewport & +\_pgvstd () \\ +PGWNAD & set window and adjust viewport to same aspect ratio & +\_pgwnad (xmin, xmax, ymin, ymax) \\ +\hline +\end{tabular} +\end{center} + +\chapter{The XSPEC Module} +\label{chap:xspec-module} + +\isisx is distributed with a +module\footnotemark (see \verb|modules/xspec|) which provides +access to all of the additive, multiplicative and convolution models in +\xspec\ (Arnaud 1996). Table models and \xspec-style local models +are also supported. This module makes it possible to fit +data using familiar \xspec\ models and to easily manipulate the +output values (e.g. computed spectra) using \slang\ array-based +mathematical operators. + +Because most of the code for this module is automatically +generated from files in the \xspec\ distribution, the model +parameter names and the order of parameters should exactly +match the \xspec\ interface (although the \isisx \verb|norm| +parameter always comes first in the parameter list). For +details on how to automatically generate new module source code +in order to match an upgrade of \xspec\ that introduces new +source functions, see \verb|modules/xspec/src/README.code|. + +\footnotetext{On systems with ELF support this module may be +included via dynamic linking, making it possible to install and +use \isisx without first installing \xspec. For convenience, +the module may also be statically linked, eliminating the need +to first {\tt import} the module before using the +\xspec\ fit-functions.} + +\section{Installation and Setup} + +See \verb|INSTALL| and \verb|modules/xspec/README| for detailed instructions +on how to compile and install the module. + +If the module is dynamically linked, it will be automatically +imported when any of the module functions is used for the first +time. One can also import it explicitly using +\begin{verbatim} + require ("xspec"); +\end{verbatim} +When the module is statically linked, the S-Lang preprocessor +symbol \verb|XSPEC_IS_STATIC| is defined. To write scripts +which work independent of how the XSPEC module is linked, one +can use +\begin{verbatim} + #ifdef XSPEC_IS_STATIC + require ("xspec"); + #endif +\end{verbatim} +This will insure that no attempt is made to import the \xspec\ +module on systems where the module is unavailable. + +\section{Imported Functions} + +{\it This section is incomplete -- many more functions are +included in the XSPEC module than are described here. Use +\verb|list_functions| to get a list of function names. +The XSPEC documentation provides parameter definitions and +more complete documentation.} + +See the \xspec\ documentation for references and a more complete +description of these functions. + +\begin{isisfunction} +{add\_atable\_model} +{Define an additive table-model} +{add\_atable\_model ("filename", "modelname")} +{add\_etable\_model, add\_mtable\_model} +This function loads an XSPEC-format additive table model +and defines a fit-function based on that table, using +parameter names defined in the \verb|NAME| column of the file. +Multiple +instances of each table-model may be fitted simultaneously. +\begin{verbatim} +Example: + add_atable_model ("atable.fits", "bshock"); + fit_fun ("bshock(1) + bshock(2)"); +\end{verbatim} +\end{isisfunction} + +\begin{isisfunction} +{add\_etable\_model} +{Define an exponential table-model} +{add\_etable\_model ("filename", "modelname")} +{add\_atable\_model, add\_mtable\_model} +This function loads an XSPEC-format exponential table model +and defines a fit-function based on that table, using +parameter names defined in the \verb|NAME| column of the file. Multiple +instances of each table-model may be fitted simultaneously. +\begin{verbatim} +Example: + add_etable_model ("atable.fits", "my_exp"); + fit_fun ("my_exp(1)*mekal(1)"); +\end{verbatim} +\end{isisfunction} + +\begin{isisfunction} +{add\_mtable\_model} +{Define an multiplicative table-model} +{add\_mtable\_model ("filename", "modelname")} +{add\_atable\_model, add\_etable\_model} +This function loads an XSPEC-format multiplicative table model +and defines a fit-function based on that table, using +parameter names defined in the \verb|NAME| column of the file. Multiple +instances of each table-model may be fitted simultaneously. +\begin{verbatim} +Example: + add_mtable_model ("atable.fits", "my_mul"); + fit_fun ("my_mul(1)*mekal(1)"); +\end{verbatim} +\end{isisfunction} + +\begin{isisfunction} +{build\_xspec\_local\_models} +{Compile \xspec\ local models (xspec 12+ only)} +{build\_xspec\_local\_models ([dir [, pkg\_name]])}; +{load\_xspec\_local\_models} + +If no arguments are provided, this function will compile the +\xspec\ local models in the directory specified by the +\verb|LMODDIR| environment variable. Optionally, the directory +path and a package name may be provided. + +Use \verb|load_xspec_local_models| to import the spectral +models into isis. +\end{isisfunction} + +\begin{isisfunction} +{load\_xspec\_local\_models} +{Load \xspec\ local models} +{load\_xspec\_local\_models ( [dir [, pkg\_name]])} +{build\_xspec\_local\_models } + +\isis\ can use local models compiled for XSPEC. Any local +models available along path specified by the \verb|LMODDIR| +environment variable are automatically loaded at the time the +\xspec\ module is imported. Local models may also be loaded by +specifying the shared library directory and, optionally, the +associated package name. + +Defining this global variable: +\begin{verbatim} + public variable _xspec_module_verbose_link_errors=1; +\end{verbatim} +will cause \verb|load_xspec_local_models| to generate more +verbose error messages that may help diagnose certain +linking errors that may occur. + +\end{isisfunction} + +\begin{isisfunction} +{xspec\_abund} +{Specify the abundance table used by XSPEC models} +{status = xspec\_abund (name)} +{xspec\_xsect} +If this function is called with no name parameter, +the name of the current abundance table is returned. + +See the \xspec\ documentation for details +\end{isisfunction} + +\begin{isisfunction} +{xspec\_elabund} +{Retrieve XSPEC element abundances} +{abundance = xspec\_elabund (elname)} +{xspec\_xsect} +The element name should be specified using its chemical +abbreviation. Use \verb|xspec_abund| to specify an +abundance table. + +\end{isisfunction} + +\begin{isisfunction} +{xspec\_get\_cosmo} +{Specify the cosmological parameters used by XSPEC models} +{(H0, q0, lambda0) = xspec\_get\_cosmo();} +{xspec\_set\_cosmo} +The cosmological parameters are the Hubble constant (\verb|H0|), +the deceleration parameter (\verb|q0|) and the cosmological +constant (\verb|lambda0|). +See the \xspec\ documentation for details +\end{isisfunction} + +\begin{isisfunction} +{xspec\_gphoto} +{Compute mean photoelectric absorption cross-sections (Verner)} +{s = xspec\_gphoto (E1\_kev, E2\_kev, Z)} +{xspec\_phfit2, xspec\_photo} + +This function computes the mean photoelectric absorption cross +section (in cm$^2$) for an element with atomic number $Z$, by +averaging the value at energies \verb|E2_kev| and +\verb|E2_kev|. + +\end{isisfunction} + +\begin{isisfunction} +{xspec\_help} +{Display documentation for an XSPEC model} +{xspec\_help (model\_name [; method=])} +{apropos, help} + +The spectral model documentation for xspec12 is locally +available in either \verb|html| or \verb|pdf| format. +The \verb|method| qualifier may be used to select the +preferred file format and reader. This string +variable must have the structure +\begin{verbatim} + " ; " +\end{verbatim} +where \verb|file-format| is either \verb|pdf| or \verb|html|. +The \verb|%s| directive must appear in the +\verb|display-command| substring to indicate where the name of +the documentation file should be inserted. + +The environment variable \verb|XSPEC_MODULE_HELP| may also be +used to select the preferred file format and reader. + +\begin{verbatim} +EXAMPLE + +% To view html documentation with the web browser `firefox': + xspec_help ("powerlaw", method="html; firefox %s"); +or + setenv XSPEC_MODULE_HELP "html; firefox %s" + +% To view pdf documentation with the pdf reader `acroread': + XSPEC_MODULE_HELP = "pdf; acroread %s" +\end{verbatim} + +\end{isisfunction} + +\begin{isisfunction} +{xspec\_ionsneqr} +{Compute non-equilibrium ionization for a given Te, tau structure} +{Struct\_Type = xspec\_ionsneqr (T[], tau[])} +{xspec\_abund} + +This function provides an interface for the XSPEC subroutine +\verb|ionsneqr|. The input arrays should have the same length. +The return value is a structure of the form +\begin{verbatim} + struct {fout, ionel, ionstage} +\end{verbatim} +From the \verb|ionsneqr| source code documentation: + +\begin{verbatim} + Calculates ionization fractions fout at electron temperature + tmp(n) and ionization parameter tau(n), for electron + temperatures tmp given in a tabular form as a function of + ionization parameter tau. + + Input: tmp - temperatures (K) + tau - ionization timescales (cm^-3 s) + Output: fout - ionic concentrations + ionel - the element for each fout entry + ionstage - the ion stage for each fout entry + (ionel+1 = fully stripped) +\end{verbatim} + +\end{isisfunction} + +\begin{isisfunction} +{xspec\_phfit2} +{Compute partial photoelectric absorption cross-sections (Verner)} +{s = xspec\_phfit2 (nz, ne, is, e)} +{xspec\_gphoto, xspec\_photo} + +This function provides an interface for Dima Verner's phfit2 +subroutine. From the \verb|phfit2| source code: + +\begin{verbatim} + This subroutine calculates partial photoionization cross sections + for all ionization stages of all atoms from H to Zn (Z=30) by use of + the following fit parameters: + Outer shells of the Opacity Project (OP) elements: + Verner, Ferland, Korista, Yakovlev, 1996, ApJ, in press. + Inner shells of all elements, and outer shells of the non-OP elements: + Verner and Yakovlev, 1995, A&AS, 109, 125 + Input parameters: nz - atomic number from 1 to 30 (integer) + ne - number of electrons from 1 to iz (integer) + is - shell number (integer) + e - photon energy, eV + Output parameter: s - photoionization cross section, Mb + Shell numbers: + 1 - 1s, 2 - 2s, 3 - 2p, 4 - 3s, 5 - 3p, 6 - 3d, 7 - 4s. + If a species in the ground state has no electrons on the given shell, + the subroutine returns s=0. +\end{verbatim} + +\end{isisfunction} + +\begin{isisfunction} +{xspec\_photo} +{Compute mean photoelectric absorption cross-sections (BCMC)} +{photo = xspec\_photo (keV1, keV2, Z [, versn])} +{xspec\_gphoto} + +This function provides an interface to the \verb|photo.f| +subroutine distributed with xspec. From the source code: + +\begin{verbatim} + Cross-section data from Henke etal, Atomic Data and Nuclear Data Tables + vol 27, no 1, 1982. Fits mainly by Monika Balucinska-Church and Dan McCammon + "Photoelectric Absorption Cross Sections with Variable Abunances" + Ap.J. 400, 699 (1992) + + Arguments : + keV1 r i: Lower energy of bin in keV. + keV2 r i: Upper energy of bin in keV. + Z i i: Atomic number of element + versn i i: 2 == old Marr & West He x-section + 3 == new Yan et al. x-section + photo r r: Cross-section in cm**2 +\end{verbatim} + +\end{isisfunction} + +\begin{isisfunction} +{xspec\_set\_cosmo} +{Specify the cosmological parameters used by XSPEC models} +{xspec\_set\_cosmo(H0, q0, lambda0)} +{xspec\_get\_cosmo} +The cosmological parameters are the Hubble constant (\verb|H0|), +the deceleration parameter (\verb|q0|) and the cosmological +constant (\verb|lambda0|). +See the \xspec\ documentation for details +\begin{verbatim} +For example: + xspec_set_cosmo (75.0, 0.5, 0.7); +\end{verbatim} +\end{isisfunction} + +\begin{isisfunction} +{xspec\_xsect} +{Specify the photoionization cross-section table used by XSPEC models} +{status = xspec\_xsect (name)} +{xspec\_abund} +The available cross-section tables are +\verb|bcmc|, \verb|vern|, \verb|obcm|. +If this function is called with no name parameter, +the name of the current cross-section table is returned. + +See the \xspec\ documentation for details +\end{isisfunction} + +\begin{isisfunction} +{xspec\_xset} +{Set various XSPEC parameters} +{xspec\_xset (\"symbol\", \"value\")} +{xspec\_abund, xspec\_xsect} + +This function is equivalent to the \xspec\ \verb|xset| function. + +For example, to set the value of the \xspec\ parameter +\verb|NEIVERS| (which controls the atomic data used by the +various non-equilibrium ionization models), do +\begin{verbatim} + xspec_xset ("NEIVERS", "2.0"); +\end{verbatim} +See the \xspec\ documentation for details. +\end{isisfunction} + +\chapter{Customizing ISIS Configuration} +\label{chap:custom} + +The \verb|~/.isisrc| file allows individual users to customize +\isisx at run-time; a template configuration file called {\tt +isis.rc} is included with the distribution. This file is a \slang\ +script which is executed at \isisx startup and could, for example, +be used to automatically load a particular database or to +initialize some constants or other useful data structures. The +sample file explains how to set several \isisx intrinsic variables +to control some aspects of the program's operation (also see \S +\ref{sec:scripts}). + +Extensions which are to be made +available to all \isisx users at a particular site may be +initialized using the file {\tt etc/local.sl} in the \isisx source +directory. If this file exists, it is automatically loaded at +\isisx startup (before the user's {\tt .isisrc} is loaded). +Documentation for such local extensions may be provided in an +ascii file called {\tt local\_help.txt} in the same directory; the +format of this file should be the same as that of the {\tt +help.txt} file included in the \isisx distribution. If the file +{\tt local\_help.txt} exists, the interactive help system will +search it automatically. + +\section{Environment Variables Affecting ISIS} +\label{sec:env-var} + +Although the simplest configuration doesn't require setting any +environment variables, several environment variables are available to +help customize \isis (Table \ref{env-tbl}). Note that, because \slang\ +provides the ability to change environment variables of the isis process, it +is possible to change some of of the following values at run-time +(it is not useful to change those environment variables which are examined +only at \isisx startup). For example, the default editor can be changed at +run-time using the \slang\ function {\tt putenv}. To change the current +editor to {\tt emacs} without first exiting \isis, use +\begin{verbatim} + isis> putenv ("EDITOR=emacs"); +\end{verbatim} + +\begin{table}[ht] \caption{Environment Variables Affecting \isis} +\label{env-tbl} +\begin{tabular}{|l|p{0.8in}|p{3.2in}|} +\hline +\rule[-1mm]{0mm}{1mm} & & \hfill \\ + +{\sc ISIS\_SRCDIR} & Optional & +Provides the full path to the \isisx source code directory. +If the \isisx source-code directory is moved after \isisx is +compiled, use this environment variable to specify the new path.\\ + +{\sc ISIS\_HISTORY\_FILE} & Optional & +If GNU readline has been enabled (see \verb|set_readline_method|) +the cumulative history of interactive commands +will be saved in the file specified by this environment variable.\\ + +\rule[-1mm]{0mm}{1mm} & & \hfill \\ + +{\sc PGPLOT\_DIR} & {\it Required by \pgplot} & +Provides the path to the \pgplot font files ({\tt grfont.dat}, etc.)\\ + +\rule[-1mm]{0mm}{1mm} & & \hfill \\ +\hline +\rule[-1mm]{0mm}{1mm} & & \hfill \\ + +{\sc PGPLOT\_DEV} & Optional & +Specifies the default plot device. See the description of the \pgplot\ +function {\tt pgopen} for details. See also \verb|plot_device()|\\ + +{\sc PAGER} & Optional & +Specifies which pager program to use for browsing output text; +the default is {\tt more}. See the table notes below for more +information. \\ + +{\sc EDITOR} & Optional & +Specifies which editor to use for editing parameter tables; the default is +{\tt vi}. See the table notes below for more +information. \\ + +{\sc TMPDIR} & Optional & +If set, \isisx places temporary files in the specified directory, otherwise, +all temporary files are placed in the startup directory. \\ + +{\sc HEADAS} & {\it May be required to build the \xspec\ module} & +Provides the path to the \xspec\ installation; usually this is the +path to the architecture-specific subdirectory +in the HEASARC headas installation. \\ + +\rule[-1mm]{0mm}{1mm} & & \hfill \\ +\hline +\rule[-1mm]{0mm}{1mm} & & \hfill \\ + +{\sc ISIS\_LOAD\_PATH} & Optional & +\isisx searches this colon-separated list of directories when loading +\slang\ scripts. \\ + +{\sc SLANG\_LOAD\_PATH} & Optional & +\isisx searches this colon-separated list of directories when loading +\slang\ scripts.\\ + +{\sc ISIS\_MODULE\_PATH} & Optional & +\isisx searches this colon-separated list of directories when loading +dynamically linked modules (.so files). \\ + +{\sc SLANG\_MODULE\_PATH} & Optional & +\isisx searches this colon-separated list of directories when loading +dynamically linked modules (.so files). \\ + +{\sc LD\_LIBRARY\_PATH} & System specific & +This colon-separated list of directories is searched when loading +dynamically linked modules (.so files). \\ +\hline +\end{tabular} +\end{table} +\noindent{\sc Table Notes:}~\begin{list}{}{ + \setlength{\leftmargin}{1cm} + \setlength{\rightmargin}{1cm} + } +\item[{\sc PAGER}] \hfill \\ +Because the standard Unix {\tt more} pager program may not provide +sufficient flexibility, we recommend using a high quality pager program such +as {\tt most} which allows scrolling files forward, backward and even +horizontally; other good choices include {\tt less} and {\tt jed}. If {\sc +PAGER} is not set and {\tt more} is not found on the command search path, +some output browsing functions will not work properly. \\ + +\item[{\sc EDITOR}] \hfill \\ +If {\sc EDITOR} is not set and {\tt vi} is not found on the +command search path, the parameter editing functions will not work properly. +If {\tt emacs} is used, the {\tt emacsclient} feature +(of {\tt emacs}) may be used to avoid invoking a new {\tt emacs} process for +each edit; see the {\tt emacs} documentation for more details. \\ +\end{list} +\clearpage + +\section{ISIS Intrinsic Variables} +\label{sec:intrin-var} + +\isisx also defines a number of \slang\ intrinsic variables which +are used to control the behavior of various functions (Table +\ref{intrinv-tbl}). Their default values may be changed at any time by +changing the value of the variable -- such configuration changes always take +place instantly and do not require restarting \isisx or re-loading the +\verb|~/.isisrc| file. + +\begin{center} +\label{intrinv-tbl} %\caption{\isisx Intrinsic Variables} +\begin{tabular}{|l|c|p{3.2in}|} +\hline +\rule[-1mm]{0mm}{1mm} & & \hfill \\ +{\bf Variable} & {\bf Default Value} & {\bf Purpose} \\ +\rule[-1mm]{0mm}{1mm} & & \hfill \\ +\hline +\rule[-1mm]{0mm}{1mm} & & \hfill \\ +{\tt Ion\_Format} & {\tt FMT\_ROMAN} & Controls the print format +for ion names. Allowed values are {\tt FMT\_ROMAN}, {\tt FMT\_INT\_ROMAN}, +{\tt FMT\_CHARGE} \\ +{\tt Use\_Memory} & 1 & Controls run-time memory usage (see {\tt plasma} and +\S\ref{specdb-init}). If non-zero, most data tables will be loaded into memory +all at once. If zero, needed items from from large tables will be loaded +only when actually used.\\ +{\tt Incomplete\_Line\_List} & 1 & Controls the treatment of line emissivity +tables on input (see {\tt plasma}). The default probably need not be changed.\\ +{\tt Isis\_Active\_Dataset} & - & This variable contains the index of the +dataset for which the fit-function is currently being evaluated. This +intrinsic variable is primarily useful for writing user-defined fit-functions +which evaluate differently for different datasets.\\ +{\tt Isis\_Append\_Semicolon} & 0 & If non-zero, \isis\ will +automatically append a semicolon (;) to each input command line +in interactive mode. Otherwise, the user must type the semicolon +to mark the end of the command line.\index{{\tt Isis\_Append\_Semicolon}}\\ +{\tt Isis\_Eval\_Grid\_Method} & {\tt SEPARATE\_GRID} & +This sets the default evaluation grid type used when fitting +models to data. Supported grid types are {\tt MERGED\_GRID|SEPARATE\_GRID}. +For details, see {\tt set\_eval\_grid\_method}. +\index{{\tt Isis\_Eval\_Grid\_Method}}.\\ +{\tt Isis\_List\_Filenames} & 0 & If non-zero, \verb|list_data| will +list the spectrum filename and background filename for each +dataset, if any.\index{{\tt Isis\_List\_Filenames}}\\ +{\tt Isis\_Use\_PHA\_Grouping} & 0 & If non-zero, +\verb|load_data| will apply the channel grouping specified by the +\verb|GROUPING| column in the input PHA file. +\index{{\tt Isis\_Use\_PHA\_Grouping}}\\ +{\tt Ignore\_PHA\_Response\_Keywords} & 0 & If non-zero, +\verb|load_data| will ignore the \verb|RESPFILE| and +\verb|ANCRFILE| keywords in PHA file headers. +\index{{\tt Ignore\_PHA\_Response\_Keywords}}\\ +{\tt Isis\_Residual\_Plot\_Type} & - & This variable controls +the type of residuals generated by \verb|rplot_counts| and +\verb|rplot_flux|. Supported options are \verb|STAT|, +\verb|DIFF|, \verb|RATIO|, to generate $\Delta\chi^2$ +residuals, \verb|(data-model)| residuals and \verb|(data/model)| ratio plots.\\ +{\tt Label\_By\_Default} & 1 & Controls the labeling of spectrum plot axes. +If non-zero, plot axes are labeled automatically; otherwise, axes are not +labeled.\\ +{\tt Fit\_Verbose} & 0 & Controls the level of information printed during +iterative fitting of models to data. If zero, only the final +value of the fit-statistic is printed. If negative, no information is printed, +if positive extra information is printed. \\ +{\tt Isis\_Verbose} & 0 & Controls the general level of +verboseness. Larger positive values indicate increased verbosity. +A negative value silences all informational output except +messages reporting serious errors. \\ +{\tt Minimum\_Stat\_Err} & 0 & Used for validating statistical +uncertainties associated with input spectral data. When positive, this +value of this variable defines the smallest valid uncertainty for +a single data bin. If zero (the default), Poisson errors are +assumed.\\ +\hline +\end{tabular} +\vfill + +\begin{tabular}{|l|c|p{3.2in}|} +\hline +\rule[-1mm]{0mm}{1mm} & & \hfill \\ +{\bf Variable} & {\bf Default Value} & {\bf Purpose} \\ +\rule[-1mm]{0mm}{1mm} & & \hfill \\ +\hline +\rule[-1mm]{0mm}{1mm} & & \hfill \\ +{\tt Min\_Model\_Spacing} & 0.0 \AA & Sets the minimum wavelength +grid spacing +used when computing the spectral model $S(\lambda)$ for multi-order +spectral analysis. Use \verb|Min_Model_Spacing=0| (the default) to get the finest +allowed grid spacing (resolution set by the combination of all the ARF grids). +\index{Minimum wavelength spacing!see {{\tt Min\_Model\_Spacing}}}\\ +{\tt Remove\_Spectrum\_Gaps} & 0 & Used for validating the +histogram grid of the input spectrum. If zero (the default), \isisx +will refuse to read a spectrum which has ${\tt bin\_hi[i]} \not= {\tt bin\_lo[i+1]}$ +for any spectrum bin ``i''. If non-zero, such gaps will be +automatically removed by merging them into the neighboring bin.\\ +{\tt Verbose\_Fitsio} & 0 & Controls printing of FITSIO error messages. If +non-zero, FITSIO error messages will be printed when they occur.\\ +{\tt Rmf\_Grid\_Tol} & $10^{-4}$ & Controls the internal grid validity +checking. An error is generated when the +fractional error between the data, RMF and ARF grids +exceeds this value. To suppress such errors, set the tolerance to +a larger value.\\ +{\tt Rmf\_OGIP\_Compliance} & 2 & Controls the level of OGIP +standard compliance required of FITS RMF files. Setting +this variable to zero means that minimum standard compliance +is required.\\ +{\tt Xspec\_Module\_Help} & {\tt "pdf;xpdf \%s"} & Indicates +the preferred format for viewing XSPEC 12 model documentation. +Available formats are {\tt pdf} and {\tt html}. The environment +variable {\tt XSPEC\_MODULE\_HELP} may also be used to provide +the same information. +\\ +\hline +\end{tabular} +\end{center} + +\clearpage % force the table to be printed immediately + +\begin{thebibliography}{} +\label{chap:biblio} +%begin{latexonly} +\ifpdf + \pdfbookmark[-1]{Bibliography}{chap:biblio} +\fi +%end{latexonly} +\bibitem{arn96} Arnaud, K.A., 1996, Astronomical Data Analysis Software +and Systems V, eds. Jacoby G. and Barnes J., p17, ASP Conf. Series volume 101. + +\bibitem{bev92} Bevington, P.R., and Robinson, D.K., 1992, ``Data +Reduction and Error Analysis for the Physical Sciences'', 2ed, +(McGraw-Hill). + +\bibitem{dav01} Davis, J., 2001, ``Event Pileup in Charge Coupled +Devices'', Astrophysical Journal, submitted. + +% \bibitem{smi98} Smith, R., Brickhouse, N., Liedahl, D., \& Raymond, J., 1998 +% ``High Resolution X-Ray Spectroscopy: Issues for Creating an Atomic +% Database for a Collisional Plasma Spectral Emission Code'', +% in ``Science with XMM: The First XMM Workshop''. + +\bibitem{smi01}Smith, R. K., Brickhouse, N. S., Liedahl, D. A., \& +Raymond, J. C. 2001, Astrophysical Journal, 556, L91. + +\end{thebibliography} + +% +% Include index +% + +% \label{chap:index} gets defined by a `sed' script +% that edits manual.ind before latex is re-run to +% include the index +\printindex + +% +% Done +% +\end{document} diff --git a/doc/scripts/bgd_subtract.sl b/doc/scripts/bgd_subtract.sl new file mode 100644 index 0000000..ac34c49 --- /dev/null +++ b/doc/scripts/bgd_subtract.sl @@ -0,0 +1,21 @@ +public define backsub (s_idx, b_idx) +{ + variable s, b; + variable s_backscale, s_exposure, b_backscale, b_exposure; + variable scale; + + s = get_data_counts (s_idx); + b = get_data_counts (b_idx); + + s_backscale = get_data_backscale (s_idx); + b_backscale = get_data_backscale (b_idx); + + s_exposure = get_data_exposure (s_idx); + b_exposure = get_data_exposure (b_idx); + + scale = (s_backscale * s_exposure) / (b_backscale * b_exposure); + s.value -= b.value * scale; + s.err = sqrt (s.err^2 + (b.err * scale)^2); + + put_data_counts (s_idx, s.bin_lo, s.bin_hi, s.value, s.err); +} diff --git a/doc/scripts/contin.sl b/doc/scripts/contin.sl new file mode 100644 index 0000000..d91b9db --- /dev/null +++ b/doc/scripts/contin.sl @@ -0,0 +1,30 @@ + +plasma(aped); + +variable lo, hi, p, pid, ymax; + +pid = open_plot ("contin.ps/vcps"); +resize(15); + +(lo, hi) = linear_grid(1,20, 3000); +p = get_contin (lo, hi, 3.e6); + +print(p); + +ymax = max ([p.true, p.pseudo]); + +yrange (ymax*1.e-4, ymax); + +ylog; + +label ("Wavelength [Angstrom]", "log Flux [photon cm\\u3\\d s\\u-1\\d]", "T = 3.0e6 K"); +hplot (lo, hi, p.true); + +ohplot (lo, hi, p.pseudo); + +variable q; +q = get_contin (lo, hi, 3.e6, 1.0e-3, 8); % Contribution from Oxygen +ohplot (lo, hi, q.true); +ohplot (lo, hi, q.pseudo); + +close_plot (pid); diff --git a/doc/scripts/contour.sl b/doc/scripts/contour.sl new file mode 100644 index 0000000..c00c5f6 --- /dev/null +++ b/doc/scripts/contour.sl @@ -0,0 +1,88 @@ +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% PGPLOT has several contouring functions: +% +% PGCONB -- contour map of a 2D data array, with blanking +% PGCONF -- fill between two contours +% PGCONL -- label contour map of a 2D data array +% PGCONS -- contour map of a 2D data array (fast algorithm) +% PGCONT -- contour map of a 2D data array (contour-following) +% PGCONX -- contour map of a 2D data array (non rectangular) +% +% +% the corresponding ISIS wrappers are +% _pgconb, _pgconf, _pgconl, _pgcons, _pgcont +% +% At the moment, _pgconx isn't supported. + +typedef struct +{ + min, max, num +} +Param_Type; + +public define plot_contours (a, px, py, levels) +{ + % 1. define the plot coordinate system and draw the box + % 2. plotting contours one at a time allows coloring + % them individually (see _pgsci()). + + _pgenv (px.min, px.max, py.min, py.max, 0, 0); + _pgswin (1, px.num, 1, py.num); + + variable tr = [0, 1.0, 0, 0, 0, 1.0]; + variable i, n = length(levels); + + _for (0, n-1, 1) + { + i = (); + % negative number of contours means contour lines + % are drawn with the current line attributes + % (color index, style, width) + _pgcont (a, 1, 1, px.num, py.num, levels[i], tr, -1); + } +} + +public define fake_data (px, py) +{ + variable a = Float_Type [px.num, py.num]; + variable i, j, r, f; + + f = PI * py.max / px.max; + for (i = 0; i < px.num; i++) + { + for (j = 0; j < py.num; j++) + { + r = sqrt ( (i - px.num/2.0)^2 + (j - py.num/2.0)^2 ); + a[i,j] = r - 0.1 * px.num * (sin(i*f/(j+1.0)))^2; + } + } + return a; +} + +public define do_demo () +{ + variable px = @Param_Type; + variable py = @Param_Type; + + % Define axis ranges and resolution + px.min = 1.0; + px.max = 175.0; + px.num = 175; + + py.min = 1.0; + py.max = 175.0; + py.num = 175; + + % Define contour levels + variable levels = [0.0:50.0:5.0]; + + plot_contours (fake_data (px, py), px, py, levels); + _pglab ("X", "Y", "Pretty Contours"); + +} + +() = _pgopen ("contour.ps/vcps"); +_pgpap (4.0, 1.0); % 4 inches, aspect ratio = 1. +do_demo (); +_pgclos(); + diff --git a/doc/scripts/crude_dem.sl b/doc/scripts/crude_dem.sl new file mode 100644 index 0000000..612839a --- /dev/null +++ b/doc/scripts/crude_dem.sl @@ -0,0 +1,22 @@ + +plasma(aped); + +variable id=open_plot("crude_dem.ps/vcps"); +resize(15); + +variable k, t, em, i, flux_obs; + +% Fe strong XVII line at 15.014 Angstrom +k = where(el_ion(Fe,17) and wl(15.0,15.02)); +flux_obs = 1.0; + +t = 10.0^[5.8:7.5:0.01]; % define a Temperature grid +em = line_em (k,t); % get emissivity vs. temperature for + % line k +i = where(em > 0.0); +limits; +variable y = flux_obs / em[i]; +yrange (0.2*min(y), 10*min(y)); +label ("Temperature (K)", "EM (arbitrary units)", "Fe XVII 15.014 Angstrom"); +plot (t[i], y); % plot the ratio +close_plot(id); diff --git a/doc/scripts/custom1.sl b/doc/scripts/custom1.sl new file mode 100644 index 0000000..111cef4 --- /dev/null +++ b/doc/scripts/custom1.sl @@ -0,0 +1,52 @@ + +variable pha2_file; +pha2_file = _isis_srcdir + "/../isis-examples/data/acisf01318N003_pha2.fits.gz"; + +variable id = 10; +() = load_data (pha2_file); +variable pid = open_plot ("custom1.ps/vcps"); +resize(15); + +xrange(10,20); +plot_data_counts (id); + +% coordinates of region for inset plot: + +variable xmin, xmax, ymin, ymax; +xmin = 12.35; +xmax = xmin + 0.2; +ymin = 0.0; +ymax = 30.0; + +_pgsci (4); % Draw blue rectangle: +_pgsfs (2); +_pgrect (xmin, xmax, ymin, ymax); +_pgsfs (1); % restore default fill-area style + +_pgsci (4); % Draw blue arrow: +_pgsch (0.7); +_pgsah (1, 45.0, 0.3); % specify arrow-head shape +_pgarro (xmax, ymax, 15.9, 122); % from (x1,y1) to (x2,y2) +_pgsci (1); + % New viewport in normalized + % device coordinates: +_pgsvp (0.6, 0.8, 0.5, 0.8); % xleft, xright, ybot, ytop +_pgswin (xmin, xmax, ymin, ymax); + + % Insert smaller plot +_pgsch (0.7); +_pgbox ("BCNST", 0.0, 1, "BCNST", 0.0, 1); +_pgsch (1.0); + +variable d; +d = get_data(id); +_pgbin (d.bin_lo, d.value, 0); % 0 means x value is bin left edge + +plasma(aped); + +charsize(0.7); +variable Fe = 26; +plot_group(where(wl(xmin, xmax) and el_ion(Fe,17)),4); +charsize(1.0); + +close_plot(pid); diff --git a/doc/scripts/data.sl b/doc/scripts/data.sl new file mode 100644 index 0000000..14333e2 --- /dev/null +++ b/doc/scripts/data.sl @@ -0,0 +1,23 @@ + +variable dir = _isis_srcdir + "/../isis-examples/data"; + +% load data file containing more than 9 spectra + +() = load_data (dir + "/acisf01318N003_pha2.fits.gz"); +() = load_arf (dir + "/acisf01318_000N001MEG_-1_garf.fits.gz"); +assign_arf(1,9); +flux_corr(9,2); % flux-correct down to 2-sigma significance level + +variable id=open_plot ("data_cts.ps/vcps"); +resize(15); +plot_data_counts (9); % plot spectrum #9 +close_plot (id); + +id=open_plot ("data_flx.ps/vcps"); +resize(15); +xrange(8,25); +plot_data_flux (9); % plot spectrum #9 +close_plot (id); + + + diff --git a/doc/scripts/demo.sl b/doc/scripts/demo.sl new file mode 100644 index 0000000..85b192f --- /dev/null +++ b/doc/scripts/demo.sl @@ -0,0 +1,49 @@ + +path = _isis_srcdir + "/../isis-examples/data"; + +load_data (path + "/acisf01318N003_pha2.fits.gz"); + +() = load_arf (path + "/acisf01318_000N001MEG_-1_garf.fits.gz"); +assign_arf(1,9); + +() = load_rmf (path + "/acismeg1D1999-07-22rmfN0002.fits.gz"); +assign_rmf(1,9); + +plot_data_counts (9); +alias ("plot_data_counts", "pdc"); + +xrange(12.0,13.0); +pdc (9); + +ignore ([ [1:8], [10:12] ]); +xnotice (9, 12.05, 12.2); + +fit_fun ("gauss(1)"); +list_par; + +set_par(1,100); +set_par(2,12.15); +set_par(3,0.03); + +() = renorm_counts; +() = fit_counts; + +alias ("oplot_model_counts", "opmc"); +opmc (9); + +save_par("gfit.p"); + +(amin, amax) = vconf(1); +a = get_par(1); +set_par(1, a, 0, 0.9*a, 1.1*a); +(amin, amax) = vconf(1); + +fp = fopen ("gfit.txt", "w"); +() = fprintf (fp, "Center Sigma Flux (F_lower, F_upper)\n"); +() = fprintf (fp, "%10.7f %12.4e %12.4e (%9.4e, %9.4e) \n", + get_par(2), get_par(3), get_par(1), amin, amax); +fclose(fp); + + + + diff --git a/doc/scripts/elev.sl b/doc/scripts/elev.sl new file mode 100644 index 0000000..f0cf773 --- /dev/null +++ b/doc/scripts/elev.sl @@ -0,0 +1,12 @@ + +variable id=open_plot ("elev.ps/vcps"); +resize(15); + +atoms(aped); +charsize(1.2); +label ("\\u(2S+1)\\dL", "Excitation Energy (eV)", "Ne IX"); +plot_elev(Ne,9); +oplot_lines (Ne, 9, where(el_ion(Ne, 9) and wl(11,15)),4); + +close_plot(id); + diff --git a/doc/scripts/ion_curves.sl b/doc/scripts/ion_curves.sl new file mode 100644 index 0000000..d2e31b9 --- /dev/null +++ b/doc/scripts/ion_curves.sl @@ -0,0 +1,26 @@ +plasma(aped); + +variable Fe=26; +variable id=open_plot("ion_frac.ps/vcps"); +resize(15); + +variable t = 10.0^[6.0:7.2:0.05]; % define a log temperature grid (K) + +label ("Temperature [K]", "Ion Fraction", ""); +plot (t, ion_frac(Fe, 17, t)); % assuming Fe = 26 defined in ~/.isisrc +close_plot(id); + +variable Ca = 20; +variable j_fe, f_fe; +variable j_ca, f_ca; +(j_fe, f_fe) = ion_bal (Fe, 1.e7); % Fe at T = 1.e7 K +(j_ca, f_ca) = ion_bal (Ca, 1.e7); % Ca at T = 1.e7 K + +variable id=open_plot ("ion_bal.ps/vcps"); +resize(15); +xrange(14,26); +label ("Ion Charge", "Ion Fraction", ""); +hplot (j_ca-0.5, j_ca+0.5, f_ca); +ohplot (j_fe-0.5, j_fe+0.5, f_fe); +color(1); +close_plot(id); diff --git a/doc/scripts/line_id.sl b/doc/scripts/line_id.sl new file mode 100644 index 0000000..4230d07 --- /dev/null +++ b/doc/scripts/line_id.sl @@ -0,0 +1,31 @@ + +variable dir = _isis_srcdir + "/../isis-examples/data"; + +% load data file containing more than 9 spectra +() = load_data (dir + "/acisf01318N003_pha2.fits.gz"); + +plasma(aped); +load_model(_isis_srcdir + "/doc/scripts/model.dat"); + +variable d, flux, g; + +d = get_data_counts (9); +flux = model_spectrum (d.bin_lo, d.bin_hi); +g = brightest(10, where (wl(10,12))); % get indices of bright lines + +variable id=open_plot ("line_id.ps/vcps"); +resize(15); + +xrange(10,12); +yrange(0,50); +plot_data_counts (9); + + +% and modify the default line label style: +variable x = line_label_default_style(); +x.angle = 45.0; % angle the labels for easier reading +x.label_type = 1; % use long labels + +plot_group(g, 1, x); + +close_plot(id); diff --git a/doc/scripts/model.dat b/doc/scripts/model.dat new file mode 100644 index 0000000..556ea9d --- /dev/null +++ b/doc/scripts/model.dat @@ -0,0 +1,11 @@ +# id Temp Dens Abund Norm Vturb redshift Nh +# K cm^-2 km/s cm^-2 + 1 2.e6 1.e-3 1.0 1.0 500.0 0.0 1.e20 + 2 4.e6 1.e-3 1.0 2.0 500.0 0.0 1.e20 + Fe=0.3 Na=0.2 Al=0.4 P=2 + Ca = 3 + 3 6.e6 1.e-3 1.0 3.0 500.0 0.0 1.e20 + 4 8.e6 1.e-3 1.0 2.0 500.0 0.0 1.e20 + Fe = 0.8 Na = 1.0 Al = 0.4 P = 2 + Ca = 1.0 + diff --git a/doc/scripts/print_args.sl b/doc/scripts/print_args.sl new file mode 100644 index 0000000..2881b70 --- /dev/null +++ b/doc/scripts/print_args.sl @@ -0,0 +1,4 @@ +vmessage ("__argc = %d", __argc); +vmessage ("__argv[0] = %s", __argv[0]); +vmessage ("Command line:"); +print (__argv); diff --git a/doc/scripts/profile_fit.dat b/doc/scripts/profile_fit.dat new file mode 100644 index 0000000..1e7fda2 --- /dev/null +++ b/doc/scripts/profile_fit.dat @@ -0,0 +1,22 @@ + 1.5955326e+01 1.5960888e+01 11.0 4.0 + 1.5960888e+01 1.5966450e+01 11.0 4.0 + 1.5966450e+01 1.5972012e+01 11.0 4.0 + 1.5972012e+01 1.5977573e+01 11.0 4.0 + 1.5977573e+01 1.5983134e+01 11.0 4.0 + 1.5983134e+01 1.5988696e+01 13.0 4.7 + 1.5988696e+01 1.5994258e+01 25.0 7.0 + 1.5994258e+01 1.5999820e+01 40.0 9.0 + 1.5999820e+01 1.6005383e+01 75.0 11.0 + 1.6005383e+01 1.6010944e+01 110.0 13.0 + 1.6010944e+01 1.6016504e+01 100.0 12.6 + 1.6016504e+01 1.6022066e+01 70.0 11.0 + 1.6022066e+01 1.6027628e+01 90.0 12.0 + 1.6027628e+01 1.6033190e+01 65.0 10.5 + 1.6033190e+01 1.6038752e+01 45.0 9.0 + 1.6038752e+01 1.6044313e+01 30.0 8.0 + 1.6044313e+01 1.6049873e+01 19.0 6.0 + 1.6049873e+01 1.6055435e+01 13.0 4.8 + 1.6055435e+01 1.6060997e+01 11.0 4.0 + 1.6060997e+01 1.6066559e+01 11.0 4.0 + 1.6066559e+01 1.6072121e+01 11.0 4.0 + 1.6072121e+01 1.6077682e+01 11.0 4.0 diff --git a/doc/scripts/profile_fit.sl b/doc/scripts/profile_fit.sl new file mode 100644 index 0000000..a0d6680 --- /dev/null +++ b/doc/scripts/profile_fit.sl @@ -0,0 +1,58 @@ + +variable use_lorentz = 0; + +variable id = open_plot("profile_fit.ps/vcps"); +resize(15); + +plot_bin_density; + +()=load_data(_isis_srcdir + "/doc/scripts/profile_fit.dat"); + +variable dx = 5.554e-3; % bin width + +if (use_lorentz) +{ + fit_fun("Lorentz(1) + Lorentz(2) + poly(1)"); + set_par(1, 300.0, 0, 50.0, 500.0); + set_par(2, 16.0, 0, 15.95, 16.03); + set_par(3, 0.02, 0, 0.001, 0.05); + set_par(4, 120.0, 0, 50.0, 500.0); + set_par(5, 16.03, 0, 15.95, 16.07); + set_par(6, 0.01, 0, 0.001, 0.05); + set_par(7, 10.0/dx); + set_par(8, 0.0, 1, -1, 1); + set_par(9, 0.0, 1, -1, 1); +} +else +{ + fit_fun("gauss(1) + gauss(2) + poly(1)"); + set_par(1, 2.7721065e+02, 0, 3.0000000e+01, 5.0000000e+02); + set_par(2, 1.6026187e+01, 0, 1.5950000e+01, 1.6030000e+01); + set_par(3, 1.0726321e-02, 0, 1.0000000e-03, 5.0000000e-02); + set_par(4, 2.8011030e+02, 0, 5.0000000e+01, 5.0000000e+02); + set_par(5, 1.6007506e+01, 0, 1.5950000e+01, 1.6070000e+01); + set_par(6, 8.1140931e-03, 0, 1.0000000e-03, 5.0000000e-02); + set_par(7, 10.0/dx); + set_par(8, 0.0, 1, -1, 1); + set_par(9, 0.0, 1, -1, 1); +} + +list_par; +() = fit_counts; +list_par; + +errorbars(1); +label("Wavelength (\\(2078))", "Counts/angstrom", ""); +plot_data_counts(1); +oplot_model_counts(1); + +variable x, y; +x = [15.95:16.1:7.5e-4]; +y = get_cfun (x); +oplot(x,y); + +close_plot(id); + + + + diff --git a/doc/scripts/residuals.sl b/doc/scripts/residuals.sl new file mode 100644 index 0000000..fe74677 --- /dev/null +++ b/doc/scripts/residuals.sl @@ -0,0 +1,30 @@ + +public define plot_count_residuals (h, dev) +{ + variable id = open_plot (dev); + resize(15); + + multiplot ([3,1]); + + errorbars (1); + plot_data_counts (h); + oplot_model_counts (h); + + variable d, m; + d = get_data_counts (h); + m = get_model_counts (h); + + errorbars (0); + label ("Wavelength [Angstrom]", "Residuals", ""); + hplot (d.bin_lo, d.bin_hi, m.value - d.value); + + return id; +} + +() = evalfile (_isis_srcdir + "/doc/scripts/profile_fit.sl"); + +message ("plotting residuals"); +variable id = plot_count_residuals (1, "residuals.ps/vcps"); + +close_plot (id); + diff --git a/doc/scripts/xspec.sl b/doc/scripts/xspec.sl new file mode 100644 index 0000000..0a4bef1 --- /dev/null +++ b/doc/scripts/xspec.sl @@ -0,0 +1,22 @@ +variable e, s, n, lo, hi, t; +require ("xspec"); + +e = 10.0^[-1:1:0.005]; % make a log energy grid +s = _mekal (5.0, e); % 5 keV, solar abundance + % MEKAL spectrum + + n = length (s); % The e array has n+1 elements +lo = e[[0:n-1]]; % low edge of histogram bin +hi = e[[1:n]]; % high edge of histogram bin + +variable id = open_plot ("xspec.ps/vcps"); +resize(15); + +xlog; ylog; +label ("log E (keV)", "log Flux", ""); +hplot (lo, hi, s); % plot log-log + +t = _wabs (0.01, e); % include Nh = 1.e20 cm^-2 +ohplot (lo, hi, t * s); % overplot absorbed spectrum + +close_plot (id); diff --git a/etc/apec_d.sl b/etc/apec_d.sl new file mode 100644 index 0000000..b57d503 --- /dev/null +++ b/etc/apec_d.sl @@ -0,0 +1,21 @@ + +define apec_d () +{ + variable db = struct + { + dir, atomic_data_filemap, + abundance, ion_balance, + line_emissivity, continuum_emissivity + }; + + db.dir = "/nfs/cxc/a1/share/atomdb/aped_2000oct04"; + + db.abundance = "Abundances.fits"; + db.ion_balance = "MM98_ionbal.fits"; + + db.line_emissivity = "APEC_TN_v101_line.fits"; + db.continuum_emissivity = "APEC_TN_v101_coco.fits"; + + return db; +} + diff --git a/etc/aped.sl b/etc/aped.sl new file mode 100644 index 0000000..7fe1d3c --- /dev/null +++ b/etc/aped.sl @@ -0,0 +1,103 @@ +% Note that there's nothing special about this function. +% The whole point is to load a structure with some database +% filenames. Using a function to generate the structure just +% allows some extra versatility. +% +% Its ok if some of the files are missing -- ISIS should +% be able to work with whatever subset of these files you +% may have. + +% Usage: +% +% isis> atoms(aped); +% isis> plasma(aped); + +define get_version_string (dir); % prototype +define get_database_directory (); + +define aped () +{ + variable db = struct + { + dir, % The ATOMDB directory + atomic_data_filemap, % An ascii file, usually "filemap" + abundance, % Elemental abundances (FITS file) + ion_balance, % Ionization balance (FITS file) + line_emissivity, % Line emissivity tables (FITS file + continuum_emissivity % Continuum emissivity tables (FITS file) + }; + + db.dir = get_database_directory (); + if (db.dir == NULL) + return NULL; + + variable version = get_version_string (db.dir); + if (version == NULL) + { + vmessage ("*** Failed loading ATOMDB from %s", db.dir); + return NULL; + } + + if (Isis_Verbose >= 0) + vmessage ("Reading database version %s from %s", version, db.dir); + + % versions >= 1.2.0 don't have this problem. + + if (version == "1.1.0") + version = version[[[0:2],4]]; + + % All these files are assumed to be in db.dir. + % If the specified files are not all within db.dir or + % one of its subdirectories, define db.dir="" + % (e.g. the empty string) and provide the full + % path to each individual file: + db.atomic_data_filemap = "filemap"; + + db.abundance = "APED/misc/Abundances.fits"; + db.ion_balance = "APED/ionbal/MM98_ionbal.fits"; + + db.line_emissivity = "apec_v" + version + "_line.fits"; + db.continuum_emissivity = "apec_v" + version + "_coco.fits"; + + return db; +} + +define get_database_directory () +{ + variable not_found = "\n*** ATOMDB not found.\n*** Is the ATOMDB environment variable set correctly?\n"; + + % Note that db.dir is taken as the definition for the $ATOMDB + % variable which appears in the atomic_data_filemap file. + % If the $ATOMDB string doesn't appear in your 'filemap' file, + % this may not work. Sorry for any trouble that may cause, + % but its not under my control. + variable dir = getenv ("ATOMDB"); + if (orelse + {dir == NULL} + {stat_file (dir) == NULL}) + { + message (not_found); + return NULL; + } + + return dir; +} + +define get_version_string (dir) +{ + variable fp = fopen (dir + "/VERSION", "r"); + if (fp == NULL) + { + vmessage ("*** File not found: %s/VERSION", dir); + return NULL; + } + + variable version; + if (-1 == fgets (&version, fp)) + { + vmessage ("*** Failed reading %s/Version", dir); + return NULL; + } + + return strtrim(version); +} diff --git a/etc/isis.rc b/etc/isis.rc new file mode 100644 index 0000000..8939df4 --- /dev/null +++ b/etc/isis.rc @@ -0,0 +1,79 @@ +% -*- slang -*- + +Min_Model_Spacing = 0.0; % Angstroms +%--------------------------------------------------------------------- +% Min_Model_Spacing is the minimum grid-spacing used for the +% theoretical source spectrum when fitting with multiple responses +% (e.g. for LETG multi-order fitting). +% +% Regardless of the value of Min_Model_Spacing, ISIS will not use a +% grid which is finer than the ARF grid at any point. +% + +Remove_Spectrum_Gaps = 0; +%---------------------------------------------------------------------- +% Remove_Spectrum_Gaps controls how ISIS treats input spectrum +% grids with holes in them. +% If Remove_Spectrum_Gaps = 0, ISIS will refuse to read a spectrum +% grid with a hole in it [default] +% If Remove_Spectrum_Gaps = 1, ISIS will automatically remove the +% gaps by merging them into the +% neighboring bin. + +Ion_Format = FMT_ROMAN; +%---------------------------------------------------------------------- +% Ion_Format controls the printing of ion names. +% Set = FMT_ROMAN to get ion names like 'Fe XXIV' +% Set = FMT_INT_ROMAN to get ion names like 'Fe 24' (meaning Fe XXIV) +% Set = FMT_CHARGE to get ion names like 'Fe +23', (meaning ion charge = 23) + + +Use_Memory = 3; +%---------------------------------------------------------------------- +% Use_Memory controls run-time memory usage and database input speed +% Use_Memory = 0 -> read lines and continua on-demand +% 1 -> read lines up front, continua on-demand +% 2 -> read lines on-demand, continua up front +% 3 -> read lines and continua up front +% +% For faster database input, uncompress the datafiles on disk. +% For fastest model computation, load all the line and continuum +% data up front (Use_Memory=3) if you have sufficient memory. +% Choose Use_Memory=0 to minimize run-time memory usage. +% Those interested mainly in line data might prefer Use_Memory=1. +% + +Incomplete_Line_List = 1; +%---------------------------------------------------------------------- +% Incomplete_Line_List controls the treatment of line emissivity tables +% on input. +% Set = 1 if the line emissivity tables might contain lines not +% listed in the atomic data tables. This option is safer, but +% a little slower. +% Set = 0 otherwise. This option results in faster input, but the +% input will fail if the wavelength tables are incomplete. + + +Label_By_Default = 1; +%---------------------------------------------------------------------- +% Label_By_Default controls the labeling of spectrum plot axes. +% Set = 1 to have spectrum plot axes labeled automatically +% Set = 0 to turn off automatic axis labeling. + + +Fit_Verbose = 0; +%---------------------------------------------------------------------- +% Fit_Verbose controls the level of information printed during +% iterative fitting of models to data. +% Set = 1 to see lots of information printed. +% = 0 for the default verbose level. +% = -1 to fit silently. + +Verbose_Fitsio = 0; +%---------------------------------------------------------------------- +% Verbose_Fitsio controls printing of FITSIO error messages +% Set = 1 to see FITSIO error messages +% = 0 to avoid seeing FITSIO error messages + + + diff --git a/etc/local.sl b/etc/local.sl new file mode 100644 index 0000000..befe190 --- /dev/null +++ b/etc/local.sl @@ -0,0 +1,18 @@ +% +% Use this file to provide site-local customizations. +% If present, this file is loaded by ISIS at startup. +% +% Site-local documentation may be placed in local_help.txt +% using the format indicated by the provided template. +% + +% provide hooks to local spectroscopy database(s): + +autoload ("aped", path_concat(_isis_srcdir,"etc/aped.sl")); +autoload ("apec_d", path_concat(_isis_srcdir,"etc/apec_d.sl")); + +% include paths to local modules and packages + +$1 = "/nfs/cxc/a1/setup/isis-setup.sl"; +if (NULL != stat_file ($1)) + () = evalfile ($1, current_namespace()); diff --git a/etc/modules.lis b/etc/modules.lis new file mode 100644 index 0000000..73b1c94 --- /dev/null +++ b/etc/modules.lis @@ -0,0 +1,4 @@ +apec_d.sl +aped.sl +isis.rc +local.sl diff --git a/files.lis b/files.lis new file mode 100644 index 0000000..0e1eda7 --- /dev/null +++ b/files.lis @@ -0,0 +1,393 @@ +test/ +test/here_doc.sh +test/arf.dat +test/uncon/ +test/uncon/Makefile.in +test/uncon/uncon.sl +test/uncon/uncon-module.c +test/uncon/run_tests +test/uncon/src/ +test/uncon/src/modules.lis +test/uncon/src/biggs.F +test/uncon/src/badscp.F +test/uncon/src/gulf.F +test/uncon/src/sing.F +test/uncon/src/cheb.F +test/uncon/src/trid.F +test/uncon/src/band.F +test/uncon/src/osb1.F +test/uncon/src/osb2.F +test/uncon/src/trig.F +test/uncon/src/devg1.F +test/uncon/src/devg2.F +test/uncon/src/bv.F +test/uncon/src/bard.F +test/uncon/src/beale.F +test/uncon/src/rose.F +test/uncon/src/helix.F +test/uncon/src/watson.F +test/uncon/src/jensam.F +test/uncon/src/dcopy.f +test/uncon/src/meyer.F +test/uncon/src/lin.F +test/uncon/src/gauss.F +test/uncon/src/froth.F +test/uncon/src/vardim.F +test/uncon/src/blas.lis +test/uncon/src/daxpy.f +test/uncon/src/han1.F +test/uncon/src/han2.F +test/uncon/src/box.F +test/uncon/src/msqrt2.F +test/uncon/src/singx.F +test/uncon/src/msqrt3.F +test/uncon/src/ddot.f +test/uncon/src/mck1.F +test/uncon/src/mck2.F +test/uncon/src/ie.F +test/uncon/src/mck3.F +test/uncon/src/almost.F +test/uncon/src/rosex.F +test/uncon/src/lin0.F +test/uncon/src/lin1.F +test/uncon/src/pen1.F +test/uncon/src/kowosb.F +test/uncon/src/pen2.F +test/uncon/src/dgv6.F +test/uncon/src/dgv8.F +test/uncon/src/wood.F +test/uncon/src/README +test/uncon/src/badscb.F +test/uncon/src/bd.F +test/uncon/README +test/Makefile.in +test/config.hin +test/backscale.sl +test/hist.sl +test/constraint.sl +test/readcol.sl +test/confmap.sl +test/data/ +test/data/pi.fits +test/data/acisf01318N003_pha2.fits.gz +test/data/confmap.fits +test/data/acismeg1D1999-07-22rmfN0002.fits.gz +test/data/acisf01318_000N001MEG_-1_garf.fits.gz +test/xgroup.sl +test/run_tests.sl +test/post_model_hook.sl +test/par_fun.sl +test/multi.sl +test/param_defaults.sl +test/region_stats.sl +test/renorm.sl +test/ds_combine.sl +test/flux_corr.sl +test/rebin_dataset.sl +test/inc.sl +test/stat.sl +test/xspec_import.sl +test/bpl.sl +test/module_import.sl +test/README +test/eval_fun2.sl +test/fit.sl +test/rmf_user.c +test/pileup.dat +test/opfun.sl +test/max_like.sl +test/pileup.sl +test/user_grid_eval.sl +test/rebin.sl +test/arrayops.sl +test/yshift.sl +contrib/ +contrib/cspec_summary.sl +contrib/pick_el.sl +contrib/aped_fit_models.sl +contrib/fspec_summary.sl +contrib/aped_contin.sl +contrib/gsmooth.sl +contrib/README +contrib/monte.sl +contrib/hanning.sl +contrib/fshift.sl +contrib/max_like.sl +contrib/ascii.sl +contrib/clear_bits +contrib/marxflux +contrib/splot_data.sl +contrib/bestfit.sl +share/ +share/setup.sl +share/fits_module_dep.sl +share/pgplot_interface.sl +share/plot-extra.sl +share/plot-cmds.sl +share/init.sl +share/mathmisc.sl +share/fit-cmds.sl +share/_isis.sl +share/isis.sl +share/backtrace.sh +share/errors.sl +share/require.sl +share/isisdb.sl +share/isisprof.sl +share/emis-cmds.sl +share/aped_fun.sl +share/modules.lis +share/model-cmds.sl +share/atom-cmds.sl +share/cmds.sl +share/physconst.sl +share/hist-cmds.sl +configure +doc/ +doc/scripts/ +doc/scripts/profile_fit.sl +doc/scripts/line_id.sl +doc/scripts/bgd_subtract.sl +doc/scripts/print_args.sl +doc/scripts/data.sl +doc/scripts/ion_curves.sl +doc/scripts/xspec.sl +doc/scripts/demo.sl +doc/scripts/crude_dem.sl +doc/scripts/contour.sl +doc/scripts/model.dat +doc/scripts/contin.sl +doc/scripts/residuals.sl +doc/scripts/elev.sl +doc/scripts/custom1.sl +doc/scripts/profile_fit.dat +doc/manual.pdf +doc/help.txt +doc/local_help.txt +doc/isis.1 +src/ +src/mkdist.sh +src/pileup_kernel.c +src/config.hin +src/Makefile.in +src/histogram.h +src/fit-cmds.c +src/errors.c +src/util.c +src/errors.h +src/subplex.c +src/util.h +src/keyword.c +src/fftn.inc +src/isismath.h +src/djbfft.inc +src/db-display.c +src/math.c +src/keyword.h +src/std_kernel.c +src/db-display.h +src/rmf_delta.c +src/marq.c +src/fc_modules.lis +src/errors.inc +src/plotlib.c +src/cfits.c +src/cfits.h +src/plot.c +src/fit-chisqrconf.c +src/mt19937ar.c +src/emis-cmds.c +src/plot.h +src/db-cie.c +src/readline.c +src/model-cmds.c +src/lmdif_lib.f +src/dblas.c +src/db-cie.h +src/fit-funs.c +src/fftn.c +src/fit-kernel.c +src/plot-cmds.c +src/simann_lib.f +src/isis.c +src/arf.c +src/isis.h +src/arf.h +src/rmf_file.c +src/atom-cmds.c +src/chkslang.c +src/lmdif.c +src/hist-cmds.c +src/crout.c +src/svd.c +src/db-atomic.c +src/model.c +src/svd.h +src/fit-params.c +src/db-atomic.h +src/model.h +src/simann.c +src/_isis.h +src/subplex_lib.f +src/modules.lis +src/cash.c +src/random.c +src/miscio.c +src/rmf.c +src/fit-engine.c +src/fit.h +src/fit-functions.c +src/voigt.c +src/chisqr.c +src/db-em.h +src/dynmem.c +src/rmf.h +src/options.c +src/histogram.c +INSTALL.txt +modules/ +modules/cfitsio/ +modules/cfitsio/share/ +modules/cfitsio/share/readrmf.sl +modules/cfitsio/configure +modules/cfitsio/doc/ +modules/cfitsio/doc/tm/ +modules/cfitsio/doc/tm/rtl/ +modules/cfitsio/doc/tm/rtl/cfitsiofuns.tm +modules/cfitsio/doc/tm/cfitsio.tm +modules/cfitsio/doc/tm/fitsfuns.tm +modules/cfitsio/doc/tm/fitswcsfuns.tm +modules/cfitsio/doc/tm/fixtex.sl +modules/cfitsio/doc/tm/helpfile.tm +modules/cfitsio/doc/tm/mkindex.sl +modules/cfitsio/doc/tm/Makefile +modules/cfitsio/doc/text/ +modules/cfitsio/doc/text/cfitsio.txt +modules/cfitsio/doc/help/ +modules/cfitsio/doc/help/cfitsio.hlp +modules/cfitsio/src/ +modules/cfitsio/src/tests/ +modules/cfitsio/src/tests/test_fits.sl +modules/cfitsio/src/fitswcs.sl +modules/cfitsio/src/Makefile.in +modules/cfitsio/src/config.hin +modules/cfitsio/src/fits.sl +modules/cfitsio/src/cfitsio-module.c +modules/cfitsio/src/mkversion.sh +modules/cfitsio/src/version.h +modules/cfitsio/src/cfitsio.sl +modules/cfitsio/INSTALL.txt +modules/cfitsio/autoconf/ +modules/cfitsio/autoconf/Makefile.in +modules/cfitsio/autoconf/configure.in +modules/cfitsio/autoconf/mkinsdir.sh +modules/cfitsio/autoconf/config.guess +modules/cfitsio/autoconf/aclocal.m4 +modules/cfitsio/autoconf/config.sub +modules/cfitsio/autoconf/install-sh +modules/cfitsio/cfitsio.lis +modules/cfitsio/ChangeLog +modules/cfitsio/COPYRIGHT +modules/cfitsio/README +modules/cfitsio/examples/ +modules/cfitsio/examples/mkimgcont +modules/cfitsio/examples/fitscopy +modules/cfitsio/examples/binevt +modules/cfitsio/examples/viewimage +modules/xspec/ +modules/xspec/src/ +modules/xspec/src/_model_externs_xspec11.inc +modules/xspec/src/_model_externs_xspec12.inc +modules/xspec/src/code_gen.sl +modules/xspec/src/tblint.f +modules/xspec/src/xsatbl.f +modules/xspec/src/config.hin +modules/xspec/src/cfortran.doc +modules/xspec/src/Makefile.in +modules/xspec/src/xsetbl.f +modules/xspec/src/xspec-module.c +modules/xspec/src/erebin.f +modules/xspec/src/xspec.inc +modules/xspec/src/xspec_libs.in +modules/xspec/src/inibin.f +modules/xspec/src/test.sl +modules/xspec/src/xsmtbl.f +modules/xspec/src/modules.lis +modules/xspec/src/cfortex.f +modules/xspec/src/parse_model_dat.sl +modules/xspec/src/xspec.sl +modules/xspec/src/cfortran.h +modules/xspec/src/README.tables +modules/xspec/src/README.code +modules/xspec/src/_names_xspec11.dat +modules/xspec/src/_names_xspec12.dat +modules/xspec/src/cfortest.c +modules/xspec/src/xspec-compat.inc +modules/xspec/src/_model_table_xspec11.inc +modules/xspec/src/_model_table_xspec12.inc +modules/xspec/configure +modules/xspec/autoconf/ +modules/xspec/autoconf/Makefile.in +modules/xspec/autoconf/configure.ac +modules/xspec/autoconf/mkinsdir.sh +modules/xspec/autoconf/config.guess +modules/xspec/autoconf/aclocal.m4 +modules/xspec/autoconf/config.sub +modules/xspec/autoconf/install-sh +modules/xspec/README +modules/Makefile.in +modules/pgplot/ +modules/pgplot/doc/ +modules/pgplot/doc/tm/ +modules/pgplot/doc/tm/fixtex.sl +modules/pgplot/doc/tm/template.tm +modules/pgplot/doc/tm/Makefile +modules/pgplot/src/ +modules/pgplot/src/tests/ +modules/pgplot/src/tests/test_pgplot.sl +modules/pgplot/src/Makefile.in +modules/pgplot/src/config.hin +modules/pgplot/src/pgplot.sl +modules/pgplot/src/pgplot-module.c +modules/pgplot/src/mkversion.sh +modules/pgplot/src/version.h +modules/pgplot/configure +modules/pgplot/INSTALL.txt +modules/pgplot/autoconf/ +modules/pgplot/autoconf/Makefile.in +modules/pgplot/autoconf/configure.ac +modules/pgplot/autoconf/mkinsdir.sh +modules/pgplot/autoconf/config.guess +modules/pgplot/autoconf/aclocal.m4 +modules/pgplot/autoconf/config.sub +modules/pgplot/autoconf/install-sh +modules/pgplot/COPYRIGHT +modules/pgplot/pgplot.lis +modules/pgplot/README +modules/pgplot/examples/ +modules/pgplot/examples/demo.sl +modules/pgplot/examples/viewimg +modules/pgplot/examples/README +modules/README +Changes.txt +COPYING +COPYRIGHT +etc/ +etc/apec_d.sl +etc/aped.sl +etc/local.sl +etc/modules.lis +etc/isis.rc +autoconf/ +autoconf/README.cdrom +autoconf/Makefile.in +autoconf/configure.ac +autoconf/mkinsdir.sh +autoconf/config.guess +autoconf/isis.binary +autoconf/isis.cdrom +autoconf/aclocal.m4 +autoconf/config.sub +autoconf/install-sh +README +files.lis diff --git a/modules/Makefile.in b/modules/Makefile.in new file mode 100644 index 0000000..9388bc6 --- /dev/null +++ b/modules/Makefile.in @@ -0,0 +1,78 @@ +# -*- sh -*- + +# $Id: Makefile.in,v 1.21 2004/09/09 11:31:49 houck Exp $ + +#----------------------------------------------------------------------- +# This file is part of ISIS, the Interactive Spectral Interpretation System +# Copyright (C) 1998-2008 Massachusetts Institute of Technology +#----------------------------------------------------------------------- + +@SET_MAKE@ +SHELL = /bin/sh +RM = /bin/rm -f +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ + +MKINSDIR = ../autoconf/mkinsdir.sh + +MODULES = @MODULE_LIST@ +LINK_XSPEC_STATIC = @LINK_XSPEC_STATIC@ + +all: + @for i in $(MODULES) ; \ + do \ + cd $$i; \ + $(MAKE) all ; \ + cd ..; \ + done + +elf: + $(MAKE) all + +install: + @for i in $(MODULES) ; \ + do \ + cd $$i; \ + $(MAKE) install ; \ + cd ..; \ + done + +install-elf: + $(MAKE) install + +install-modules: + cd xspec; $(MAKE) install + +xspec-static: + cd xspec; $(MAKE) static + +xspec-elf: + cd xspec; $(MAKE) elf + +clean: + @for i in $(MODULES) ; \ + do \ + cd $$i ; $(MAKE) clean ; cd .. ; \ + done ; \ + if test "$(LINK_XSPEC_STATIC)" = "yes" ; then \ + cd xspec ; make clean ; cd .. ; \ + fi + -$(RM) *~ .##* + +distclean: + @for i in $(MODULES) ; \ + do \ + cd $$i ; $(MAKE) distclean ; cd .. ;\ + done ; \ + if test "$(LINK_XSPEC_STATIC)" = "yes" ; then \ + cd xspec ; make distclean ; cd .. ; \ + fi + -$(RM) .##* *~ Makefile config.status config.log config.cache files.pck autoconf/f77test.out + +confclean: + -$(RM) .##* *~ Makefile config.status config.log config.cache files.pck +# +# The symlinks target is for my own private use. It simply creates the object +# directory as a symbolic link to a local disk instead of an NFS mounted one. +symlinks: + cd xspec; $(MAKE) symlinks diff --git a/modules/README b/modules/README new file mode 100644 index 0000000..816ed37 --- /dev/null +++ b/modules/README @@ -0,0 +1,10 @@ + +This directory contains modules which provide optional +functionality for ISIS. They are normally compiled as +dynamically linked modules which may optionally be loaded at +run-time. For systems lacking ELF support, these modules may +additionally support being statically linked to ISIS. + +See the individual module directories for installation +instructions. + diff --git a/modules/cfitsio/COPYRIGHT b/modules/cfitsio/COPYRIGHT new file mode 100644 index 0000000..3efe62b --- /dev/null +++ b/modules/cfitsio/COPYRIGHT @@ -0,0 +1,24 @@ + Copyright (c) 2003 Massachusetts Institute of Technology + + This software was developed by the MIT Center for Space Research + under contract SV1-61010 from the Smithsonian Institution. + + Permission to use, copy, modify, distribute, and sell this software + and its documentation for any purpose is hereby granted without fee, + provided that the above copyright notice appear in all copies and + that both that copyright notice and this permission notice appear in + the supporting documentation, and that the name of the Massachusetts + Institute of Technology not be used in advertising or publicity + pertaining to distribution of the software without specific, written + prior permission. The Massachusetts Institute of Technology makes + no representations about the suitability of this software for any + purpose. It is provided "as is" without express or implied warranty. + + THE MASSACHUSETTS INSTITUTE OF TECHNOLOGY DISCLAIMS ALL WARRANTIES + WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE MASSACHUSETTS + INSTITUTE OF TECHNOLOGY BE LIABLE FOR ANY SPECIAL, INDIRECT OR + CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS + OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, + NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION + WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. diff --git a/modules/cfitsio/ChangeLog b/modules/cfitsio/ChangeLog new file mode 100644 index 0000000..65c2c82 --- /dev/null +++ b/modules/cfitsio/ChangeLog @@ -0,0 +1,213 @@ +2008-6-12 John E. Davis + + * src/version.h (MODULE_PATCH_LEVEL): bumped to 0.4.3 + + * src/cfitsio-module.c (write_col): unsigned ints were getting + written as ints, causing integer overflows. + +2008-5-1 John E. Davis + + * src/version.h (MODULE_PATCH_LEVEL): bumped to 0.4.2 + + * src/cfitsio-module.c (FitsFile_Type): Made changes to use + the physical integer sizes where possible instead of the + confusing cfitsio types, e.g., INT32_TYPE instead of TLONG. + The changes reduces the memory usage on 64 bit systems. + +2008-4-29 John E. Davis + + * src/version.h (MODULE_PATCH_LEVEL): bumped to 0.4.1 + + * src/cfitsio-module.c (FitsFile_Type): I was using SIZEOF_INT + as bits rather than bytes. Gr.... + + * src/fits.sl (_fits_sl_version_string): Bumped to 0.4.3-3 + +2008-1-24 John E. Davis + + * src/fits.sl (fits_write_binary_table): Bug fixed when + writing vector columns. + +2007-12-7 John E. Davis + + * src/fits.sl (fits_write_binary_table): Fixed infinite loop + bug in fits_write_binary_table + (_fits_sl_version_string): bumped to 0.4.3-2 + +2007-11-16 John E. Davis + + * src/version.h (MODULE_VERSION_NUMBER): Changed to 0.3.9 + +2007-10-3 John E. Davis + + * src/cfitsio-module.c: Started adding support for LONGLONG. + +2007-9-18 John E. Davis + + * src/cfitsio-module.c (map_fitsio_type_to_slang): improved + support for bit columns that are not a multiple of 8. + +2007-5-15 John E. Davis + + * src/fits.sl (_fits_sl_version_string): bumped to 0.4.3-1 + (fits_read_key): call _fits_clear_errmsg if status==_FITS_KEY_NO_EXIST. + +2007-4-19 John E. Davis + + * src/fits.sl: (_fits_sl_version_string): bumped to 0.4.2-0 + + * src/fits.sl (fits_set_verbose_errors): Used to control the + error message verbosity. + +2007-4-18 John E. Davis + + * src/cfitsio-module.c (clear_errmsg): Made _fits_clear_errmsg + a wrapper around fits_clear_errmsg. + + * src/version.h (MODULE_VERSION_NUMBER): bumped to 0.3.8 + +2007-4-17 John E. Davis + + * src/fits.sl (do_fits_error): modified to use + _fits_read_errmsg. Also added a FitsError exception and + added a function called fits_get_errmsgs, which returns the + messages from the fits errmsg queue. + + * src/cfitsio-module.c (read_errmsg): Added wrapper for + fits_read_errmsg. + + * src/version.h (MODULE_VERSION_NUMBER): bumped to 0.3.7 + + * src/fits.sl (get_open_hdu_of_type): If looking for a binary + table, accept an ascii table. + + * src/cfitsio-module.c (read_col): Support for ascii tables + added. For string columns, this required a different + interpretation of the TFORM specifier. Binary tables use, + e.g, 8A for TFORM whereas ASCII tables use A8. Nice. + +2007-4-10 John E. Davis + + * src/fits.sl (_fits_sl_version_string): bumped to 0.4.1-0 + * src/fits.sl: Added additional information to calls to + do_fits_error in an effort to improve the error messages. + + +2007-4-6 John E. Davis + + * src/version.h (MODULE_PATCH_LEVEL): bumped to 0.3.6 + + * src/cfitsio-module.c (map_fitsio_type_to_slang): bit types + get mapped to SIGNED int values instead of unsigned values. + This avoids the silly unsigned integer convention when such + values get written out as integers. + +2007-3-28 John E. Davis + + * src/fits.sl (reverse): made reverse a private function. + (_fits_sl_version_string): bumped to 0.4.4-0 + + * src/fitswcs.sl (simplify_wcs): work-around what appears to + be a ds9 bug-- if a PC matrix is present, then the CDELT + values must be equal. + (_fitswcs_version_string): 0.2.0-1 + +2007-3-27 John E. Davis + + * src/fitswcs.sl (_fitswcs_version_string): bumped to 0.2.0-0 + (fitswcs_linear_transform_wcs): Modified the interface to make + it more intuitive. + (fitswcs_bin_wcs): New function + (fitswcs_rebin_wcs): Changed the interface so that it works + with images-- not event lists. + +2007-3-22 John E. Davis + + * src/fitswcs.sl (fitswcs_new): typo that initialized cdelt to 0. + (_fitswcs_version_string): bumped to 0.1.1-1 + +2007-3-8 John E. Davis + + * src/fits.sl (make_tdim_string): Use array_reverse instead of + reverse. + (_fits_sl_version_string): bumped to 0.4.3-1 + +2007-2-21 John E. Davis + + * src/cfitsio-module.c (open_file): fits_open_file does not + set fptr to NULL upon return if an error occurs as assumed. + + * src/version.h (MODULE_PATCH_LEVEL): bumped to 0.3.5 + + * src/cfitsio-module.c (check_version): Added a warning + message if the compiled and linked cfitsio versions do not match. + + * src/cfitsio-module.c (read_column_values): change to support + repeat = 0 for variable length arrays left an uninitialized + variable. + +2007-2-16 John E. Davis + + * src/cfitsio-module.c (write_img): added support for unsigned types. + + * src/version.h (MODULE_PATCH_LEVEL): bumped to 0.3.4 + + * src/fits.sl (fits_write_binary_table): Added support for + unsigned 16 and 32 bit integers. + (fits_get_bitpix): modified bitpix values for unsigned types + and Char_Type. + (_fits_sl_version_string): version bumped to 0.4.3-0 + +2007-2-14 John E. Davis + + * src/version.h (MODULE_PATCH_LEVEL): Bumped to version 0.3-3 + + * src/cfitsio-module.c (read_column_values): repeat=0 (a + column with 0 length was not supported). + +2006-6-13 John E. Davis + + * src/fits.sl (fits_update_logical): Usage message referred to + fits_update_key. + (_fits_sl_version_string): Updated to 0.4.2-4 + +2006-4-7 John E. Davis + + * src/fits.sl (_fits_sl_version_string): bumped to 0.4.2-3 + (fits_write_binary_table): allow data struct to be NULL + +2006-2-17 John E. Davis + + * src/fits.sl (fits_write_records): The usage string referred + to fits_read+records. + (_fits_sl_version_string): version string bumped to 0.4.2-2 + +2006-1-26 John E. Davis + + * src/fitswcs.sl (struct): Added radsys and equinox fields to + the the wcs structure. + +2005-11-10 John E. Davis + + * src/fits.sl (_fits_sl_version_string): bumped to 0.4.2-1. + (read_cols): numrows was not being passed to _fits_read_cols + (Ronnie Hoogerwerf ronnieh at head, cfa, harvard, edu) + +2005-10-27 John E. Davis + + * autoconf/configure.in: removed JD_SET_RPATH. + + * src/Makefile.in: changed *HELP_* to *HLP_* + +2005-5-18 John E. Davis + + * src/fits.sl (_fits_sl_version_string): Bumped to 0.4.2-0 + + * src/fits.sl: Changed static qualifier to private and + dropped the public qualifiers. + + * src/fitswcs.sl (_fitswcs_version_string): Bumped to 0.1.1-0 + + * src/fitswcs.sl: Changed static qualifier to private and + dropped the public qualifiers. + diff --git a/modules/cfitsio/INSTALL.txt b/modules/cfitsio/INSTALL.txt new file mode 100644 index 0000000..655a07a --- /dev/null +++ b/modules/cfitsio/INSTALL.txt @@ -0,0 +1,183 @@ +See the README file before reading this. + +Basic Installation +================== + + These are generic installation instructions. + + 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, a file +`config.cache' that saves the results of its tests to speed up +reconfiguring, and a file `config.log' containing compiler output +(useful mainly for debugging `configure'). + + 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 at some point `config.cache' +contains results you don't want to keep, you may remove or edit it. + + The file `configure.in' is used to create `configure' by a program +called `autoconf'. You only need `configure.in' 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. If you're + using `csh' on an old version of System V, you might need to type + `sh ./configure' instead to prevent `csh' from trying to execute + `configure' itself. + + Running `configure' takes awhile. 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. + + 4. Type `make install' to install the programs and any data files and + documentation. + + 5. 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. + +Compilers and Options +===================== + + Some systems require unusual options for compilation or linking that +the `configure' script does not know about. You can give `configure' +initial values for variables by setting them in the environment. Using +a Bourne-compatible shell, you can do that on the command line like +this: + CC=c89 CFLAGS=-O2 LIBS=-lposix ./configure + +Or on systems that have the `env' program, you can do it like this: + env CPPFLAGS=-I/usr/local/include LDFLAGS=-s ./configure + +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 must use a version of `make' that +supports the `VPATH' variable, such as 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 `..'. + + If you have to use a `make' that does not supports the `VPATH' +variable, you have 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. + +Installation Names +================== + + By default, `make install' will install the package's files in +`/usr/local/bin', `/usr/local/man', etc. You can specify an +installation prefix other than `/usr/local' by giving `configure' the +option `--prefix=PATH'. + + You can specify separate installation prefixes for +architecture-specific files and architecture-independent files. If you +give `configure' the option `--exec-prefix=PATH', the package will use +PATH as the prefix for installing programs and libraries. +Documentation and other data files will still use the regular prefix. + + In addition, if you use an unusual directory layout you can give +options like `--bindir=PATH' 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. + + 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'. + +Optional Features +================= + + 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. + +Specifying the System Type +========================== + + There may be some features `configure' can not figure out +automatically, but needs to determine by the type of host the package +will run on. Usually `configure' can figure that out, but if it prints +a message saying it can not guess the host type, give it the +`--host=TYPE' option. TYPE can either be a short name for the system +type, such as `sun4', or a canonical name with three fields: + CPU-COMPANY-SYSTEM + +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 host type. + + If you are building compiler tools for cross-compiling, you can also +use the `--target=TYPE' option to select the type of system they will +produce code for and the `--build=TYPE' option to select the type of +system on which you are compiling the package. + +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. + +Operation Controls +================== + + `configure' recognizes the following options to control how it +operates. + +`--cache-file=FILE' + Use and save the results of the tests in FILE instead of + `./config.cache'. Set FILE to `/dev/null' to disable caching, for + debugging `configure'. + +`--help' + Print a summary of the options to `configure', and exit. + +`--quiet' +`--silent' +`-q' + Do not print messages saying which checks are being made. + +`--srcdir=DIR' + Look for the package's source code in directory DIR. Usually + `configure' can determine that directory automatically. + +`--version' + Print the version of Autoconf used to generate the `configure' + script, and exit. + +`configure' also accepts some other, not widely useful, options. + diff --git a/modules/cfitsio/README b/modules/cfitsio/README new file mode 100644 index 0000000..dd37d43 --- /dev/null +++ b/modules/cfitsio/README @@ -0,0 +1,87 @@ +The code here provides a slang module for the CFITSIO library. It +also provides a higher-level interface to the module via the slang +wrappers in src/fits.sl. + +See the documentation in the doc/ directory for information +about using the module, or, for the most up to date version, see +. + +To build the code, you will need the following additional libraries: + + 1. The slang library (http://www.jedsoft.org/slang/) + 2. The CFITSIO library + (http://heasarc.gsfc.nasa.gov/docs/software/fitsio/fitsio.html) + + *** NOTE: You may already have the cfitsio library installed as part + of some other package, e.g., CIAO, LHEASOFT, HEADAS, etc. Although + unrecommended, if you want to link against cfitsio in one of these + packages, be aware that the library may have been renamed to a + package specific name, e.g., libcxccfitsio. As such, the configure + script may not be able to find the library. If this happens, you + will have to edit the cfitsio specific variables in src/Makefile. + + *** NOTE: The cfitsio developers have informed me that they make no + guarantees of binary compatibility between releases. Hence, if you + upgrade your cfitsio library, then you should recompile the cfitsio + module and anything else that depends upon the upgraded library. + This is also true if you have linked against a package-specific + version of cfitsio (e.g., from HEADAS) and you have upgraded the + package. + +You must run the configure script before you can compile the module. +If either the slang or cfitsio libraries are installed in +non-standard locations, then you will need to specify the locations of +these libraries as arguments to the configure script. For example, +suppose libslang.so is located in /home/bill/lib and its include file +slang.h is located in /home/bill/include. Similarly, assume the cfitsio +library and include files are located in /home/bill/opt/lib and +/home/bill/opt/include, respectively. Then one would run the +configure script using: + + ./configure --with-slanglib=/home/bill/lib \ + --with-slanginc=/home/bill/include \ + --with-cfitsiolib=/home/bill/opt/lib \ + --with-cfitsioinc=/home/bill/opt/include + +or, the shorter form which assumes a common pathname prefix for the +lib include directories: + + + ./configure --with-slang=/home/bill --with-cfitsio=/home/bill/opt + +You should also specify a location for the modules (*.so) and any associated +script (*.sl) files created by this package. The default location for +the modules is in + + $prefix/lib/slang/modules/ + +Any .sl files will be installed in + + $exec_prefix/share/slsh/local-packages/ + +where the values of the variable $prefix defaults to /usr/local, and +that of $exec_prefix to the value of $prefix. These values may be +changed using the --prefix and --exec-prefix configure script +parameters. For example, to set the value of $prefix to /home/bill, +use + + ./configure --prefix=/home/bill ... + +For more help using the configure script, run it using + + ./configure --help + +It is also a good idea to read the INSTALL.txt file located in this +directory. + +Once the configure script has been run, it is a good idea to inspect +the Makefile that it generated in the src directory. Then building +and installing the library should involve nothing more than: + + make + make install + +You may have to have root privileges to peform the last step. + + + diff --git a/modules/cfitsio/autoconf/Makefile.in b/modules/cfitsio/autoconf/Makefile.in new file mode 100644 index 0000000..703b95e --- /dev/null +++ b/modules/cfitsio/autoconf/Makefile.in @@ -0,0 +1,24 @@ +# -*- sh -*- + +@SET_MAKE@ +SHELL = /bin/sh + +all: + cd src; $(MAKE) all +clean: + /bin/rm -f *~ \#* + cd src; $(MAKE) clean +distclean: clean + cd src; $(MAKE) distclean +install: + cd src; $(MAKE) install +# +# These targets are used by the maintainer +# +configure: autoconf/aclocal.m4 autoconf/configure.in + cd autoconf && autoconf && mv ./configure .. +update: autoconf/config.sub autoconf/config.guess +autoconf/config.guess: /usr/share/misc/config.guess + /bin/cp -f /usr/share/misc/config.guess autoconf/config.guess +autoconf/config.sub: /usr/share/misc/config.sub + /bin/cp -f /usr/share/misc/config.sub autoconf/config.sub diff --git a/modules/cfitsio/autoconf/aclocal.m4 b/modules/cfitsio/autoconf/aclocal.m4 new file mode 100644 index 0000000..d7b8e55 --- /dev/null +++ b/modules/cfitsio/autoconf/aclocal.m4 @@ -0,0 +1,1002 @@ +dnl# -*- mode: sh; mode: fold -*- +dnl# Version 0.1.10: rpath support for netbsd +dnl# Version 0.1.9: When searching for libs, use dylib on darwin +dnl# Version 0.1.8: Add rpath support for OpenBSD +dnl# Version 0.1.7: removed "-K pic" from IRIX compiler lines +dnl# Version 0.1.6: Added cygwin module support +dnl# Version 0.1.5: Added gcc version-script support. +dnl# + +AC_DEFUN(JD_INIT, dnl#{{{ +[ +#These variable are initialized by JD init function +CONFIG_DIR=`pwd` +cd $srcdir +if test "`pwd`" != "$CONFIG_DIR" +then + AC_MSG_ERROR("This software does not support configuring from another directory. See the INSTALL file") +fi +dnl# if test "X$PWD" != "X" +dnl# then +dnl# CONFIG_DIR="$PWD" +dnl# fi +AC_SUBST(CONFIG_DIR)dnl +# Note: these will differ if one is a symbolic link +if test -f /usr/bin/dirname; then + JD_Above_Dir=`dirname $CONFIG_DIR` +else +# system is a loser + JD_Above_Dir=`cd ..;pwd` +fi +JD_Above_Dir2=`cd ..;pwd` +]) +dnl#}}} + +dnl# This function expand the "prefix variables. For example, it will expand +dnl# values such as ${exec_prefix}/foo when ${exec_prefix} itself has a +dnl# of ${prefix}. This function produces the shell variables: +dnl# jd_prefix_libdir, jd_prefix_incdir +AC_DEFUN(JD_EXPAND_PREFIX, dnl#{{{ +[ + if test "X$jd_prefix" = "X" + then + jd_prefix=$ac_default_prefix + if test "X$prefix" != "XNONE" + then + jd_prefix="$prefix" + fi + jd_exec_prefix="$jd_prefix" + if test "X$exec_prefix" != "XNONE" + then + jd_exec_prefix="$exec_prefix" + fi + + dnl#Unfortunately, exec_prefix may have a value like ${prefix}, etc. + dnl#Let the shell expand those. Yuk. + eval `sh <>)dnl +define(<<$2>>, translit($1, [a-z], [A-Z]))dnl +changequote([, ])dnl +]) +#}}} + +AC_DEFUN(JD_SIMPLE_LIB_DIR, dnl#{{{ +[ +JD_UPPERCASE($1,JD_UP_NAME) +JD_UP_NAME[]_LIB_DIR=$JD_Above_Dir/$1/libsrc/"$ARCH"objs +JD_UP_NAME[]_INCLUDE=$JD_Above_Dir/$1/libsrc + +if test ! -d "[$]JD_UP_NAME[]_INCLUDE" +then + JD_UP_NAME[]_LIB_DIR=$JD_Above_Dir/$1/src/"$ARCH"objs + JD_UP_NAME[]_INCLUDE=$JD_Above_Dir/$1/src + if test ! -d "[$]JD_UP_NAME[]_INCLUDE" + then + echo "" + echo WARNING------Unable to find the JD_UP_NAME directory + echo You may have to edit $CONFIG_DIR/src/Makefile. + echo "" + fi +fi + +AC_SUBST(JD_UP_NAME[]_LIB_DIR)dnl +AC_SUBST(JD_UP_NAME[]_INCLUDE)dnl +undefine([JD_UP_NAME])dnl +]) + + +dnl#}}} + +AC_DEFUN(JD_FIND_GENERIC, dnl#{{{ +[ + AC_REQUIRE([JD_EXPAND_PREFIX])dnl + + changequote(<<, >>)dnl + define(<>, translit($1, [a-z], [A-Z]))dnl + changequote([, ])dnl +# Look for the JD_UP_NAME package +#JD_UP_NAME[]_INCLUDE="" +#JD_UP_NAME[]_LIB_DIR="" + +# This list consists of "include,lib include,lib ..." +JD_Search_Dirs="$JD_Above_Dir2/$1/libsrc,$JD_Above_Dir2/$1/libsrc/"$ARCH"objs \ + $JD_Above_Dir/$1/libsrc,$JD_Above_Dir/$1/libsrc/"$ARCH"objs \ + $JD_Above_Dir2/$1/src,$JD_Above_Dir2/$1/src/"$ARCH"objs \ + $JD_Above_Dir/$1/src,$JD_Above_Dir/$1/src/"$ARCH"objs" + +JD_Search_Dirs="$JD_Search_Dirs \ + $jd_prefix_incdir,$jd_prefix_libdir \ + $HOME/include,$HOME/lib" + +if test -n "$ARCH" +then + JD_Search_Dirs="$JD_Search_Dirs $HOME/include,$HOME/$ARCH/lib" + JD_Search_Dirs="$JD_Search_Dirs $HOME/include,$HOME/sys/$ARCH/lib" +fi + +# Now add the standard system includes. The reason for doing this is that +# the other directories may have a better chance of containing a more recent +# version. + +JD_Search_Dirs="$JD_Search_Dirs \ + /usr/local/include,/usr/local/lib \ + /usr/include,/usr/lib \ + /usr/include/$1,/usr/lib \ + /usr/include/$1,/usr/lib/$1" + +echo looking for the JD_UP_NAME library + +for include_and_lib in $JD_Search_Dirs +do + # Yuk. Is there a better way to set these variables?? + generic_include=`echo $include_and_lib | tr ',' ' ' | awk '{print [$]1}'` + generic_lib=`echo $include_and_lib | tr ',' ' ' | awk '{print [$]2}'` + echo Looking for $1.h in $generic_include + echo and lib$1.a in $generic_lib + if test -r $generic_include/$1.h && test -r $generic_lib/lib$1.a + then + echo Found it. + JD_UP_NAME[]_LIB_DIR="$generic_lib" + JD_UP_NAME[]_INCLUDE="$generic_include" + break + else + if test -r $generic_include/$1.h && test -r $generic_lib/lib$1.so + then + echo Found it. + JD_UP_NAME[]_LIB_DIR="$generic_lib" + JD_UP_NAME[]_INCLUDE="$generic_include" + break + fi + fi +done + +if test -n "[$]JD_UP_NAME[]_LIB_DIR" +then + jd_have_$1="yes" +else + echo Unable to find the $JD_UP_NAME library. + echo You may have to edit $CONFIG_DIR/src/Makefile. + JD_UP_NAME[]_INCLUDE=$JD_Above_Dir/$1/src + JD_UP_NAME[]_LIB_DIR=$JD_Above_Dir/$1/src/"$ARCH"objs + jd_have_$1="no" +fi + +JD_UP_NAME[]_INC="-I[$]JD_UP_NAME[]_INCLUDE" +JD_UP_NAME[]_LIB="-L[$]JD_UP_NAME[]_LIB_DIR" +JD_SET_RPATH([$]JD_UP_NAME[]_LIB_DIR) +dnl if test "X$GCC" = Xyes +dnl then +dnl RPATH_[]JD_UP_NAME="-Wl,-R[$]JD_UP_NAME[]_LIB_DIR" +dnl else +dnl RPATH_[]JD_UP_NAME="-R[$]JD_UP_NAME[]_LIB_DIR" +dnl fi + +# gcc under solaris is often not installed correctly. Avoid specifying +# -I/usr/include. +if test "[$]JD_UP_NAME[]_INC" = "-I/usr/include" +then + JD_UP_NAME[]_INC="" +fi + +if test "[$]JD_UP_NAME[]_LIB" = "-L/usr/lib" +then + JD_UP_NAME[]_LIB="" + RPATH_[]JD_UP_NAME="" +fi + +AC_SUBST(JD_UP_NAME[]_LIB)dnl +AC_SUBST(JD_UP_NAME[]_INC)dnl +AC_SUBST(JD_UP_NAME[]_LIB_DIR)dnl +AC_SUBST(JD_UP_NAME[]_INCLUDE)dnl +dnl AC_SUBST(RPATH_[]JD_UP_NAME)dnl +undefine([JD_UP_NAME])dnl +]) + + +dnl#}}} + +AC_DEFUN(JD_FIND_SLANG, dnl#{{{ +[ +JD_FIND_GENERIC(slang) +]) + +dnl#}}} + +AC_DEFUN(JD_GCC_WARNINGS, dnl#{{{ +[ +AC_ARG_ENABLE(warnings, + [ --enable-warnings turn on GCC compiler warnings], + [gcc_warnings=$enableval]) +if test -n "$GCC" +then + #CFLAGS="$CFLAGS -fno-strength-reduce" + if test -n "$gcc_warnings" + then + CFLAGS="$CFLAGS -Wall -W -pedantic -Winline -Wmissing-prototypes \ + -Wnested-externs -Wpointer-arith -Wcast-align -Wshadow -Wstrict-prototypes" + # Now trim excess whitespace + CFLAGS=`echo $CFLAGS` + fi +fi +]) + + +dnl#}}} + +IEEE_CFLAGS="" +AC_DEFUN(JD_IEEE_CFLAGS, dnl#{{{ +[ +case "$host_cpu" in + *alpha* ) + if test "$GCC" = yes + then + IEEE_CFLAGS="-mieee" + else + IEEE_CFLAGS="-ieee_with_no_inexact" + fi + ;; + * ) + IEEE_CFLAGS="" +esac +]) + + +dnl#}}} + +AC_DEFUN(JD_CREATE_ORULE, dnl#{{{ +[ +PROGRAM_OBJECT_RULES="$PROGRAM_OBJECT_RULES +\$(OBJDIR)/$1.o : \$(SRCDIR)/$1.c \$(DOT_O_DEPS) \$("$1"_O_DEP) + cd \$(OBJDIR); \$(COMPILE_CMD) \$("$1"_C_FLAGS) \$(SRCDIR)/$1.c +" +]) + +dnl#}}} + +AC_DEFUN(JD_CREATE_ELFORULE, dnl#{{{ +[ +PROGRAM_ELF_ORULES="$PROGRAM_ELF_ORULES +\$(ELFDIR)/$1.o : \$(SRCDIR)/$1.c \$(DOT_O_DEPS) \$("$1"_O_DEP) + cd \$(ELFDIR); \$(ELFCOMPILE_CMD) \$("$1"_C_FLAGS) \$(SRCDIR)/$1.c +" +]) + + +dnl#}}} + +AC_DEFUN(JD_CREATE_EXEC_RULE, dnl#{{{ +[ +PROGRAM_OBJECT_RULES="$PROGRAM_OBJECT_RULES +$1 : \$(OBJDIR)/$1 + @echo $1 created in \$(OBJDIR) +\$(OBJDIR)/$1 : \$(OBJDIR)/$1.o \$("$1"_DEPS) \$(EXECDEPS) + \$(CC) -o \$(OBJDIR)/$1 \$(LDFLAGS) \$(OBJDIR)/$1.o \$("$1"_LIBS) \$(EXECLIBS) +\$(OBJDIR)/$1.o : \$(SRCDIR)/$1.c \$(DOT_O_DEPS) \$("$1"_O_DEP) + cd \$(OBJDIR); \$(COMPILE_CMD) \$("$1"_INC) \$(EXECINC) \$(SRCDIR)/$1.c +" +]) + + +dnl#}}} + +AC_DEFUN(JD_CREATE_MODULE_ORULES, dnl#{{{ +[ + for program_module in $Program_Modules; do + JD_CREATE_ORULE($program_module) + JD_CREATE_ELFORULE($program_module) + done +]) + +dnl#}}} + +AC_DEFUN(JD_GET_MODULES, dnl#{{{ +[ + PROGRAM_HFILES="" + PROGRAM_OFILES="" + PROGRAM_CFILES="" + PROGRAM_OBJECTS="" + PROGRAM_ELFOBJECTS="" + PROGRAM_OBJECT_RULES="" + PROGRAM_ELF_ORULES="" + if test -z "$1" + then + Program_Modules="" + else + comment_re="^#" + Program_Modules=`grep -v '$comment_re' $1 | awk '{print [$]1}'` + Program_H_Modules=`grep -v '$comment_re' $1 | awk '{print [$]2}'` + for program_module in $Program_H_Modules; do + PROGRAM_HFILES="$PROGRAM_HFILES $program_module" + done + fi + for program_module in $Program_Modules; do + PROGRAM_OFILES="$PROGRAM_OFILES $program_module.o" + PROGRAM_CFILES="$PROGRAM_CFILES $program_module.c" + PROGRAM_OBJECTS="$PROGRAM_OBJECTS \$(OBJDIR)/$program_module.o" + PROGRAM_ELFOBJECTS="$PROGRAM_ELFOBJECTS \$(ELFDIR)/$program_module.o" + done +dnl echo $PROGRAM_OFILES +dnl echo $PROGRAM_HFILES +AC_SUBST(PROGRAM_OFILES)dnl +AC_SUBST(PROGRAM_CFILES)dnl +AC_SUBST(PROGRAM_HFILES)dnl +AC_SUBST(PROGRAM_OBJECTS)dnl +AC_SUBST(PROGRAM_ELFOBJECTS)dnl +]) + + +dnl#}}} + +AC_DEFUN(JD_APPEND_RULES, dnl#{{{ +[ + echo "$PROGRAM_OBJECT_RULES" >> $1 +]) + + +dnl#}}} + +AC_DEFUN(JD_APPEND_ELFRULES, dnl#{{{ +[ + echo "$PROGRAM_ELF_ORULES" >> $1 +]) + +dnl#}}} + +AC_DEFUN(JD_CREATE_MODULE_EXEC_RULES, dnl#{{{ +[ + for program_module in $Program_Modules; do + JD_CREATE_EXEC_RULE($program_module) + done +]) + +dnl#}}} + +AC_DEFUN(JD_TERMCAP, dnl#{{{ +[ +AC_MSG_CHECKING(for Terminfo) +MISC_TERMINFO_DIRS="$FINKPREFIX/share/terminfo" +if test ! -d $MISC_TERMINFO_DIRS +then + MISC_TERMINFO_DIRS="" +fi + +JD_Terminfo_Dirs="/usr/lib/terminfo \ + /usr/share/terminfo \ + /usr/share/lib/terminfo \ + /usr/local/lib/terminfo \ + $MISC_TERMINFO_DIRS" + +TERMCAP=-ltermcap + +for terminfo_dir in $JD_Terminfo_Dirs +do + if test -d $terminfo_dir + then + AC_MSG_RESULT(yes) + TERMCAP="" + break + fi +done +if test "$TERMCAP"; then + AC_MSG_RESULT(no) + AC_DEFINE(USE_TERMCAP) +fi +AC_SUBST(TERMCAP)dnl +AC_SUBST(MISC_TERMINFO_DIRS)dnl +]) + + +dnl#}}} + +AC_DEFUN(JD_ANSI_CC, dnl#{{{ +[ +AC_PROG_CC +AC_PROG_CPP +AC_PROG_GCC_TRADITIONAL +AC_ISC_POSIX +AC_AIX + +dnl #This stuff came from Yorick config script +dnl +dnl # HPUX needs special stuff +dnl +AC_EGREP_CPP(yes, +[#ifdef hpux + yes +#endif +], [ +AC_DEFINE(_HPUX_SOURCE) +if test "$CC" = cc; then CC="cc -Ae"; fi +])dnl +dnl +dnl #Be sure we've found compiler that understands prototypes +dnl +AC_MSG_CHECKING(C compiler that understands ANSI prototypes) +AC_TRY_COMPILE([ ],[ + extern int silly (int);], [ + AC_MSG_RESULT($CC looks ok. Good.)], [ + AC_MSG_RESULT($CC is not a good enough compiler) + AC_MSG_ERROR(Set env variable CC to your ANSI compiler and rerun configure.) + ])dnl +])dnl + +dnl#}}} + + +AC_DEFUN(JD_ELF_COMPILER, dnl#{{{ +[ +dnl #------------------------------------------------------------------------- +dnl # Check for dynamic linker +dnl #------------------------------------------------------------------------- +DYNAMIC_LINK_LIB="" +AC_CHECK_HEADER(dlfcn.h,[ + AC_DEFINE(HAVE_DLFCN_H) + AC_CHECK_LIB(dl,dlopen,[ + DYNAMIC_LINK_LIB="-ldl" + AC_DEFINE(HAVE_DLOPEN) + ],[ + AC_CHECK_FUNC(dlopen,AC_DEFINE(HAVE_DLOPEN)) + if test "$ac_cv_func_dlopen" != yes + then + AC_MSG_WARN(cannot perform dynamic linking) + fi + ])]) +AC_SUBST(DYNAMIC_LINK_LIB) + +ELFLIB="lib\$(THIS_LIB).so" +ELFLIB_MAJOR="\$(ELFLIB).\$(ELF_MAJOR_VERSION)" +ELFLIB_MAJOR_MINOR="\$(ELFLIB).\$(ELF_MAJOR_VERSION).\$(ELF_MINOR_VERSION)" + +if test "$GCC" = yes +then + if test X"$CFLAGS" = X + then + CFLAGS="-O2" + fi +fi + +INSTALL_MODULE="\$(INSTALL_DATA)" + +case "$host_os" in + *linux*|*gnu*|k*bsd*-gnu ) + DYNAMIC_LINK_FLAGS="-Wl,-export-dynamic" + ELF_CC="\$(CC)" + ELF_CFLAGS="\$(CFLAGS) -fPIC" + ELF_LINK="\$(CC) \$(LDFLAGS) -shared -Wl,-O1 -Wl,--version-script,\$(VERSION_SCRIPT) -Wl,-soname,\$(ELFLIB_MAJOR)" + ELF_DEP_LIBS="\$(DL_LIB) -lm -lc" + CC_SHARED="\$(CC) \$(CFLAGS) -shared -fPIC" + ;; + *solaris* ) + if test "$GCC" = yes + then + DYNAMIC_LINK_FLAGS="" + ELF_CC="\$(CC)" + ELF_CFLAGS="\$(CFLAGS) -fPIC" + ELF_LINK="\$(CC) \$(LDFLAGS) -shared -Wl,-ztext -Wl,-h,\$(ELFLIB_MAJOR)" + ELF_DEP_LIBS="\$(DL_LIB) -lm -lc" + CC_SHARED="\$(CC) \$(CFLAGS) -G -fPIC" + else + DYNAMIC_LINK_FLAGS="" + ELF_CC="\$(CC)" + ELF_CFLAGS="\$(CFLAGS) -K PIC" + ELF_LINK="\$(CC) \$(LDFLAGS) -G -h\$(ELFLIB_MAJOR)" + ELF_DEP_LIBS="\$(DL_LIB) -lm -lc" + CC_SHARED="\$(CC) \$(CFLAGS) -G -K PIC" + fi + ;; + # osr5 or unixware7 with current or late autoconf + *sco3.2v5* | *unixware-5* | *sco-sysv5uw7*) + if test "$GCC" = yes + then + DYNAMIC_LINK_FLAGS="" + ELF_CC="\$(CC)" + ELF_CFLAGS="\$(CFLAGS) -fPIC" + ELF_LINK="\$(CC) \$(LDFLAGS) -shared -Wl,-h,\$(ELFLIB_MAJOR)" + ELF_DEP_LIBS= + CC_SHARED="\$(CC) \$(CFLAGS) -G -fPIC" + else + DYNAMIC_LINK_FLAGS="" + ELF_CC="\$(CC)" + ELF_CFLAGS="\$(CFLAGS) -K pic" + # ELF_LINK="ld -G -z text -h#" + ELF_LINK="\$(CC) \$(LDFLAGS) -G -z text -h\$(ELFLIB_MAJOR)" + ELF_DEP_LIBS= + CC_SHARED="\$(CC) \$(CFLAGS) -G -K pic" + fi + ;; + *irix6.5* ) + echo "Note: ELF compiler for host_os=$host_os may not be correct" + echo "double-check: 'mode_t', 'pid_t' may be wrong!" + if test "$GCC" = yes + then + # not tested + DYNAMIC_LINK_FLAGS="" + ELF_CC="\$(CC)" + ELF_CFLAGS="\$(CFLAGS) -fPIC" + ELF_LINK="\$(CC) \$(LDFLAGS) -shared -Wl,-h,\$(ELFLIB_MAJOR)" + ELF_DEP_LIBS= + CC_SHARED="\$(CC) \$(CFLAGS) -shared -fPIC" + else + DYNAMIC_LINK_FLAGS="" + ELF_CC="\$(CC)" + ELF_CFLAGS="\$(CFLAGS)" # default anyhow + ELF_LINK="\$(CC) \$(LDFLAGS) -shared -o \$(ELFLIB_MAJOR)" + ELF_DEP_LIBS= + CC_SHARED="\$(CC) \$(CFLAGS) -shared" + fi + ;; + *darwin* ) + DYNAMIC_LINK_FLAGS="" + ELF_CC="\$(CC)" + ELF_CFLAGS="\$(CFLAGS) -fno-common" + ELF_LINK="\$(CC) \$(LDFLAGS) -dynamiclib -install_name \$(install_lib_dir)/\$(ELFLIB_MAJOR) -compatibility_version \$(ELF_MAJOR_VERSION) -current_version \$(ELF_MAJOR_VERSION).\$(ELF_MINOR_VERSION)" + ELF_DEP_LIBS="\$(LDFLAGS) \$(DL_LIB)" + CC_SHARED="\$(CC) -bundle -flat_namespace -undefined suppress \$(CFLAGS) -fno-common" + ELFLIB="lib\$(THIS_LIB).dylib" + ELFLIB_MAJOR="lib\$(THIS_LIB).\$(ELF_MAJOR_VERSION).dylib" + ELFLIB_MAJOR_MINOR="lib\$(THIS_LIB).\$(ELF_MAJOR_VERSION).\$(ELF_MINOR_VERSION).dylib" + ;; + *freebsd* ) + ELFLIB_MAJOR_MINOR="\$(ELFLIB).\$(ELF_MAJOR_VERSION)" + ELF_CC="\$(CC)" + ELF_CFLAGS="\$(CFLAGS) -fPIC" + if test "X$PORTOBJFORMAT" = "Xelf" ; then + ELF_LINK="\$(CC) \$(LDFLAGS) -shared -Wl,-soname,\$(ELFLIB_MAJOR)" + else + ELF_LINK="ld -Bshareable -x" + fi + ELF_DEP_LIBS="\$(DL_LIB) -lm" + CC_SHARED="\$(CC) \$(CFLAGS) -shared -fPIC" + ;; + *cygwin* ) + DYNAMIC_LINK_FLAGS="" + ELF_CC="\$(CC)" + ELF_CFLAGS="\$(CFLAGS) " + DLL_IMPLIB_NAME="lib\$(THIS_LIB)\$(ELFLIB_MAJOR_VERSION).dll.a" + ELF_LINK="\$(CC) \$(LDFLAGS) -shared -Wl,-O1 -Wl,--version-script,\$(VERSION_SCRIPT) -Wl,-soname,\$(ELFLIB_MAJOR) -Wl,--out-implib=\$(DLL_IMPLIB_NAME) -Wl,-export-all-symbols -Wl,-enable-auto-import" + ELF_DEP_LIBS="\$(DL_LIB) -lm" + CC_SHARED="\$(CC) \$(CFLAGS) -shared" + dnl# CYGWIN prohibits undefined symbols when linking shared libs + SLANG_LIB_FOR_MODULES="-L\$(ELFDIR) -lslang" + INSTALL_MODULE="\$(INSTALL)" + ;; + * ) + echo "Note: ELF compiler for host_os=$host_os may be wrong" + ELF_CC="\$(CC)" + ELF_CFLAGS="\$(CFLAGS) -fPIC" + ELF_LINK="\$(CC) \$(LDFLAGS) -shared" + ELF_DEP_LIBS="\$(DL_LIB) -lm -lc" + CC_SHARED="\$(CC) \$(CFLAGS) -shared -fPIC" +esac + +AC_SUBST(ELF_CC) +AC_SUBST(ELF_CFLAGS) +AC_SUBST(ELF_LINK) +AC_SUBST(ELF_LINK_CMD) +AC_SUBST(ELF_DEP_LIBS) +AC_SUBST(DYNAMIC_LINK_FLAGS) +AC_SUBST(CC_SHARED) +AC_SUBST(ELFLIB) +AC_SUBST(ELFLIB_MAJOR) +AC_SUBST(ELFLIB_MAJOR_MINOR) +AC_SUBST(SLANG_LIB_FOR_MODULES) +AC_SUBST(DLL_IMPLIB_NAME) +AC_SUBST(INSTALL_MODULE) +]) + + +dnl#}}} + +AC_DEFUN(JD_F77_COMPILER, dnl#{{{ +[ +case "$host_os" in + *linux* ) + F77="g77" + F77_LIBS="-lg2c" + ;; + *solaris*) + F77=f77 + #F77_LIBS="-lF77 -lM77 -L/opt/SUNWspro/SC4.0/lib -lsunmath" + F77_LIBS="-lF77 -lM77 -lsunmath" + ;; + *) + echo "" + echo "WARNING: Assuming f77 as your FORTRAN compiler" + echo "" + F77=f77 + F77_LIBS="" +esac +AC_SUBST(F77) +AC_SUBST(F77_LIBS) +]) + + + +dnl#}}} + +dnl# This macro process the --with-xxx, --with-xxxinc, and --with-xxxlib +dnl# command line arguments and returns the values as shell variables +dnl# jd_xxx_include_dir and jd_xxx_library_dir. It does not perform any +dnl# substitutions, nor check for the existence of the supplied values. +AC_DEFUN(JD_WITH_LIBRARY_PATHS, dnl#{{{ +[ + JD_UPPERCASE($1,JD_ARG1) + jd_$1_include_dir="" + jd_$1_library_dir="" + jd_with_$1_library="" + + AC_ARG_WITH($1, + [ --with-$1=DIR Use DIR/lib and DIR/include for $1], + [jd_with_$1_arg=$withval], [jd_with_$1_arg=unspecified]) + + case "x$jd_with_$1_arg" in + xno) + jd_with_$1_library="no" + ;; + x) + AC_MSG_ERROR(--with-$1 requires a value-- try yes or no) + ;; + xunspecified) + ;; + xyes) + ;; + *) + jd_$1_include_dir="$jd_with_$1_arg"/include + jd_$1_library_dir="$jd_with_$1_arg"/lib + ;; + esac + + AC_ARG_WITH($1lib, + [ --with-$1lib=DIR $1 library in DIR], + [jd_with_$1lib_arg=$withval], [jd_with_$1lib_arg=unspecified]) + case "x$jd_with_$1lib_arg" in + xunspecified) + ;; + xno) + ;; + x) + AC_MSG_ERROR(--with-$1lib requres a value) + ;; + *) + jd_$1_library_dir="$jd_with_$1lib_arg" + ;; + esac + + AC_ARG_WITH($1inc, + [ --with-$1inc=DIR $1 include files in DIR], + [jd_with_$1inc_arg=$withval], [jd_with_$1inc_arg=unspecified]) + case "x$jd_with_$1inc_arg" in + x) + AC_MSG_ERROR(--with-$1inc requres a value) + ;; + xunspecified) + ;; + xno) + ;; + *) + jd_$1_include_dir="$jd_with_$1inc_arg" + ;; + esac +]) +dnl#}}} + +dnl# This function checks for the existence of the specified library $1 with +dnl# header file $2. If the library exists, then the shell variables will +dnl# be created: +dnl# jd_with_$1_library=yes/no, +dnl# jd_$1_inc_file +dnl# jd_$1_include_dir +dnl# jd_$1_library_dir +AC_DEFUN(JD_CHECK_FOR_LIBRARY, dnl#{{{ +[ + AC_REQUIRE([JD_EXPAND_PREFIX])dnl + AC_MSG_CHECKING(for the $1 library and header files $2) + dnl JD_UPPERCASE($1,JD_ARG1) + JD_WITH_LIBRARY_PATHS($1) + if test X"$jd_with_$1_library" = X + then + jd_$1_inc_file=$2 + jd_with_$1_library="yes" + + if test "X$jd_$1_inc_file" = "X" + then + jd_$1_inc_file=$1.h + fi + if test X"$jd_$1_include_dir" = X + then + lib_include_dirs="\ + $jd_prefix_incdir \ + /usr/local/$1/include \ + /usr/local/include/$1 \ + /usr/local/include \ + /usr/include/$1 \ + /usr/$1/include \ + /usr/include \ + /opt/include/$1 \ + /opt/$1/include \ + /opt/include" + + for X in $lib_include_dirs + do + if test -r "$X/$jd_$1_inc_file" + then + jd_$1_include_dir="$X" + break + fi + done + if test X"$jd_$1_include_dir" = X + then + jd_with_$1_library="no" + fi + fi + + if test X"$jd_$1_library_dir" = X + then + lib_library_dirs="\ + $jd_prefix_libdir \ + /usr/local/lib \ + /usr/local/lib/$1 \ + /usr/local/$1/lib \ + /usr/lib \ + /usr/lib/$1 \ + /usr/$1/lib \ + /opt/lib \ + /opt/lib/$1 \ + /opt/$1/lib" + + case "$host_os" in + *darwin* ) + exts="dylib so a" + ;; + * ) + exts="so a" + esac + + found=0 + for X in $lib_library_dirs + do + for E in $exts + do + if test -r "$X/lib$1.$E" + then + jd_$1_library_dir="$X" + found=1 + break + fi + done + if test $found -eq 1 + then + break + fi + done + if test X"$jd_$1_library_dir" = X + then + jd_with_$1_library="no" + fi + fi + fi + + if test "$jd_with_$1_library" = "yes" + then + AC_MSG_RESULT(yes: $jd_$1_library_dir and $jd_$1_include_dir) + dnl# Avoid using /usr/lib and /usr/include because of problems with + dnl# gcc on some solaris systems. + JD_ARG1[]_LIB=-L$jd_$1_library_dir + if test "X$jd_$1_library_dir" = "X/usr/lib" + then + JD_ARG1[]_LIB="" + else + JD_SET_RPATH($jd_$1_library_dir) + fi + + JD_ARG1[]_INC=-I$jd_$1_include_dir + if test "X$jd_$1_include_dir" = "X/usr/include" + then + JD_ARG1[]_INC="" + fi + else + AC_MSG_RESULT(no) + JD_ARG1[]_INC="" + JD_ARG1[]_LIB="" + fi + AC_SUBST(JD_ARG1[]_LIB) + AC_SUBST(JD_ARG1[]_INC) +]) +dnl#}}} + +AC_DEFUN(JD_WITH_LIBRARY, dnl#{{{ +[ + JD_CHECK_FOR_LIBRARY($1, $2) + if test "$jd_with_$1_library" = "no" + then + AC_MSG_ERROR(unable to find the $1 library and header file $jd_$1_inc_file) + fi +]) +dnl#}}} + +AC_DEFUN(JD_SLANG_VERSION, dnl#{{{ +[ + slang_h=$jd_slang_include_dir/slang.h + AC_MSG_CHECKING(SLANG_VERSION in $slang_h) +slang_version=`grep "^#define *SLANG_VERSION " $slang_h | + awk '{ print [$]3 }'` +slang_major_version=`echo $slang_version | + awk '{ print int([$]1/10000) }'` +slang_minor_version=`echo $slang_version $slang_major_version | + awk '{ print int(([$]1 - [$]2*10000)/100) }'` +slang_patchlevel_version=`echo $slang_version $slang_major_version $slang_minor_version | + awk '{ print ([$]1 - [$]2*10000 - [$]3*100) }'` + +AC_MSG_RESULT($slang_major_version.$slang_minor_version.$slang_patchlevel_version) +AC_SUBST(slang_version) +AC_SUBST(slang_major_version) +AC_SUBST(slang_minor_version) +AC_SUBST(slang_patchlevel_version) +]) +#}}} + +AC_DEFUN(JD_SLANG_MODULE_INSTALL_DIR, dnl#{{{ +[ + AC_REQUIRE([JD_SLANG_VERSION]) + if test "X$slang_major_version" = "X1" + then + MODULE_INSTALL_DIR="$libdir/slang/modules" + else + MODULE_INSTALL_DIR="$libdir/slang/v$slang_major_version/modules" + fi + SL_FILES_INSTALL_DIR=$datadir/slsh/local-packages + AC_SUBST(MODULE_INSTALL_DIR) + AC_SUBST(SL_FILES_INSTALL_DIR) +]) +#}}} + +AC_DEFUN(JD_CHECK_LONG_LONG, dnl#{{{ +[ + AC_CHECK_TYPES(long long) + AC_CHECK_SIZEOF(long long) +]) +dnl#}}} + +AC_DEFUN(JD_LARGE_FILE_SUPPORTXXX, dnl#{{{ +[ + AC_REQUIRE([JD_CHECK_LONG_LONG]) + AC_MSG_CHECKING(whether to explicitly activate long file support) + AC_DEFINE(_LARGEFILE_SOURCE, 1) + AC_DEFINE(_FILE_OFFSET_BITS, 64) + jd_large_file_support=no + if test X$ac_cv_type_long_long = Xyes + then + if test $ac_cv_sizeof_long_long -ge 8 + then + jd_large_file_support=yes + fi + fi + + if test $jd_large_file_support = yes + then + AC_DEFINE(HAVE_LARGEFILE_SUPPORT, 1) + AC_MSG_RESULT(yes) + else + AC_MSG_RESULT(no) + fi +]) +dnl#}}} + +AC_DEFUN(JD_LARGE_FILE_SUPPORT, dnl#{{{ +[ + AC_SYS_LARGEFILE + AC_FUNC_FSEEKO + AC_TYPE_OFF_T + AC_CHECK_SIZEOF(off_t) +]) +#}}} + +AC_DEFUN(JD_HAVE_ISINF, dnl#{{{ +[ + AC_MSG_CHECKING([for isinf]) + AC_LINK_IFELSE([AC_LANG_PROGRAM( [[#include ]], [[isinf (0.0);]])], + [AC_MSG_RESULT([yes]) + AC_DEFINE(HAVE_ISINF, 1)]) +]) +#}}} diff --git a/modules/cfitsio/autoconf/config.guess b/modules/cfitsio/autoconf/config.guess new file mode 100755 index 0000000..396482d --- /dev/null +++ b/modules/cfitsio/autoconf/config.guess @@ -0,0 +1,1500 @@ +#! /bin/sh +# Attempt to guess a canonical system name. +# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, +# 2000, 2001, 2002, 2003, 2004, 2005, 2006 Free Software Foundation, +# Inc. + +timestamp='2006-07-02' + +# This file is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA +# 02110-1301, USA. +# +# As a special exception to the GNU General Public License, if you +# distribute this file as part of a program that contains a +# configuration script generated by Autoconf, you may include it under +# the same distribution terms that you use for the rest of that program. + + +# Originally written by Per Bothner . +# Please send patches to . Submit a context +# diff and a properly formatted ChangeLog entry. +# +# This script attempts to guess a canonical system name similar to +# config.sub. If it succeeds, it prints the system name on stdout, and +# exits with 0. Otherwise, it exits with 1. +# +# The plan is that this can be called by configure scripts if you +# don't specify an explicit build system type. + +me=`echo "$0" | sed -e 's,.*/,,'` + +usage="\ +Usage: $0 [OPTION] + +Output the configuration name of the system \`$me' is run on. + +Operation modes: + -h, --help print this help, then exit + -t, --time-stamp print date of last modification, then exit + -v, --version print version number, then exit + +Report bugs and patches to ." + +version="\ +GNU config.guess ($timestamp) + +Originally written by Per Bothner. +Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005 +Free Software Foundation, Inc. + +This is free software; see the source for copying conditions. There is NO +warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." + +help=" +Try \`$me --help' for more information." + +# Parse command line +while test $# -gt 0 ; do + case $1 in + --time-stamp | --time* | -t ) + echo "$timestamp" ; exit ;; + --version | -v ) + echo "$version" ; exit ;; + --help | --h* | -h ) + echo "$usage"; exit ;; + -- ) # Stop option processing + shift; break ;; + - ) # Use stdin as input. + break ;; + -* ) + echo "$me: invalid option $1$help" >&2 + exit 1 ;; + * ) + break ;; + esac +done + +if test $# != 0; then + echo "$me: too many arguments$help" >&2 + exit 1 +fi + +trap 'exit 1' 1 2 15 + +# CC_FOR_BUILD -- compiler used by this script. Note that the use of a +# compiler to aid in system detection is discouraged as it requires +# temporary files to be created and, as you can see below, it is a +# headache to deal with in a portable fashion. + +# Historically, `CC_FOR_BUILD' used to be named `HOST_CC'. We still +# use `HOST_CC' if defined, but it is deprecated. + +# Portable tmp directory creation inspired by the Autoconf team. + +set_cc_for_build=' +trap "exitcode=\$?; (rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null) && exit \$exitcode" 0 ; +trap "rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null; exit 1" 1 2 13 15 ; +: ${TMPDIR=/tmp} ; + { tmp=`(umask 077 && mktemp -d "$TMPDIR/cgXXXXXX") 2>/dev/null` && test -n "$tmp" && test -d "$tmp" ; } || + { test -n "$RANDOM" && tmp=$TMPDIR/cg$$-$RANDOM && (umask 077 && mkdir $tmp) ; } || + { tmp=$TMPDIR/cg-$$ && (umask 077 && mkdir $tmp) && echo "Warning: creating insecure temp directory" >&2 ; } || + { echo "$me: cannot create a temporary directory in $TMPDIR" >&2 ; exit 1 ; } ; +dummy=$tmp/dummy ; +tmpfiles="$dummy.c $dummy.o $dummy.rel $dummy" ; +case $CC_FOR_BUILD,$HOST_CC,$CC in + ,,) echo "int x;" > $dummy.c ; + for c in cc gcc c89 c99 ; do + if ($c -c -o $dummy.o $dummy.c) >/dev/null 2>&1 ; then + CC_FOR_BUILD="$c"; break ; + fi ; + done ; + if test x"$CC_FOR_BUILD" = x ; then + CC_FOR_BUILD=no_compiler_found ; + fi + ;; + ,,*) CC_FOR_BUILD=$CC ;; + ,*,*) CC_FOR_BUILD=$HOST_CC ;; +esac ; set_cc_for_build= ;' + +# This is needed to find uname on a Pyramid OSx when run in the BSD universe. +# (ghazi@noc.rutgers.edu 1994-08-24) +if (test -f /.attbin/uname) >/dev/null 2>&1 ; then + PATH=$PATH:/.attbin ; export PATH +fi + +UNAME_MACHINE=`(uname -m) 2>/dev/null` || UNAME_MACHINE=unknown +UNAME_RELEASE=`(uname -r) 2>/dev/null` || UNAME_RELEASE=unknown +UNAME_SYSTEM=`(uname -s) 2>/dev/null` || UNAME_SYSTEM=unknown +UNAME_VERSION=`(uname -v) 2>/dev/null` || UNAME_VERSION=unknown + +# Note: order is significant - the case branches are not exclusive. + +case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in + *:NetBSD:*:*) + # NetBSD (nbsd) targets should (where applicable) match one or + # more of the tupples: *-*-netbsdelf*, *-*-netbsdaout*, + # *-*-netbsdecoff* and *-*-netbsd*. For targets that recently + # switched to ELF, *-*-netbsd* would select the old + # object file format. This provides both forward + # compatibility and a consistent mechanism for selecting the + # object file format. + # + # Note: NetBSD doesn't particularly care about the vendor + # portion of the name. We always set it to "unknown". + sysctl="sysctl -n hw.machine_arch" + UNAME_MACHINE_ARCH=`(/sbin/$sysctl 2>/dev/null || \ + /usr/sbin/$sysctl 2>/dev/null || echo unknown)` + case "${UNAME_MACHINE_ARCH}" in + armeb) machine=armeb-unknown ;; + arm*) machine=arm-unknown ;; + sh3el) machine=shl-unknown ;; + sh3eb) machine=sh-unknown ;; + *) machine=${UNAME_MACHINE_ARCH}-unknown ;; + esac + # The Operating System including object format, if it has switched + # to ELF recently, or will in the future. + case "${UNAME_MACHINE_ARCH}" in + arm*|i386|m68k|ns32k|sh3*|sparc|vax) + eval $set_cc_for_build + if echo __ELF__ | $CC_FOR_BUILD -E - 2>/dev/null \ + | grep __ELF__ >/dev/null + then + # Once all utilities can be ECOFF (netbsdecoff) or a.out (netbsdaout). + # Return netbsd for either. FIX? + os=netbsd + else + os=netbsdelf + fi + ;; + *) + os=netbsd + ;; + esac + # The OS release + # Debian GNU/NetBSD machines have a different userland, and + # thus, need a distinct triplet. However, they do not need + # kernel version information, so it can be replaced with a + # suitable tag, in the style of linux-gnu. + case "${UNAME_VERSION}" in + Debian*) + release='-gnu' + ;; + *) + release=`echo ${UNAME_RELEASE}|sed -e 's/[-_].*/\./'` + ;; + esac + # Since CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM: + # contains redundant information, the shorter form: + # CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM is used. + echo "${machine}-${os}${release}" + exit ;; + *:OpenBSD:*:*) + UNAME_MACHINE_ARCH=`arch | sed 's/OpenBSD.//'` + echo ${UNAME_MACHINE_ARCH}-unknown-openbsd${UNAME_RELEASE} + exit ;; + *:ekkoBSD:*:*) + echo ${UNAME_MACHINE}-unknown-ekkobsd${UNAME_RELEASE} + exit ;; + *:SolidBSD:*:*) + echo ${UNAME_MACHINE}-unknown-solidbsd${UNAME_RELEASE} + exit ;; + macppc:MirBSD:*:*) + echo powerpc-unknown-mirbsd${UNAME_RELEASE} + exit ;; + *:MirBSD:*:*) + echo ${UNAME_MACHINE}-unknown-mirbsd${UNAME_RELEASE} + exit ;; + alpha:OSF1:*:*) + case $UNAME_RELEASE in + *4.0) + UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $3}'` + ;; + *5.*) + UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $4}'` + ;; + esac + # According to Compaq, /usr/sbin/psrinfo has been available on + # OSF/1 and Tru64 systems produced since 1995. I hope that + # covers most systems running today. This code pipes the CPU + # types through head -n 1, so we only detect the type of CPU 0. + ALPHA_CPU_TYPE=`/usr/sbin/psrinfo -v | sed -n -e 's/^ The alpha \(.*\) processor.*$/\1/p' | head -n 1` + case "$ALPHA_CPU_TYPE" in + "EV4 (21064)") + UNAME_MACHINE="alpha" ;; + "EV4.5 (21064)") + UNAME_MACHINE="alpha" ;; + "LCA4 (21066/21068)") + UNAME_MACHINE="alpha" ;; + "EV5 (21164)") + UNAME_MACHINE="alphaev5" ;; + "EV5.6 (21164A)") + UNAME_MACHINE="alphaev56" ;; + "EV5.6 (21164PC)") + UNAME_MACHINE="alphapca56" ;; + "EV5.7 (21164PC)") + UNAME_MACHINE="alphapca57" ;; + "EV6 (21264)") + UNAME_MACHINE="alphaev6" ;; + "EV6.7 (21264A)") + UNAME_MACHINE="alphaev67" ;; + "EV6.8CB (21264C)") + UNAME_MACHINE="alphaev68" ;; + "EV6.8AL (21264B)") + UNAME_MACHINE="alphaev68" ;; + "EV6.8CX (21264D)") + UNAME_MACHINE="alphaev68" ;; + "EV6.9A (21264/EV69A)") + UNAME_MACHINE="alphaev69" ;; + "EV7 (21364)") + UNAME_MACHINE="alphaev7" ;; + "EV7.9 (21364A)") + UNAME_MACHINE="alphaev79" ;; + esac + # A Pn.n version is a patched version. + # A Vn.n version is a released version. + # A Tn.n version is a released field test version. + # A Xn.n version is an unreleased experimental baselevel. + # 1.2 uses "1.2" for uname -r. + echo ${UNAME_MACHINE}-dec-osf`echo ${UNAME_RELEASE} | sed -e 's/^[PVTX]//' | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'` + exit ;; + Alpha\ *:Windows_NT*:*) + # How do we know it's Interix rather than the generic POSIX subsystem? + # Should we change UNAME_MACHINE based on the output of uname instead + # of the specific Alpha model? + echo alpha-pc-interix + exit ;; + 21064:Windows_NT:50:3) + echo alpha-dec-winnt3.5 + exit ;; + Amiga*:UNIX_System_V:4.0:*) + echo m68k-unknown-sysv4 + exit ;; + *:[Aa]miga[Oo][Ss]:*:*) + echo ${UNAME_MACHINE}-unknown-amigaos + exit ;; + *:[Mm]orph[Oo][Ss]:*:*) + echo ${UNAME_MACHINE}-unknown-morphos + exit ;; + *:OS/390:*:*) + echo i370-ibm-openedition + exit ;; + *:z/VM:*:*) + echo s390-ibm-zvmoe + exit ;; + *:OS400:*:*) + echo powerpc-ibm-os400 + exit ;; + arm:RISC*:1.[012]*:*|arm:riscix:1.[012]*:*) + echo arm-acorn-riscix${UNAME_RELEASE} + exit ;; + arm:riscos:*:*|arm:RISCOS:*:*) + echo arm-unknown-riscos + exit ;; + SR2?01:HI-UX/MPP:*:* | SR8000:HI-UX/MPP:*:*) + echo hppa1.1-hitachi-hiuxmpp + exit ;; + Pyramid*:OSx*:*:* | MIS*:OSx*:*:* | MIS*:SMP_DC-OSx*:*:*) + # akee@wpdis03.wpafb.af.mil (Earle F. Ake) contributed MIS and NILE. + if test "`(/bin/universe) 2>/dev/null`" = att ; then + echo pyramid-pyramid-sysv3 + else + echo pyramid-pyramid-bsd + fi + exit ;; + NILE*:*:*:dcosx) + echo pyramid-pyramid-svr4 + exit ;; + DRS?6000:unix:4.0:6*) + echo sparc-icl-nx6 + exit ;; + DRS?6000:UNIX_SV:4.2*:7* | DRS?6000:isis:4.2*:7*) + case `/usr/bin/uname -p` in + sparc) echo sparc-icl-nx7; exit ;; + esac ;; + sun4H:SunOS:5.*:*) + echo sparc-hal-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit ;; + sun4*:SunOS:5.*:* | tadpole*:SunOS:5.*:*) + echo sparc-sun-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit ;; + i86pc:SunOS:5.*:*) + echo i386-pc-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit ;; + sun4*:SunOS:6*:*) + # According to config.sub, this is the proper way to canonicalize + # SunOS6. Hard to guess exactly what SunOS6 will be like, but + # it's likely to be more like Solaris than SunOS4. + echo sparc-sun-solaris3`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit ;; + sun4*:SunOS:*:*) + case "`/usr/bin/arch -k`" in + Series*|S4*) + UNAME_RELEASE=`uname -v` + ;; + esac + # Japanese Language versions have a version number like `4.1.3-JL'. + echo sparc-sun-sunos`echo ${UNAME_RELEASE}|sed -e 's/-/_/'` + exit ;; + sun3*:SunOS:*:*) + echo m68k-sun-sunos${UNAME_RELEASE} + exit ;; + sun*:*:4.2BSD:*) + UNAME_RELEASE=`(sed 1q /etc/motd | awk '{print substr($5,1,3)}') 2>/dev/null` + test "x${UNAME_RELEASE}" = "x" && UNAME_RELEASE=3 + case "`/bin/arch`" in + sun3) + echo m68k-sun-sunos${UNAME_RELEASE} + ;; + sun4) + echo sparc-sun-sunos${UNAME_RELEASE} + ;; + esac + exit ;; + aushp:SunOS:*:*) + echo sparc-auspex-sunos${UNAME_RELEASE} + exit ;; + # The situation for MiNT is a little confusing. The machine name + # can be virtually everything (everything which is not + # "atarist" or "atariste" at least should have a processor + # > m68000). The system name ranges from "MiNT" over "FreeMiNT" + # to the lowercase version "mint" (or "freemint"). Finally + # the system name "TOS" denotes a system which is actually not + # MiNT. But MiNT is downward compatible to TOS, so this should + # be no problem. + atarist[e]:*MiNT:*:* | atarist[e]:*mint:*:* | atarist[e]:*TOS:*:*) + echo m68k-atari-mint${UNAME_RELEASE} + exit ;; + atari*:*MiNT:*:* | atari*:*mint:*:* | atarist[e]:*TOS:*:*) + echo m68k-atari-mint${UNAME_RELEASE} + exit ;; + *falcon*:*MiNT:*:* | *falcon*:*mint:*:* | *falcon*:*TOS:*:*) + echo m68k-atari-mint${UNAME_RELEASE} + exit ;; + milan*:*MiNT:*:* | milan*:*mint:*:* | *milan*:*TOS:*:*) + echo m68k-milan-mint${UNAME_RELEASE} + exit ;; + hades*:*MiNT:*:* | hades*:*mint:*:* | *hades*:*TOS:*:*) + echo m68k-hades-mint${UNAME_RELEASE} + exit ;; + *:*MiNT:*:* | *:*mint:*:* | *:*TOS:*:*) + echo m68k-unknown-mint${UNAME_RELEASE} + exit ;; + m68k:machten:*:*) + echo m68k-apple-machten${UNAME_RELEASE} + exit ;; + powerpc:machten:*:*) + echo powerpc-apple-machten${UNAME_RELEASE} + exit ;; + RISC*:Mach:*:*) + echo mips-dec-mach_bsd4.3 + exit ;; + RISC*:ULTRIX:*:*) + echo mips-dec-ultrix${UNAME_RELEASE} + exit ;; + VAX*:ULTRIX*:*:*) + echo vax-dec-ultrix${UNAME_RELEASE} + exit ;; + 2020:CLIX:*:* | 2430:CLIX:*:*) + echo clipper-intergraph-clix${UNAME_RELEASE} + exit ;; + mips:*:*:UMIPS | mips:*:*:RISCos) + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c +#ifdef __cplusplus +#include /* for printf() prototype */ + int main (int argc, char *argv[]) { +#else + int main (argc, argv) int argc; char *argv[]; { +#endif + #if defined (host_mips) && defined (MIPSEB) + #if defined (SYSTYPE_SYSV) + printf ("mips-mips-riscos%ssysv\n", argv[1]); exit (0); + #endif + #if defined (SYSTYPE_SVR4) + printf ("mips-mips-riscos%ssvr4\n", argv[1]); exit (0); + #endif + #if defined (SYSTYPE_BSD43) || defined(SYSTYPE_BSD) + printf ("mips-mips-riscos%sbsd\n", argv[1]); exit (0); + #endif + #endif + exit (-1); + } +EOF + $CC_FOR_BUILD -o $dummy $dummy.c && + dummyarg=`echo "${UNAME_RELEASE}" | sed -n 's/\([0-9]*\).*/\1/p'` && + SYSTEM_NAME=`$dummy $dummyarg` && + { echo "$SYSTEM_NAME"; exit; } + echo mips-mips-riscos${UNAME_RELEASE} + exit ;; + Motorola:PowerMAX_OS:*:*) + echo powerpc-motorola-powermax + exit ;; + Motorola:*:4.3:PL8-*) + echo powerpc-harris-powermax + exit ;; + Night_Hawk:*:*:PowerMAX_OS | Synergy:PowerMAX_OS:*:*) + echo powerpc-harris-powermax + exit ;; + Night_Hawk:Power_UNIX:*:*) + echo powerpc-harris-powerunix + exit ;; + m88k:CX/UX:7*:*) + echo m88k-harris-cxux7 + exit ;; + m88k:*:4*:R4*) + echo m88k-motorola-sysv4 + exit ;; + m88k:*:3*:R3*) + echo m88k-motorola-sysv3 + exit ;; + AViiON:dgux:*:*) + # DG/UX returns AViiON for all architectures + UNAME_PROCESSOR=`/usr/bin/uname -p` + if [ $UNAME_PROCESSOR = mc88100 ] || [ $UNAME_PROCESSOR = mc88110 ] + then + if [ ${TARGET_BINARY_INTERFACE}x = m88kdguxelfx ] || \ + [ ${TARGET_BINARY_INTERFACE}x = x ] + then + echo m88k-dg-dgux${UNAME_RELEASE} + else + echo m88k-dg-dguxbcs${UNAME_RELEASE} + fi + else + echo i586-dg-dgux${UNAME_RELEASE} + fi + exit ;; + M88*:DolphinOS:*:*) # DolphinOS (SVR3) + echo m88k-dolphin-sysv3 + exit ;; + M88*:*:R3*:*) + # Delta 88k system running SVR3 + echo m88k-motorola-sysv3 + exit ;; + XD88*:*:*:*) # Tektronix XD88 system running UTekV (SVR3) + echo m88k-tektronix-sysv3 + exit ;; + Tek43[0-9][0-9]:UTek:*:*) # Tektronix 4300 system running UTek (BSD) + echo m68k-tektronix-bsd + exit ;; + *:IRIX*:*:*) + echo mips-sgi-irix`echo ${UNAME_RELEASE}|sed -e 's/-/_/g'` + exit ;; + ????????:AIX?:[12].1:2) # AIX 2.2.1 or AIX 2.1.1 is RT/PC AIX. + echo romp-ibm-aix # uname -m gives an 8 hex-code CPU id + exit ;; # Note that: echo "'`uname -s`'" gives 'AIX ' + i*86:AIX:*:*) + echo i386-ibm-aix + exit ;; + ia64:AIX:*:*) + if [ -x /usr/bin/oslevel ] ; then + IBM_REV=`/usr/bin/oslevel` + else + IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE} + fi + echo ${UNAME_MACHINE}-ibm-aix${IBM_REV} + exit ;; + *:AIX:2:3) + if grep bos325 /usr/include/stdio.h >/dev/null 2>&1; then + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c + #include + + main() + { + if (!__power_pc()) + exit(1); + puts("powerpc-ibm-aix3.2.5"); + exit(0); + } +EOF + if $CC_FOR_BUILD -o $dummy $dummy.c && SYSTEM_NAME=`$dummy` + then + echo "$SYSTEM_NAME" + else + echo rs6000-ibm-aix3.2.5 + fi + elif grep bos324 /usr/include/stdio.h >/dev/null 2>&1; then + echo rs6000-ibm-aix3.2.4 + else + echo rs6000-ibm-aix3.2 + fi + exit ;; + *:AIX:*:[45]) + IBM_CPU_ID=`/usr/sbin/lsdev -C -c processor -S available | sed 1q | awk '{ print $1 }'` + if /usr/sbin/lsattr -El ${IBM_CPU_ID} | grep ' POWER' >/dev/null 2>&1; then + IBM_ARCH=rs6000 + else + IBM_ARCH=powerpc + fi + if [ -x /usr/bin/oslevel ] ; then + IBM_REV=`/usr/bin/oslevel` + else + IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE} + fi + echo ${IBM_ARCH}-ibm-aix${IBM_REV} + exit ;; + *:AIX:*:*) + echo rs6000-ibm-aix + exit ;; + ibmrt:4.4BSD:*|romp-ibm:BSD:*) + echo romp-ibm-bsd4.4 + exit ;; + ibmrt:*BSD:*|romp-ibm:BSD:*) # covers RT/PC BSD and + echo romp-ibm-bsd${UNAME_RELEASE} # 4.3 with uname added to + exit ;; # report: romp-ibm BSD 4.3 + *:BOSX:*:*) + echo rs6000-bull-bosx + exit ;; + DPX/2?00:B.O.S.:*:*) + echo m68k-bull-sysv3 + exit ;; + 9000/[34]??:4.3bsd:1.*:*) + echo m68k-hp-bsd + exit ;; + hp300:4.4BSD:*:* | 9000/[34]??:4.3bsd:2.*:*) + echo m68k-hp-bsd4.4 + exit ;; + 9000/[34678]??:HP-UX:*:*) + HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'` + case "${UNAME_MACHINE}" in + 9000/31? ) HP_ARCH=m68000 ;; + 9000/[34]?? ) HP_ARCH=m68k ;; + 9000/[678][0-9][0-9]) + if [ -x /usr/bin/getconf ]; then + sc_cpu_version=`/usr/bin/getconf SC_CPU_VERSION 2>/dev/null` + sc_kernel_bits=`/usr/bin/getconf SC_KERNEL_BITS 2>/dev/null` + case "${sc_cpu_version}" in + 523) HP_ARCH="hppa1.0" ;; # CPU_PA_RISC1_0 + 528) HP_ARCH="hppa1.1" ;; # CPU_PA_RISC1_1 + 532) # CPU_PA_RISC2_0 + case "${sc_kernel_bits}" in + 32) HP_ARCH="hppa2.0n" ;; + 64) HP_ARCH="hppa2.0w" ;; + '') HP_ARCH="hppa2.0" ;; # HP-UX 10.20 + esac ;; + esac + fi + if [ "${HP_ARCH}" = "" ]; then + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c + + #define _HPUX_SOURCE + #include + #include + + int main () + { + #if defined(_SC_KERNEL_BITS) + long bits = sysconf(_SC_KERNEL_BITS); + #endif + long cpu = sysconf (_SC_CPU_VERSION); + + switch (cpu) + { + case CPU_PA_RISC1_0: puts ("hppa1.0"); break; + case CPU_PA_RISC1_1: puts ("hppa1.1"); break; + case CPU_PA_RISC2_0: + #if defined(_SC_KERNEL_BITS) + switch (bits) + { + case 64: puts ("hppa2.0w"); break; + case 32: puts ("hppa2.0n"); break; + default: puts ("hppa2.0"); break; + } break; + #else /* !defined(_SC_KERNEL_BITS) */ + puts ("hppa2.0"); break; + #endif + default: puts ("hppa1.0"); break; + } + exit (0); + } +EOF + (CCOPTS= $CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null) && HP_ARCH=`$dummy` + test -z "$HP_ARCH" && HP_ARCH=hppa + fi ;; + esac + if [ ${HP_ARCH} = "hppa2.0w" ] + then + eval $set_cc_for_build + + # hppa2.0w-hp-hpux* has a 64-bit kernel and a compiler generating + # 32-bit code. hppa64-hp-hpux* has the same kernel and a compiler + # generating 64-bit code. GNU and HP use different nomenclature: + # + # $ CC_FOR_BUILD=cc ./config.guess + # => hppa2.0w-hp-hpux11.23 + # $ CC_FOR_BUILD="cc +DA2.0w" ./config.guess + # => hppa64-hp-hpux11.23 + + if echo __LP64__ | (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) | + grep __LP64__ >/dev/null + then + HP_ARCH="hppa2.0w" + else + HP_ARCH="hppa64" + fi + fi + echo ${HP_ARCH}-hp-hpux${HPUX_REV} + exit ;; + ia64:HP-UX:*:*) + HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'` + echo ia64-hp-hpux${HPUX_REV} + exit ;; + 3050*:HI-UX:*:*) + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c + #include + int + main () + { + long cpu = sysconf (_SC_CPU_VERSION); + /* The order matters, because CPU_IS_HP_MC68K erroneously returns + true for CPU_PA_RISC1_0. CPU_IS_PA_RISC returns correct + results, however. */ + if (CPU_IS_PA_RISC (cpu)) + { + switch (cpu) + { + case CPU_PA_RISC1_0: puts ("hppa1.0-hitachi-hiuxwe2"); break; + case CPU_PA_RISC1_1: puts ("hppa1.1-hitachi-hiuxwe2"); break; + case CPU_PA_RISC2_0: puts ("hppa2.0-hitachi-hiuxwe2"); break; + default: puts ("hppa-hitachi-hiuxwe2"); break; + } + } + else if (CPU_IS_HP_MC68K (cpu)) + puts ("m68k-hitachi-hiuxwe2"); + else puts ("unknown-hitachi-hiuxwe2"); + exit (0); + } +EOF + $CC_FOR_BUILD -o $dummy $dummy.c && SYSTEM_NAME=`$dummy` && + { echo "$SYSTEM_NAME"; exit; } + echo unknown-hitachi-hiuxwe2 + exit ;; + 9000/7??:4.3bsd:*:* | 9000/8?[79]:4.3bsd:*:* ) + echo hppa1.1-hp-bsd + exit ;; + 9000/8??:4.3bsd:*:*) + echo hppa1.0-hp-bsd + exit ;; + *9??*:MPE/iX:*:* | *3000*:MPE/iX:*:*) + echo hppa1.0-hp-mpeix + exit ;; + hp7??:OSF1:*:* | hp8?[79]:OSF1:*:* ) + echo hppa1.1-hp-osf + exit ;; + hp8??:OSF1:*:*) + echo hppa1.0-hp-osf + exit ;; + i*86:OSF1:*:*) + if [ -x /usr/sbin/sysversion ] ; then + echo ${UNAME_MACHINE}-unknown-osf1mk + else + echo ${UNAME_MACHINE}-unknown-osf1 + fi + exit ;; + parisc*:Lites*:*:*) + echo hppa1.1-hp-lites + exit ;; + C1*:ConvexOS:*:* | convex:ConvexOS:C1*:*) + echo c1-convex-bsd + exit ;; + C2*:ConvexOS:*:* | convex:ConvexOS:C2*:*) + if getsysinfo -f scalar_acc + then echo c32-convex-bsd + else echo c2-convex-bsd + fi + exit ;; + C34*:ConvexOS:*:* | convex:ConvexOS:C34*:*) + echo c34-convex-bsd + exit ;; + C38*:ConvexOS:*:* | convex:ConvexOS:C38*:*) + echo c38-convex-bsd + exit ;; + C4*:ConvexOS:*:* | convex:ConvexOS:C4*:*) + echo c4-convex-bsd + exit ;; + CRAY*Y-MP:*:*:*) + echo ymp-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + exit ;; + CRAY*[A-Z]90:*:*:*) + echo ${UNAME_MACHINE}-cray-unicos${UNAME_RELEASE} \ + | sed -e 's/CRAY.*\([A-Z]90\)/\1/' \ + -e y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/ \ + -e 's/\.[^.]*$/.X/' + exit ;; + CRAY*TS:*:*:*) + echo t90-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + exit ;; + CRAY*T3E:*:*:*) + echo alphaev5-cray-unicosmk${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + exit ;; + CRAY*SV1:*:*:*) + echo sv1-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + exit ;; + *:UNICOS/mp:*:*) + echo craynv-cray-unicosmp${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + exit ;; + F30[01]:UNIX_System_V:*:* | F700:UNIX_System_V:*:*) + FUJITSU_PROC=`uname -m | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'` + FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'` + FUJITSU_REL=`echo ${UNAME_RELEASE} | sed -e 's/ /_/'` + echo "${FUJITSU_PROC}-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}" + exit ;; + 5000:UNIX_System_V:4.*:*) + FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'` + FUJITSU_REL=`echo ${UNAME_RELEASE} | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/ /_/'` + echo "sparc-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}" + exit ;; + i*86:BSD/386:*:* | i*86:BSD/OS:*:* | *:Ascend\ Embedded/OS:*:*) + echo ${UNAME_MACHINE}-pc-bsdi${UNAME_RELEASE} + exit ;; + sparc*:BSD/OS:*:*) + echo sparc-unknown-bsdi${UNAME_RELEASE} + exit ;; + *:BSD/OS:*:*) + echo ${UNAME_MACHINE}-unknown-bsdi${UNAME_RELEASE} + exit ;; + *:FreeBSD:*:*) + case ${UNAME_MACHINE} in + pc98) + echo i386-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;; + amd64) + echo x86_64-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;; + *) + echo ${UNAME_MACHINE}-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;; + esac + exit ;; + i*:CYGWIN*:*) + echo ${UNAME_MACHINE}-pc-cygwin + exit ;; + i*:MINGW*:*) + echo ${UNAME_MACHINE}-pc-mingw32 + exit ;; + i*:windows32*:*) + # uname -m includes "-pc" on this system. + echo ${UNAME_MACHINE}-mingw32 + exit ;; + i*:PW*:*) + echo ${UNAME_MACHINE}-pc-pw32 + exit ;; + x86:Interix*:[3456]*) + echo i586-pc-interix${UNAME_RELEASE} + exit ;; + EM64T:Interix*:[3456]*) + echo x86_64-unknown-interix${UNAME_RELEASE} + exit ;; + [345]86:Windows_95:* | [345]86:Windows_98:* | [345]86:Windows_NT:*) + echo i${UNAME_MACHINE}-pc-mks + exit ;; + i*:Windows_NT*:* | Pentium*:Windows_NT*:*) + # How do we know it's Interix rather than the generic POSIX subsystem? + # It also conflicts with pre-2.0 versions of AT&T UWIN. Should we + # UNAME_MACHINE based on the output of uname instead of i386? + echo i586-pc-interix + exit ;; + i*:UWIN*:*) + echo ${UNAME_MACHINE}-pc-uwin + exit ;; + amd64:CYGWIN*:*:* | x86_64:CYGWIN*:*:*) + echo x86_64-unknown-cygwin + exit ;; + p*:CYGWIN*:*) + echo powerpcle-unknown-cygwin + exit ;; + prep*:SunOS:5.*:*) + echo powerpcle-unknown-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit ;; + *:GNU:*:*) + # the GNU system + echo `echo ${UNAME_MACHINE}|sed -e 's,[-/].*$,,'`-unknown-gnu`echo ${UNAME_RELEASE}|sed -e 's,/.*$,,'` + exit ;; + *:GNU/*:*:*) + # other systems with GNU libc and userland + echo ${UNAME_MACHINE}-unknown-`echo ${UNAME_SYSTEM} | sed 's,^[^/]*/,,' | tr '[A-Z]' '[a-z]'``echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`-gnu + exit ;; + i*86:Minix:*:*) + echo ${UNAME_MACHINE}-pc-minix + exit ;; + arm*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; + avr32*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; + cris:Linux:*:*) + echo cris-axis-linux-gnu + exit ;; + crisv32:Linux:*:*) + echo crisv32-axis-linux-gnu + exit ;; + frv:Linux:*:*) + echo frv-unknown-linux-gnu + exit ;; + ia64:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; + m32r*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; + m68*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; + mips:Linux:*:*) + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c + #undef CPU + #undef mips + #undef mipsel + #if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL) || defined(MIPSEL) + CPU=mipsel + #else + #if defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB) || defined(MIPSEB) + CPU=mips + #else + CPU= + #endif + #endif +EOF + eval "`$CC_FOR_BUILD -E $dummy.c 2>/dev/null | sed -n ' + /^CPU/{ + s: ::g + p + }'`" + test x"${CPU}" != x && { echo "${CPU}-unknown-linux-gnu"; exit; } + ;; + mips64:Linux:*:*) + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c + #undef CPU + #undef mips64 + #undef mips64el + #if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL) || defined(MIPSEL) + CPU=mips64el + #else + #if defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB) || defined(MIPSEB) + CPU=mips64 + #else + CPU= + #endif + #endif +EOF + eval "`$CC_FOR_BUILD -E $dummy.c 2>/dev/null | sed -n ' + /^CPU/{ + s: ::g + p + }'`" + test x"${CPU}" != x && { echo "${CPU}-unknown-linux-gnu"; exit; } + ;; + or32:Linux:*:*) + echo or32-unknown-linux-gnu + exit ;; + ppc:Linux:*:*) + echo powerpc-unknown-linux-gnu + exit ;; + ppc64:Linux:*:*) + echo powerpc64-unknown-linux-gnu + exit ;; + alpha:Linux:*:*) + case `sed -n '/^cpu model/s/^.*: \(.*\)/\1/p' < /proc/cpuinfo` in + EV5) UNAME_MACHINE=alphaev5 ;; + EV56) UNAME_MACHINE=alphaev56 ;; + PCA56) UNAME_MACHINE=alphapca56 ;; + PCA57) UNAME_MACHINE=alphapca56 ;; + EV6) UNAME_MACHINE=alphaev6 ;; + EV67) UNAME_MACHINE=alphaev67 ;; + EV68*) UNAME_MACHINE=alphaev68 ;; + esac + objdump --private-headers /bin/sh | grep ld.so.1 >/dev/null + if test "$?" = 0 ; then LIBC="libc1" ; else LIBC="" ; fi + echo ${UNAME_MACHINE}-unknown-linux-gnu${LIBC} + exit ;; + parisc:Linux:*:* | hppa:Linux:*:*) + # Look for CPU level + case `grep '^cpu[^a-z]*:' /proc/cpuinfo 2>/dev/null | cut -d' ' -f2` in + PA7*) echo hppa1.1-unknown-linux-gnu ;; + PA8*) echo hppa2.0-unknown-linux-gnu ;; + *) echo hppa-unknown-linux-gnu ;; + esac + exit ;; + parisc64:Linux:*:* | hppa64:Linux:*:*) + echo hppa64-unknown-linux-gnu + exit ;; + s390:Linux:*:* | s390x:Linux:*:*) + echo ${UNAME_MACHINE}-ibm-linux + exit ;; + sh64*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; + sh*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; + sparc:Linux:*:* | sparc64:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; + vax:Linux:*:*) + echo ${UNAME_MACHINE}-dec-linux-gnu + exit ;; + x86_64:Linux:*:*) + echo x86_64-unknown-linux-gnu + exit ;; + i*86:Linux:*:*) + # The BFD linker knows what the default object file format is, so + # first see if it will tell us. cd to the root directory to prevent + # problems with other programs or directories called `ld' in the path. + # Set LC_ALL=C to ensure ld outputs messages in English. + ld_supported_targets=`cd /; LC_ALL=C ld --help 2>&1 \ + | sed -ne '/supported targets:/!d + s/[ ][ ]*/ /g + s/.*supported targets: *// + s/ .*// + p'` + case "$ld_supported_targets" in + elf32-i386) + TENTATIVE="${UNAME_MACHINE}-pc-linux-gnu" + ;; + a.out-i386-linux) + echo "${UNAME_MACHINE}-pc-linux-gnuaout" + exit ;; + coff-i386) + echo "${UNAME_MACHINE}-pc-linux-gnucoff" + exit ;; + "") + # Either a pre-BFD a.out linker (linux-gnuoldld) or + # one that does not give us useful --help. + echo "${UNAME_MACHINE}-pc-linux-gnuoldld" + exit ;; + esac + # Determine whether the default compiler is a.out or elf + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c + #include + #ifdef __ELF__ + # ifdef __GLIBC__ + # if __GLIBC__ >= 2 + LIBC=gnu + # else + LIBC=gnulibc1 + # endif + # else + LIBC=gnulibc1 + # endif + #else + #if defined(__INTEL_COMPILER) || defined(__PGI) || defined(__SUNPRO_C) || defined(__SUNPRO_CC) + LIBC=gnu + #else + LIBC=gnuaout + #endif + #endif + #ifdef __dietlibc__ + LIBC=dietlibc + #endif +EOF + eval "`$CC_FOR_BUILD -E $dummy.c 2>/dev/null | sed -n ' + /^LIBC/{ + s: ::g + p + }'`" + test x"${LIBC}" != x && { + echo "${UNAME_MACHINE}-pc-linux-${LIBC}" + exit + } + test x"${TENTATIVE}" != x && { echo "${TENTATIVE}"; exit; } + ;; + i*86:DYNIX/ptx:4*:*) + # ptx 4.0 does uname -s correctly, with DYNIX/ptx in there. + # earlier versions are messed up and put the nodename in both + # sysname and nodename. + echo i386-sequent-sysv4 + exit ;; + i*86:UNIX_SV:4.2MP:2.*) + # Unixware is an offshoot of SVR4, but it has its own version + # number series starting with 2... + # I am not positive that other SVR4 systems won't match this, + # I just have to hope. -- rms. + # Use sysv4.2uw... so that sysv4* matches it. + echo ${UNAME_MACHINE}-pc-sysv4.2uw${UNAME_VERSION} + exit ;; + i*86:OS/2:*:*) + # If we were able to find `uname', then EMX Unix compatibility + # is probably installed. + echo ${UNAME_MACHINE}-pc-os2-emx + exit ;; + i*86:XTS-300:*:STOP) + echo ${UNAME_MACHINE}-unknown-stop + exit ;; + i*86:atheos:*:*) + echo ${UNAME_MACHINE}-unknown-atheos + exit ;; + i*86:syllable:*:*) + echo ${UNAME_MACHINE}-pc-syllable + exit ;; + i*86:LynxOS:2.*:* | i*86:LynxOS:3.[01]*:* | i*86:LynxOS:4.0*:*) + echo i386-unknown-lynxos${UNAME_RELEASE} + exit ;; + i*86:*DOS:*:*) + echo ${UNAME_MACHINE}-pc-msdosdjgpp + exit ;; + i*86:*:4.*:* | i*86:SYSTEM_V:4.*:*) + UNAME_REL=`echo ${UNAME_RELEASE} | sed 's/\/MP$//'` + if grep Novell /usr/include/link.h >/dev/null 2>/dev/null; then + echo ${UNAME_MACHINE}-univel-sysv${UNAME_REL} + else + echo ${UNAME_MACHINE}-pc-sysv${UNAME_REL} + fi + exit ;; + i*86:*:5:[678]*) + # UnixWare 7.x, OpenUNIX and OpenServer 6. + case `/bin/uname -X | grep "^Machine"` in + *486*) UNAME_MACHINE=i486 ;; + *Pentium) UNAME_MACHINE=i586 ;; + *Pent*|*Celeron) UNAME_MACHINE=i686 ;; + esac + echo ${UNAME_MACHINE}-unknown-sysv${UNAME_RELEASE}${UNAME_SYSTEM}${UNAME_VERSION} + exit ;; + i*86:*:3.2:*) + if test -f /usr/options/cb.name; then + UNAME_REL=`sed -n 's/.*Version //p' /dev/null >/dev/null ; then + UNAME_REL=`(/bin/uname -X|grep Release|sed -e 's/.*= //')` + (/bin/uname -X|grep i80486 >/dev/null) && UNAME_MACHINE=i486 + (/bin/uname -X|grep '^Machine.*Pentium' >/dev/null) \ + && UNAME_MACHINE=i586 + (/bin/uname -X|grep '^Machine.*Pent *II' >/dev/null) \ + && UNAME_MACHINE=i686 + (/bin/uname -X|grep '^Machine.*Pentium Pro' >/dev/null) \ + && UNAME_MACHINE=i686 + echo ${UNAME_MACHINE}-pc-sco$UNAME_REL + else + echo ${UNAME_MACHINE}-pc-sysv32 + fi + exit ;; + pc:*:*:*) + # Left here for compatibility: + # uname -m prints for DJGPP always 'pc', but it prints nothing about + # the processor, so we play safe by assuming i386. + echo i386-pc-msdosdjgpp + exit ;; + Intel:Mach:3*:*) + echo i386-pc-mach3 + exit ;; + paragon:*:*:*) + echo i860-intel-osf1 + exit ;; + i860:*:4.*:*) # i860-SVR4 + if grep Stardent /usr/include/sys/uadmin.h >/dev/null 2>&1 ; then + echo i860-stardent-sysv${UNAME_RELEASE} # Stardent Vistra i860-SVR4 + else # Add other i860-SVR4 vendors below as they are discovered. + echo i860-unknown-sysv${UNAME_RELEASE} # Unknown i860-SVR4 + fi + exit ;; + mini*:CTIX:SYS*5:*) + # "miniframe" + echo m68010-convergent-sysv + exit ;; + mc68k:UNIX:SYSTEM5:3.51m) + echo m68k-convergent-sysv + exit ;; + M680?0:D-NIX:5.3:*) + echo m68k-diab-dnix + exit ;; + M68*:*:R3V[5678]*:*) + test -r /sysV68 && { echo 'm68k-motorola-sysv'; exit; } ;; + 3[345]??:*:4.0:3.0 | 3[34]??A:*:4.0:3.0 | 3[34]??,*:*:4.0:3.0 | 3[34]??/*:*:4.0:3.0 | 4400:*:4.0:3.0 | 4850:*:4.0:3.0 | SKA40:*:4.0:3.0 | SDS2:*:4.0:3.0 | SHG2:*:4.0:3.0 | S7501*:*:4.0:3.0) + OS_REL='' + test -r /etc/.relid \ + && OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid` + /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ + && { echo i486-ncr-sysv4.3${OS_REL}; exit; } + /bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \ + && { echo i586-ncr-sysv4.3${OS_REL}; exit; } ;; + 3[34]??:*:4.0:* | 3[34]??,*:*:4.0:*) + /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ + && { echo i486-ncr-sysv4; exit; } ;; + m68*:LynxOS:2.*:* | m68*:LynxOS:3.0*:*) + echo m68k-unknown-lynxos${UNAME_RELEASE} + exit ;; + mc68030:UNIX_System_V:4.*:*) + echo m68k-atari-sysv4 + exit ;; + TSUNAMI:LynxOS:2.*:*) + echo sparc-unknown-lynxos${UNAME_RELEASE} + exit ;; + rs6000:LynxOS:2.*:*) + echo rs6000-unknown-lynxos${UNAME_RELEASE} + exit ;; + PowerPC:LynxOS:2.*:* | PowerPC:LynxOS:3.[01]*:* | PowerPC:LynxOS:4.0*:*) + echo powerpc-unknown-lynxos${UNAME_RELEASE} + exit ;; + SM[BE]S:UNIX_SV:*:*) + echo mips-dde-sysv${UNAME_RELEASE} + exit ;; + RM*:ReliantUNIX-*:*:*) + echo mips-sni-sysv4 + exit ;; + RM*:SINIX-*:*:*) + echo mips-sni-sysv4 + exit ;; + *:SINIX-*:*:*) + if uname -p 2>/dev/null >/dev/null ; then + UNAME_MACHINE=`(uname -p) 2>/dev/null` + echo ${UNAME_MACHINE}-sni-sysv4 + else + echo ns32k-sni-sysv + fi + exit ;; + PENTIUM:*:4.0*:*) # Unisys `ClearPath HMP IX 4000' SVR4/MP effort + # says + echo i586-unisys-sysv4 + exit ;; + *:UNIX_System_V:4*:FTX*) + # From Gerald Hewes . + # How about differentiating between stratus architectures? -djm + echo hppa1.1-stratus-sysv4 + exit ;; + *:*:*:FTX*) + # From seanf@swdc.stratus.com. + echo i860-stratus-sysv4 + exit ;; + i*86:VOS:*:*) + # From Paul.Green@stratus.com. + echo ${UNAME_MACHINE}-stratus-vos + exit ;; + *:VOS:*:*) + # From Paul.Green@stratus.com. + echo hppa1.1-stratus-vos + exit ;; + mc68*:A/UX:*:*) + echo m68k-apple-aux${UNAME_RELEASE} + exit ;; + news*:NEWS-OS:6*:*) + echo mips-sony-newsos6 + exit ;; + R[34]000:*System_V*:*:* | R4000:UNIX_SYSV:*:* | R*000:UNIX_SV:*:*) + if [ -d /usr/nec ]; then + echo mips-nec-sysv${UNAME_RELEASE} + else + echo mips-unknown-sysv${UNAME_RELEASE} + fi + exit ;; + BeBox:BeOS:*:*) # BeOS running on hardware made by Be, PPC only. + echo powerpc-be-beos + exit ;; + BeMac:BeOS:*:*) # BeOS running on Mac or Mac clone, PPC only. + echo powerpc-apple-beos + exit ;; + BePC:BeOS:*:*) # BeOS running on Intel PC compatible. + echo i586-pc-beos + exit ;; + SX-4:SUPER-UX:*:*) + echo sx4-nec-superux${UNAME_RELEASE} + exit ;; + SX-5:SUPER-UX:*:*) + echo sx5-nec-superux${UNAME_RELEASE} + exit ;; + SX-6:SUPER-UX:*:*) + echo sx6-nec-superux${UNAME_RELEASE} + exit ;; + Power*:Rhapsody:*:*) + echo powerpc-apple-rhapsody${UNAME_RELEASE} + exit ;; + *:Rhapsody:*:*) + echo ${UNAME_MACHINE}-apple-rhapsody${UNAME_RELEASE} + exit ;; + *:Darwin:*:*) + UNAME_PROCESSOR=`uname -p` || UNAME_PROCESSOR=unknown + case $UNAME_PROCESSOR in + unknown) UNAME_PROCESSOR=powerpc ;; + esac + echo ${UNAME_PROCESSOR}-apple-darwin${UNAME_RELEASE} + exit ;; + *:procnto*:*:* | *:QNX:[0123456789]*:*) + UNAME_PROCESSOR=`uname -p` + if test "$UNAME_PROCESSOR" = "x86"; then + UNAME_PROCESSOR=i386 + UNAME_MACHINE=pc + fi + echo ${UNAME_PROCESSOR}-${UNAME_MACHINE}-nto-qnx${UNAME_RELEASE} + exit ;; + *:QNX:*:4*) + echo i386-pc-qnx + exit ;; + NSE-?:NONSTOP_KERNEL:*:*) + echo nse-tandem-nsk${UNAME_RELEASE} + exit ;; + NSR-?:NONSTOP_KERNEL:*:*) + echo nsr-tandem-nsk${UNAME_RELEASE} + exit ;; + *:NonStop-UX:*:*) + echo mips-compaq-nonstopux + exit ;; + BS2000:POSIX*:*:*) + echo bs2000-siemens-sysv + exit ;; + DS/*:UNIX_System_V:*:*) + echo ${UNAME_MACHINE}-${UNAME_SYSTEM}-${UNAME_RELEASE} + exit ;; + *:Plan9:*:*) + # "uname -m" is not consistent, so use $cputype instead. 386 + # is converted to i386 for consistency with other x86 + # operating systems. + if test "$cputype" = "386"; then + UNAME_MACHINE=i386 + else + UNAME_MACHINE="$cputype" + fi + echo ${UNAME_MACHINE}-unknown-plan9 + exit ;; + *:TOPS-10:*:*) + echo pdp10-unknown-tops10 + exit ;; + *:TENEX:*:*) + echo pdp10-unknown-tenex + exit ;; + KS10:TOPS-20:*:* | KL10:TOPS-20:*:* | TYPE4:TOPS-20:*:*) + echo pdp10-dec-tops20 + exit ;; + XKL-1:TOPS-20:*:* | TYPE5:TOPS-20:*:*) + echo pdp10-xkl-tops20 + exit ;; + *:TOPS-20:*:*) + echo pdp10-unknown-tops20 + exit ;; + *:ITS:*:*) + echo pdp10-unknown-its + exit ;; + SEI:*:*:SEIUX) + echo mips-sei-seiux${UNAME_RELEASE} + exit ;; + *:DragonFly:*:*) + echo ${UNAME_MACHINE}-unknown-dragonfly`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` + exit ;; + *:*VMS:*:*) + UNAME_MACHINE=`(uname -p) 2>/dev/null` + case "${UNAME_MACHINE}" in + A*) echo alpha-dec-vms ; exit ;; + I*) echo ia64-dec-vms ; exit ;; + V*) echo vax-dec-vms ; exit ;; + esac ;; + *:XENIX:*:SysV) + echo i386-pc-xenix + exit ;; + i*86:skyos:*:*) + echo ${UNAME_MACHINE}-pc-skyos`echo ${UNAME_RELEASE}` | sed -e 's/ .*$//' + exit ;; + i*86:rdos:*:*) + echo ${UNAME_MACHINE}-pc-rdos + exit ;; +esac + +#echo '(No uname command or uname output not recognized.)' 1>&2 +#echo "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" 1>&2 + +eval $set_cc_for_build +cat >$dummy.c < +# include +#endif +main () +{ +#if defined (sony) +#if defined (MIPSEB) + /* BFD wants "bsd" instead of "newsos". Perhaps BFD should be changed, + I don't know.... */ + printf ("mips-sony-bsd\n"); exit (0); +#else +#include + printf ("m68k-sony-newsos%s\n", +#ifdef NEWSOS4 + "4" +#else + "" +#endif + ); exit (0); +#endif +#endif + +#if defined (__arm) && defined (__acorn) && defined (__unix) + printf ("arm-acorn-riscix\n"); exit (0); +#endif + +#if defined (hp300) && !defined (hpux) + printf ("m68k-hp-bsd\n"); exit (0); +#endif + +#if defined (NeXT) +#if !defined (__ARCHITECTURE__) +#define __ARCHITECTURE__ "m68k" +#endif + int version; + version=`(hostinfo | sed -n 's/.*NeXT Mach \([0-9]*\).*/\1/p') 2>/dev/null`; + if (version < 4) + printf ("%s-next-nextstep%d\n", __ARCHITECTURE__, version); + else + printf ("%s-next-openstep%d\n", __ARCHITECTURE__, version); + exit (0); +#endif + +#if defined (MULTIMAX) || defined (n16) +#if defined (UMAXV) + printf ("ns32k-encore-sysv\n"); exit (0); +#else +#if defined (CMU) + printf ("ns32k-encore-mach\n"); exit (0); +#else + printf ("ns32k-encore-bsd\n"); exit (0); +#endif +#endif +#endif + +#if defined (__386BSD__) + printf ("i386-pc-bsd\n"); exit (0); +#endif + +#if defined (sequent) +#if defined (i386) + printf ("i386-sequent-dynix\n"); exit (0); +#endif +#if defined (ns32000) + printf ("ns32k-sequent-dynix\n"); exit (0); +#endif +#endif + +#if defined (_SEQUENT_) + struct utsname un; + + uname(&un); + + if (strncmp(un.version, "V2", 2) == 0) { + printf ("i386-sequent-ptx2\n"); exit (0); + } + if (strncmp(un.version, "V1", 2) == 0) { /* XXX is V1 correct? */ + printf ("i386-sequent-ptx1\n"); exit (0); + } + printf ("i386-sequent-ptx\n"); exit (0); + +#endif + +#if defined (vax) +# if !defined (ultrix) +# include +# if defined (BSD) +# if BSD == 43 + printf ("vax-dec-bsd4.3\n"); exit (0); +# else +# if BSD == 199006 + printf ("vax-dec-bsd4.3reno\n"); exit (0); +# else + printf ("vax-dec-bsd\n"); exit (0); +# endif +# endif +# else + printf ("vax-dec-bsd\n"); exit (0); +# endif +# else + printf ("vax-dec-ultrix\n"); exit (0); +# endif +#endif + +#if defined (alliant) && defined (i860) + printf ("i860-alliant-bsd\n"); exit (0); +#endif + + exit (1); +} +EOF + +$CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null && SYSTEM_NAME=`$dummy` && + { echo "$SYSTEM_NAME"; exit; } + +# Apollos put the system type in the environment. + +test -d /usr/apollo && { echo ${ISP}-apollo-${SYSTYPE}; exit; } + +# Convex versions that predate uname can use getsysinfo(1) + +if [ -x /usr/convex/getsysinfo ] +then + case `getsysinfo -f cpu_type` in + c1*) + echo c1-convex-bsd + exit ;; + c2*) + if getsysinfo -f scalar_acc + then echo c32-convex-bsd + else echo c2-convex-bsd + fi + exit ;; + c34*) + echo c34-convex-bsd + exit ;; + c38*) + echo c38-convex-bsd + exit ;; + c4*) + echo c4-convex-bsd + exit ;; + esac +fi + +cat >&2 < in order to provide the needed +information to handle your system. + +config.guess timestamp = $timestamp + +uname -m = `(uname -m) 2>/dev/null || echo unknown` +uname -r = `(uname -r) 2>/dev/null || echo unknown` +uname -s = `(uname -s) 2>/dev/null || echo unknown` +uname -v = `(uname -v) 2>/dev/null || echo unknown` + +/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null` +/bin/uname -X = `(/bin/uname -X) 2>/dev/null` + +hostinfo = `(hostinfo) 2>/dev/null` +/bin/universe = `(/bin/universe) 2>/dev/null` +/usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null` +/bin/arch = `(/bin/arch) 2>/dev/null` +/usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null` +/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null` + +UNAME_MACHINE = ${UNAME_MACHINE} +UNAME_RELEASE = ${UNAME_RELEASE} +UNAME_SYSTEM = ${UNAME_SYSTEM} +UNAME_VERSION = ${UNAME_VERSION} +EOF + +exit 1 + +# Local variables: +# eval: (add-hook 'write-file-hooks 'time-stamp) +# time-stamp-start: "timestamp='" +# time-stamp-format: "%:y-%02m-%02d" +# time-stamp-end: "'" +# End: diff --git a/modules/cfitsio/autoconf/config.sub b/modules/cfitsio/autoconf/config.sub new file mode 100755 index 0000000..387c18d --- /dev/null +++ b/modules/cfitsio/autoconf/config.sub @@ -0,0 +1,1608 @@ +#! /bin/sh +# Configuration validation subroutine script. +# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, +# 2000, 2001, 2002, 2003, 2004, 2005, 2006 Free Software Foundation, +# Inc. + +timestamp='2006-07-02' + +# This file is (in principle) common to ALL GNU software. +# The presence of a machine in this file suggests that SOME GNU software +# can handle that machine. It does not imply ALL GNU software can. +# +# This file is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA +# 02110-1301, USA. +# +# As a special exception to the GNU General Public License, if you +# distribute this file as part of a program that contains a +# configuration script generated by Autoconf, you may include it under +# the same distribution terms that you use for the rest of that program. + + +# Please send patches to . Submit a context +# diff and a properly formatted ChangeLog entry. +# +# Configuration subroutine to validate and canonicalize a configuration type. +# Supply the specified configuration type as an argument. +# If it is invalid, we print an error message on stderr and exit with code 1. +# Otherwise, we print the canonical config type on stdout and succeed. + +# This file is supposed to be the same for all GNU packages +# and recognize all the CPU types, system types and aliases +# that are meaningful with *any* GNU software. +# Each package is responsible for reporting which valid configurations +# it does not support. The user should be able to distinguish +# a failure to support a valid configuration from a meaningless +# configuration. + +# The goal of this file is to map all the various variations of a given +# machine specification into a single specification in the form: +# CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM +# or in some cases, the newer four-part form: +# CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM +# It is wrong to echo any other type of specification. + +me=`echo "$0" | sed -e 's,.*/,,'` + +usage="\ +Usage: $0 [OPTION] CPU-MFR-OPSYS + $0 [OPTION] ALIAS + +Canonicalize a configuration name. + +Operation modes: + -h, --help print this help, then exit + -t, --time-stamp print date of last modification, then exit + -v, --version print version number, then exit + +Report bugs and patches to ." + +version="\ +GNU config.sub ($timestamp) + +Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005 +Free Software Foundation, Inc. + +This is free software; see the source for copying conditions. There is NO +warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." + +help=" +Try \`$me --help' for more information." + +# Parse command line +while test $# -gt 0 ; do + case $1 in + --time-stamp | --time* | -t ) + echo "$timestamp" ; exit ;; + --version | -v ) + echo "$version" ; exit ;; + --help | --h* | -h ) + echo "$usage"; exit ;; + -- ) # Stop option processing + shift; break ;; + - ) # Use stdin as input. + break ;; + -* ) + echo "$me: invalid option $1$help" + exit 1 ;; + + *local*) + # First pass through any local machine types. + echo $1 + exit ;; + + * ) + break ;; + esac +done + +case $# in + 0) echo "$me: missing argument$help" >&2 + exit 1;; + 1) ;; + *) echo "$me: too many arguments$help" >&2 + exit 1;; +esac + +# Separate what the user gave into CPU-COMPANY and OS or KERNEL-OS (if any). +# Here we must recognize all the valid KERNEL-OS combinations. +maybe_os=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\2/'` +case $maybe_os in + nto-qnx* | linux-gnu* | linux-dietlibc | linux-newlib* | linux-uclibc* | \ + uclinux-uclibc* | uclinux-gnu* | kfreebsd*-gnu* | knetbsd*-gnu* | netbsd*-gnu* | \ + storm-chaos* | os2-emx* | rtmk-nova*) + os=-$maybe_os + basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'` + ;; + *) + basic_machine=`echo $1 | sed 's/-[^-]*$//'` + if [ $basic_machine != $1 ] + then os=`echo $1 | sed 's/.*-/-/'` + else os=; fi + ;; +esac + +### Let's recognize common machines as not being operating systems so +### that things like config.sub decstation-3100 work. We also +### recognize some manufacturers as not being operating systems, so we +### can provide default operating systems below. +case $os in + -sun*os*) + # Prevent following clause from handling this invalid input. + ;; + -dec* | -mips* | -sequent* | -encore* | -pc532* | -sgi* | -sony* | \ + -att* | -7300* | -3300* | -delta* | -motorola* | -sun[234]* | \ + -unicom* | -ibm* | -next | -hp | -isi* | -apollo | -altos* | \ + -convergent* | -ncr* | -news | -32* | -3600* | -3100* | -hitachi* |\ + -c[123]* | -convex* | -sun | -crds | -omron* | -dg | -ultra | -tti* | \ + -harris | -dolphin | -highlevel | -gould | -cbm | -ns | -masscomp | \ + -apple | -axis | -knuth | -cray) + os= + basic_machine=$1 + ;; + -sim | -cisco | -oki | -wec | -winbond) + os= + basic_machine=$1 + ;; + -scout) + ;; + -wrs) + os=-vxworks + basic_machine=$1 + ;; + -chorusos*) + os=-chorusos + basic_machine=$1 + ;; + -chorusrdb) + os=-chorusrdb + basic_machine=$1 + ;; + -hiux*) + os=-hiuxwe2 + ;; + -sco6) + os=-sco5v6 + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -sco5) + os=-sco3.2v5 + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -sco4) + os=-sco3.2v4 + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -sco3.2.[4-9]*) + os=`echo $os | sed -e 's/sco3.2./sco3.2v/'` + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -sco3.2v[4-9]*) + # Don't forget version if it is 3.2v4 or newer. + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -sco5v6*) + # Don't forget version if it is 3.2v4 or newer. + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -sco*) + os=-sco3.2v2 + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -udk*) + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -isc) + os=-isc2.2 + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -clix*) + basic_machine=clipper-intergraph + ;; + -isc*) + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -lynx*) + os=-lynxos + ;; + -ptx*) + basic_machine=`echo $1 | sed -e 's/86-.*/86-sequent/'` + ;; + -windowsnt*) + os=`echo $os | sed -e 's/windowsnt/winnt/'` + ;; + -psos*) + os=-psos + ;; + -mint | -mint[0-9]*) + basic_machine=m68k-atari + os=-mint + ;; +esac + +# Decode aliases for certain CPU-COMPANY combinations. +case $basic_machine in + # Recognize the basic CPU types without company name. + # Some are omitted here because they have special meanings below. + 1750a | 580 \ + | a29k \ + | alpha | alphaev[4-8] | alphaev56 | alphaev6[78] | alphapca5[67] \ + | alpha64 | alpha64ev[4-8] | alpha64ev56 | alpha64ev6[78] | alpha64pca5[67] \ + | am33_2.0 \ + | arc | arm | arm[bl]e | arme[lb] | armv[2345] | armv[345][lb] | avr | avr32 \ + | bfin \ + | c4x | clipper \ + | d10v | d30v | dlx | dsp16xx \ + | fr30 | frv \ + | h8300 | h8500 | hppa | hppa1.[01] | hppa2.0 | hppa2.0[nw] | hppa64 \ + | i370 | i860 | i960 | ia64 \ + | ip2k | iq2000 \ + | m32c | m32r | m32rle | m68000 | m68k | m88k \ + | maxq | mb | microblaze | mcore \ + | mips | mipsbe | mipseb | mipsel | mipsle \ + | mips16 \ + | mips64 | mips64el \ + | mips64vr | mips64vrel \ + | mips64orion | mips64orionel \ + | mips64vr4100 | mips64vr4100el \ + | mips64vr4300 | mips64vr4300el \ + | mips64vr5000 | mips64vr5000el \ + | mips64vr5900 | mips64vr5900el \ + | mipsisa32 | mipsisa32el \ + | mipsisa32r2 | mipsisa32r2el \ + | mipsisa64 | mipsisa64el \ + | mipsisa64r2 | mipsisa64r2el \ + | mipsisa64sb1 | mipsisa64sb1el \ + | mipsisa64sr71k | mipsisa64sr71kel \ + | mipstx39 | mipstx39el \ + | mn10200 | mn10300 \ + | mt \ + | msp430 \ + | nios | nios2 \ + | ns16k | ns32k \ + | or32 \ + | pdp10 | pdp11 | pj | pjl \ + | powerpc | powerpc64 | powerpc64le | powerpcle | ppcbe \ + | pyramid \ + | sh | sh[1234] | sh[24]a | sh[23]e | sh[34]eb | sheb | shbe | shle | sh[1234]le | sh3ele \ + | sh64 | sh64le \ + | sparc | sparc64 | sparc64b | sparc64v | sparc86x | sparclet | sparclite \ + | sparcv8 | sparcv9 | sparcv9b | sparcv9v \ + | spu | strongarm \ + | tahoe | thumb | tic4x | tic80 | tron \ + | v850 | v850e \ + | we32k \ + | x86 | xscale | xscalee[bl] | xstormy16 | xtensa \ + | z8k) + basic_machine=$basic_machine-unknown + ;; + m6811 | m68hc11 | m6812 | m68hc12) + # Motorola 68HC11/12. + basic_machine=$basic_machine-unknown + os=-none + ;; + m88110 | m680[12346]0 | m683?2 | m68360 | m5200 | v70 | w65 | z8k) + ;; + ms1) + basic_machine=mt-unknown + ;; + + # We use `pc' rather than `unknown' + # because (1) that's what they normally are, and + # (2) the word "unknown" tends to confuse beginning users. + i*86 | x86_64) + basic_machine=$basic_machine-pc + ;; + # Object if more than one company name word. + *-*-*) + echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2 + exit 1 + ;; + # Recognize the basic CPU types with company name. + 580-* \ + | a29k-* \ + | alpha-* | alphaev[4-8]-* | alphaev56-* | alphaev6[78]-* \ + | alpha64-* | alpha64ev[4-8]-* | alpha64ev56-* | alpha64ev6[78]-* \ + | alphapca5[67]-* | alpha64pca5[67]-* | arc-* \ + | arm-* | armbe-* | armle-* | armeb-* | armv*-* \ + | avr-* | avr32-* \ + | bfin-* | bs2000-* \ + | c[123]* | c30-* | [cjt]90-* | c4x-* | c54x-* | c55x-* | c6x-* \ + | clipper-* | craynv-* | cydra-* \ + | d10v-* | d30v-* | dlx-* \ + | elxsi-* \ + | f30[01]-* | f700-* | fr30-* | frv-* | fx80-* \ + | h8300-* | h8500-* \ + | hppa-* | hppa1.[01]-* | hppa2.0-* | hppa2.0[nw]-* | hppa64-* \ + | i*86-* | i860-* | i960-* | ia64-* \ + | ip2k-* | iq2000-* \ + | m32c-* | m32r-* | m32rle-* \ + | m68000-* | m680[012346]0-* | m68360-* | m683?2-* | m68k-* \ + | m88110-* | m88k-* | maxq-* | mcore-* \ + | mips-* | mipsbe-* | mipseb-* | mipsel-* | mipsle-* \ + | mips16-* \ + | mips64-* | mips64el-* \ + | mips64vr-* | mips64vrel-* \ + | mips64orion-* | mips64orionel-* \ + | mips64vr4100-* | mips64vr4100el-* \ + | mips64vr4300-* | mips64vr4300el-* \ + | mips64vr5000-* | mips64vr5000el-* \ + | mips64vr5900-* | mips64vr5900el-* \ + | mipsisa32-* | mipsisa32el-* \ + | mipsisa32r2-* | mipsisa32r2el-* \ + | mipsisa64-* | mipsisa64el-* \ + | mipsisa64r2-* | mipsisa64r2el-* \ + | mipsisa64sb1-* | mipsisa64sb1el-* \ + | mipsisa64sr71k-* | mipsisa64sr71kel-* \ + | mipstx39-* | mipstx39el-* \ + | mmix-* \ + | mt-* \ + | msp430-* \ + | nios-* | nios2-* \ + | none-* | np1-* | ns16k-* | ns32k-* \ + | orion-* \ + | pdp10-* | pdp11-* | pj-* | pjl-* | pn-* | power-* \ + | powerpc-* | powerpc64-* | powerpc64le-* | powerpcle-* | ppcbe-* \ + | pyramid-* \ + | romp-* | rs6000-* \ + | sh-* | sh[1234]-* | sh[24]a-* | sh[23]e-* | sh[34]eb-* | sheb-* | shbe-* \ + | shle-* | sh[1234]le-* | sh3ele-* | sh64-* | sh64le-* \ + | sparc-* | sparc64-* | sparc64b-* | sparc64v-* | sparc86x-* | sparclet-* \ + | sparclite-* \ + | sparcv8-* | sparcv9-* | sparcv9b-* | sparcv9v-* | strongarm-* | sv1-* | sx?-* \ + | tahoe-* | thumb-* \ + | tic30-* | tic4x-* | tic54x-* | tic55x-* | tic6x-* | tic80-* \ + | tron-* \ + | v850-* | v850e-* | vax-* \ + | we32k-* \ + | x86-* | x86_64-* | xps100-* | xscale-* | xscalee[bl]-* \ + | xstormy16-* | xtensa-* \ + | ymp-* \ + | z8k-*) + ;; + # Recognize the various machine names and aliases which stand + # for a CPU type and a company and sometimes even an OS. + 386bsd) + basic_machine=i386-unknown + os=-bsd + ;; + 3b1 | 7300 | 7300-att | att-7300 | pc7300 | safari | unixpc) + basic_machine=m68000-att + ;; + 3b*) + basic_machine=we32k-att + ;; + a29khif) + basic_machine=a29k-amd + os=-udi + ;; + abacus) + basic_machine=abacus-unknown + ;; + adobe68k) + basic_machine=m68010-adobe + os=-scout + ;; + alliant | fx80) + basic_machine=fx80-alliant + ;; + altos | altos3068) + basic_machine=m68k-altos + ;; + am29k) + basic_machine=a29k-none + os=-bsd + ;; + amd64) + basic_machine=x86_64-pc + ;; + amd64-*) + basic_machine=x86_64-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + amdahl) + basic_machine=580-amdahl + os=-sysv + ;; + amiga | amiga-*) + basic_machine=m68k-unknown + ;; + amigaos | amigados) + basic_machine=m68k-unknown + os=-amigaos + ;; + amigaunix | amix) + basic_machine=m68k-unknown + os=-sysv4 + ;; + apollo68) + basic_machine=m68k-apollo + os=-sysv + ;; + apollo68bsd) + basic_machine=m68k-apollo + os=-bsd + ;; + aux) + basic_machine=m68k-apple + os=-aux + ;; + balance) + basic_machine=ns32k-sequent + os=-dynix + ;; + c90) + basic_machine=c90-cray + os=-unicos + ;; + convex-c1) + basic_machine=c1-convex + os=-bsd + ;; + convex-c2) + basic_machine=c2-convex + os=-bsd + ;; + convex-c32) + basic_machine=c32-convex + os=-bsd + ;; + convex-c34) + basic_machine=c34-convex + os=-bsd + ;; + convex-c38) + basic_machine=c38-convex + os=-bsd + ;; + cray | j90) + basic_machine=j90-cray + os=-unicos + ;; + craynv) + basic_machine=craynv-cray + os=-unicosmp + ;; + cr16c) + basic_machine=cr16c-unknown + os=-elf + ;; + crds | unos) + basic_machine=m68k-crds + ;; + crisv32 | crisv32-* | etraxfs*) + basic_machine=crisv32-axis + ;; + cris | cris-* | etrax*) + basic_machine=cris-axis + ;; + crx) + basic_machine=crx-unknown + os=-elf + ;; + da30 | da30-*) + basic_machine=m68k-da30 + ;; + decstation | decstation-3100 | pmax | pmax-* | pmin | dec3100 | decstatn) + basic_machine=mips-dec + ;; + decsystem10* | dec10*) + basic_machine=pdp10-dec + os=-tops10 + ;; + decsystem20* | dec20*) + basic_machine=pdp10-dec + os=-tops20 + ;; + delta | 3300 | motorola-3300 | motorola-delta \ + | 3300-motorola | delta-motorola) + basic_machine=m68k-motorola + ;; + delta88) + basic_machine=m88k-motorola + os=-sysv3 + ;; + djgpp) + basic_machine=i586-pc + os=-msdosdjgpp + ;; + dpx20 | dpx20-*) + basic_machine=rs6000-bull + os=-bosx + ;; + dpx2* | dpx2*-bull) + basic_machine=m68k-bull + os=-sysv3 + ;; + ebmon29k) + basic_machine=a29k-amd + os=-ebmon + ;; + elxsi) + basic_machine=elxsi-elxsi + os=-bsd + ;; + encore | umax | mmax) + basic_machine=ns32k-encore + ;; + es1800 | OSE68k | ose68k | ose | OSE) + basic_machine=m68k-ericsson + os=-ose + ;; + fx2800) + basic_machine=i860-alliant + ;; + genix) + basic_machine=ns32k-ns + ;; + gmicro) + basic_machine=tron-gmicro + os=-sysv + ;; + go32) + basic_machine=i386-pc + os=-go32 + ;; + h3050r* | hiux*) + basic_machine=hppa1.1-hitachi + os=-hiuxwe2 + ;; + h8300hms) + basic_machine=h8300-hitachi + os=-hms + ;; + h8300xray) + basic_machine=h8300-hitachi + os=-xray + ;; + h8500hms) + basic_machine=h8500-hitachi + os=-hms + ;; + harris) + basic_machine=m88k-harris + os=-sysv3 + ;; + hp300-*) + basic_machine=m68k-hp + ;; + hp300bsd) + basic_machine=m68k-hp + os=-bsd + ;; + hp300hpux) + basic_machine=m68k-hp + os=-hpux + ;; + hp3k9[0-9][0-9] | hp9[0-9][0-9]) + basic_machine=hppa1.0-hp + ;; + hp9k2[0-9][0-9] | hp9k31[0-9]) + basic_machine=m68000-hp + ;; + hp9k3[2-9][0-9]) + basic_machine=m68k-hp + ;; + hp9k6[0-9][0-9] | hp6[0-9][0-9]) + basic_machine=hppa1.0-hp + ;; + hp9k7[0-79][0-9] | hp7[0-79][0-9]) + basic_machine=hppa1.1-hp + ;; + hp9k78[0-9] | hp78[0-9]) + # FIXME: really hppa2.0-hp + basic_machine=hppa1.1-hp + ;; + hp9k8[67]1 | hp8[67]1 | hp9k80[24] | hp80[24] | hp9k8[78]9 | hp8[78]9 | hp9k893 | hp893) + # FIXME: really hppa2.0-hp + basic_machine=hppa1.1-hp + ;; + hp9k8[0-9][13679] | hp8[0-9][13679]) + basic_machine=hppa1.1-hp + ;; + hp9k8[0-9][0-9] | hp8[0-9][0-9]) + basic_machine=hppa1.0-hp + ;; + hppa-next) + os=-nextstep3 + ;; + hppaosf) + basic_machine=hppa1.1-hp + os=-osf + ;; + hppro) + basic_machine=hppa1.1-hp + os=-proelf + ;; + i370-ibm* | ibm*) + basic_machine=i370-ibm + ;; +# I'm not sure what "Sysv32" means. Should this be sysv3.2? + i*86v32) + basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` + os=-sysv32 + ;; + i*86v4*) + basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` + os=-sysv4 + ;; + i*86v) + basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` + os=-sysv + ;; + i*86sol2) + basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` + os=-solaris2 + ;; + i386mach) + basic_machine=i386-mach + os=-mach + ;; + i386-vsta | vsta) + basic_machine=i386-unknown + os=-vsta + ;; + iris | iris4d) + basic_machine=mips-sgi + case $os in + -irix*) + ;; + *) + os=-irix4 + ;; + esac + ;; + isi68 | isi) + basic_machine=m68k-isi + os=-sysv + ;; + m88k-omron*) + basic_machine=m88k-omron + ;; + magnum | m3230) + basic_machine=mips-mips + os=-sysv + ;; + merlin) + basic_machine=ns32k-utek + os=-sysv + ;; + mingw32) + basic_machine=i386-pc + os=-mingw32 + ;; + miniframe) + basic_machine=m68000-convergent + ;; + *mint | -mint[0-9]* | *MiNT | *MiNT[0-9]*) + basic_machine=m68k-atari + os=-mint + ;; + mips3*-*) + basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'` + ;; + mips3*) + basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'`-unknown + ;; + monitor) + basic_machine=m68k-rom68k + os=-coff + ;; + morphos) + basic_machine=powerpc-unknown + os=-morphos + ;; + msdos) + basic_machine=i386-pc + os=-msdos + ;; + ms1-*) + basic_machine=`echo $basic_machine | sed -e 's/ms1-/mt-/'` + ;; + mvs) + basic_machine=i370-ibm + os=-mvs + ;; + ncr3000) + basic_machine=i486-ncr + os=-sysv4 + ;; + netbsd386) + basic_machine=i386-unknown + os=-netbsd + ;; + netwinder) + basic_machine=armv4l-rebel + os=-linux + ;; + news | news700 | news800 | news900) + basic_machine=m68k-sony + os=-newsos + ;; + news1000) + basic_machine=m68030-sony + os=-newsos + ;; + news-3600 | risc-news) + basic_machine=mips-sony + os=-newsos + ;; + necv70) + basic_machine=v70-nec + os=-sysv + ;; + next | m*-next ) + basic_machine=m68k-next + case $os in + -nextstep* ) + ;; + -ns2*) + os=-nextstep2 + ;; + *) + os=-nextstep3 + ;; + esac + ;; + nh3000) + basic_machine=m68k-harris + os=-cxux + ;; + nh[45]000) + basic_machine=m88k-harris + os=-cxux + ;; + nindy960) + basic_machine=i960-intel + os=-nindy + ;; + mon960) + basic_machine=i960-intel + os=-mon960 + ;; + nonstopux) + basic_machine=mips-compaq + os=-nonstopux + ;; + np1) + basic_machine=np1-gould + ;; + nsr-tandem) + basic_machine=nsr-tandem + ;; + op50n-* | op60c-*) + basic_machine=hppa1.1-oki + os=-proelf + ;; + openrisc | openrisc-*) + basic_machine=or32-unknown + ;; + os400) + basic_machine=powerpc-ibm + os=-os400 + ;; + OSE68000 | ose68000) + basic_machine=m68000-ericsson + os=-ose + ;; + os68k) + basic_machine=m68k-none + os=-os68k + ;; + pa-hitachi) + basic_machine=hppa1.1-hitachi + os=-hiuxwe2 + ;; + paragon) + basic_machine=i860-intel + os=-osf + ;; + pbd) + basic_machine=sparc-tti + ;; + pbb) + basic_machine=m68k-tti + ;; + pc532 | pc532-*) + basic_machine=ns32k-pc532 + ;; + pc98) + basic_machine=i386-pc + ;; + pc98-*) + basic_machine=i386-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + pentium | p5 | k5 | k6 | nexgen | viac3) + basic_machine=i586-pc + ;; + pentiumpro | p6 | 6x86 | athlon | athlon_*) + basic_machine=i686-pc + ;; + pentiumii | pentium2 | pentiumiii | pentium3) + basic_machine=i686-pc + ;; + pentium4) + basic_machine=i786-pc + ;; + pentium-* | p5-* | k5-* | k6-* | nexgen-* | viac3-*) + basic_machine=i586-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + pentiumpro-* | p6-* | 6x86-* | athlon-*) + basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + pentiumii-* | pentium2-* | pentiumiii-* | pentium3-*) + basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + pentium4-*) + basic_machine=i786-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + pn) + basic_machine=pn-gould + ;; + power) basic_machine=power-ibm + ;; + ppc) basic_machine=powerpc-unknown + ;; + ppc-*) basic_machine=powerpc-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + ppcle | powerpclittle | ppc-le | powerpc-little) + basic_machine=powerpcle-unknown + ;; + ppcle-* | powerpclittle-*) + basic_machine=powerpcle-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + ppc64) basic_machine=powerpc64-unknown + ;; + ppc64-*) basic_machine=powerpc64-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + ppc64le | powerpc64little | ppc64-le | powerpc64-little) + basic_machine=powerpc64le-unknown + ;; + ppc64le-* | powerpc64little-*) + basic_machine=powerpc64le-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + ps2) + basic_machine=i386-ibm + ;; + pw32) + basic_machine=i586-unknown + os=-pw32 + ;; + rdos) + basic_machine=i386-pc + os=-rdos + ;; + rom68k) + basic_machine=m68k-rom68k + os=-coff + ;; + rm[46]00) + basic_machine=mips-siemens + ;; + rtpc | rtpc-*) + basic_machine=romp-ibm + ;; + s390 | s390-*) + basic_machine=s390-ibm + ;; + s390x | s390x-*) + basic_machine=s390x-ibm + ;; + sa29200) + basic_machine=a29k-amd + os=-udi + ;; + sb1) + basic_machine=mipsisa64sb1-unknown + ;; + sb1el) + basic_machine=mipsisa64sb1el-unknown + ;; + sei) + basic_machine=mips-sei + os=-seiux + ;; + sequent) + basic_machine=i386-sequent + ;; + sh) + basic_machine=sh-hitachi + os=-hms + ;; + sh64) + basic_machine=sh64-unknown + ;; + sparclite-wrs | simso-wrs) + basic_machine=sparclite-wrs + os=-vxworks + ;; + sps7) + basic_machine=m68k-bull + os=-sysv2 + ;; + spur) + basic_machine=spur-unknown + ;; + st2000) + basic_machine=m68k-tandem + ;; + stratus) + basic_machine=i860-stratus + os=-sysv4 + ;; + sun2) + basic_machine=m68000-sun + ;; + sun2os3) + basic_machine=m68000-sun + os=-sunos3 + ;; + sun2os4) + basic_machine=m68000-sun + os=-sunos4 + ;; + sun3os3) + basic_machine=m68k-sun + os=-sunos3 + ;; + sun3os4) + basic_machine=m68k-sun + os=-sunos4 + ;; + sun4os3) + basic_machine=sparc-sun + os=-sunos3 + ;; + sun4os4) + basic_machine=sparc-sun + os=-sunos4 + ;; + sun4sol2) + basic_machine=sparc-sun + os=-solaris2 + ;; + sun3 | sun3-*) + basic_machine=m68k-sun + ;; + sun4) + basic_machine=sparc-sun + ;; + sun386 | sun386i | roadrunner) + basic_machine=i386-sun + ;; + sv1) + basic_machine=sv1-cray + os=-unicos + ;; + symmetry) + basic_machine=i386-sequent + os=-dynix + ;; + t3e) + basic_machine=alphaev5-cray + os=-unicos + ;; + t90) + basic_machine=t90-cray + os=-unicos + ;; + tic54x | c54x*) + basic_machine=tic54x-unknown + os=-coff + ;; + tic55x | c55x*) + basic_machine=tic55x-unknown + os=-coff + ;; + tic6x | c6x*) + basic_machine=tic6x-unknown + os=-coff + ;; + tx39) + basic_machine=mipstx39-unknown + ;; + tx39el) + basic_machine=mipstx39el-unknown + ;; + toad1) + basic_machine=pdp10-xkl + os=-tops20 + ;; + tower | tower-32) + basic_machine=m68k-ncr + ;; + tpf) + basic_machine=s390x-ibm + os=-tpf + ;; + udi29k) + basic_machine=a29k-amd + os=-udi + ;; + ultra3) + basic_machine=a29k-nyu + os=-sym1 + ;; + v810 | necv810) + basic_machine=v810-nec + os=-none + ;; + vaxv) + basic_machine=vax-dec + os=-sysv + ;; + vms) + basic_machine=vax-dec + os=-vms + ;; + vpp*|vx|vx-*) + basic_machine=f301-fujitsu + ;; + vxworks960) + basic_machine=i960-wrs + os=-vxworks + ;; + vxworks68) + basic_machine=m68k-wrs + os=-vxworks + ;; + vxworks29k) + basic_machine=a29k-wrs + os=-vxworks + ;; + w65*) + basic_machine=w65-wdc + os=-none + ;; + w89k-*) + basic_machine=hppa1.1-winbond + os=-proelf + ;; + xbox) + basic_machine=i686-pc + os=-mingw32 + ;; + xps | xps100) + basic_machine=xps100-honeywell + ;; + ymp) + basic_machine=ymp-cray + os=-unicos + ;; + z8k-*-coff) + basic_machine=z8k-unknown + os=-sim + ;; + none) + basic_machine=none-none + os=-none + ;; + +# Here we handle the default manufacturer of certain CPU types. It is in +# some cases the only manufacturer, in others, it is the most popular. + w89k) + basic_machine=hppa1.1-winbond + ;; + op50n) + basic_machine=hppa1.1-oki + ;; + op60c) + basic_machine=hppa1.1-oki + ;; + romp) + basic_machine=romp-ibm + ;; + mmix) + basic_machine=mmix-knuth + ;; + rs6000) + basic_machine=rs6000-ibm + ;; + vax) + basic_machine=vax-dec + ;; + pdp10) + # there are many clones, so DEC is not a safe bet + basic_machine=pdp10-unknown + ;; + pdp11) + basic_machine=pdp11-dec + ;; + we32k) + basic_machine=we32k-att + ;; + sh[1234] | sh[24]a | sh[34]eb | sh[1234]le | sh[23]ele) + basic_machine=sh-unknown + ;; + sparc | sparcv8 | sparcv9 | sparcv9b | sparcv9v) + basic_machine=sparc-sun + ;; + cydra) + basic_machine=cydra-cydrome + ;; + orion) + basic_machine=orion-highlevel + ;; + orion105) + basic_machine=clipper-highlevel + ;; + mac | mpw | mac-mpw) + basic_machine=m68k-apple + ;; + pmac | pmac-mpw) + basic_machine=powerpc-apple + ;; + *-unknown) + # Make sure to match an already-canonicalized machine name. + ;; + *) + echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2 + exit 1 + ;; +esac + +# Here we canonicalize certain aliases for manufacturers. +case $basic_machine in + *-digital*) + basic_machine=`echo $basic_machine | sed 's/digital.*/dec/'` + ;; + *-commodore*) + basic_machine=`echo $basic_machine | sed 's/commodore.*/cbm/'` + ;; + *) + ;; +esac + +# Decode manufacturer-specific aliases for certain operating systems. + +if [ x"$os" != x"" ] +then +case $os in + # First match some system type aliases + # that might get confused with valid system types. + # -solaris* is a basic system type, with this one exception. + -solaris1 | -solaris1.*) + os=`echo $os | sed -e 's|solaris1|sunos4|'` + ;; + -solaris) + os=-solaris2 + ;; + -svr4*) + os=-sysv4 + ;; + -unixware*) + os=-sysv4.2uw + ;; + -gnu/linux*) + os=`echo $os | sed -e 's|gnu/linux|linux-gnu|'` + ;; + # First accept the basic system types. + # The portable systems comes first. + # Each alternative MUST END IN A *, to match a version number. + # -sysv* is not here because it comes later, after sysvr4. + -gnu* | -bsd* | -mach* | -minix* | -genix* | -ultrix* | -irix* \ + | -*vms* | -sco* | -esix* | -isc* | -aix* | -sunos | -sunos[34]*\ + | -hpux* | -unos* | -osf* | -luna* | -dgux* | -solaris* | -sym* \ + | -amigaos* | -amigados* | -msdos* | -newsos* | -unicos* | -aof* \ + | -aos* \ + | -nindy* | -vxsim* | -vxworks* | -ebmon* | -hms* | -mvs* \ + | -clix* | -riscos* | -uniplus* | -iris* | -rtu* | -xenix* \ + | -hiux* | -386bsd* | -knetbsd* | -mirbsd* | -netbsd* \ + | -openbsd* | -solidbsd* \ + | -ekkobsd* | -kfreebsd* | -freebsd* | -riscix* | -lynxos* \ + | -bosx* | -nextstep* | -cxux* | -aout* | -elf* | -oabi* \ + | -ptx* | -coff* | -ecoff* | -winnt* | -domain* | -vsta* \ + | -udi* | -eabi* | -lites* | -ieee* | -go32* | -aux* \ + | -chorusos* | -chorusrdb* \ + | -cygwin* | -pe* | -psos* | -moss* | -proelf* | -rtems* \ + | -mingw32* | -linux-gnu* | -linux-newlib* | -linux-uclibc* \ + | -uxpv* | -beos* | -mpeix* | -udk* \ + | -interix* | -uwin* | -mks* | -rhapsody* | -darwin* | -opened* \ + | -openstep* | -oskit* | -conix* | -pw32* | -nonstopux* \ + | -storm-chaos* | -tops10* | -tenex* | -tops20* | -its* \ + | -os2* | -vos* | -palmos* | -uclinux* | -nucleus* \ + | -morphos* | -superux* | -rtmk* | -rtmk-nova* | -windiss* \ + | -powermax* | -dnix* | -nx6 | -nx7 | -sei* | -dragonfly* \ + | -skyos* | -haiku* | -rdos* | -toppers*) + # Remember, each alternative MUST END IN *, to match a version number. + ;; + -qnx*) + case $basic_machine in + x86-* | i*86-*) + ;; + *) + os=-nto$os + ;; + esac + ;; + -nto-qnx*) + ;; + -nto*) + os=`echo $os | sed -e 's|nto|nto-qnx|'` + ;; + -sim | -es1800* | -hms* | -xray | -os68k* | -none* | -v88r* \ + | -windows* | -osx | -abug | -netware* | -os9* | -beos* | -haiku* \ + | -macos* | -mpw* | -magic* | -mmixware* | -mon960* | -lnews*) + ;; + -mac*) + os=`echo $os | sed -e 's|mac|macos|'` + ;; + -linux-dietlibc) + os=-linux-dietlibc + ;; + -linux*) + os=`echo $os | sed -e 's|linux|linux-gnu|'` + ;; + -sunos5*) + os=`echo $os | sed -e 's|sunos5|solaris2|'` + ;; + -sunos6*) + os=`echo $os | sed -e 's|sunos6|solaris3|'` + ;; + -opened*) + os=-openedition + ;; + -os400*) + os=-os400 + ;; + -wince*) + os=-wince + ;; + -osfrose*) + os=-osfrose + ;; + -osf*) + os=-osf + ;; + -utek*) + os=-bsd + ;; + -dynix*) + os=-bsd + ;; + -acis*) + os=-aos + ;; + -atheos*) + os=-atheos + ;; + -syllable*) + os=-syllable + ;; + -386bsd) + os=-bsd + ;; + -ctix* | -uts*) + os=-sysv + ;; + -nova*) + os=-rtmk-nova + ;; + -ns2 ) + os=-nextstep2 + ;; + -nsk*) + os=-nsk + ;; + # Preserve the version number of sinix5. + -sinix5.*) + os=`echo $os | sed -e 's|sinix|sysv|'` + ;; + -sinix*) + os=-sysv4 + ;; + -tpf*) + os=-tpf + ;; + -triton*) + os=-sysv3 + ;; + -oss*) + os=-sysv3 + ;; + -svr4) + os=-sysv4 + ;; + -svr3) + os=-sysv3 + ;; + -sysvr4) + os=-sysv4 + ;; + # This must come after -sysvr4. + -sysv*) + ;; + -ose*) + os=-ose + ;; + -es1800*) + os=-ose + ;; + -xenix) + os=-xenix + ;; + -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*) + os=-mint + ;; + -aros*) + os=-aros + ;; + -kaos*) + os=-kaos + ;; + -zvmoe) + os=-zvmoe + ;; + -none) + ;; + *) + # Get rid of the `-' at the beginning of $os. + os=`echo $os | sed 's/[^-]*-//'` + echo Invalid configuration \`$1\': system \`$os\' not recognized 1>&2 + exit 1 + ;; +esac +else + +# Here we handle the default operating systems that come with various machines. +# The value should be what the vendor currently ships out the door with their +# machine or put another way, the most popular os provided with the machine. + +# Note that if you're going to try to match "-MANUFACTURER" here (say, +# "-sun"), then you have to tell the case statement up towards the top +# that MANUFACTURER isn't an operating system. Otherwise, code above +# will signal an error saying that MANUFACTURER isn't an operating +# system, and we'll never get to this point. + +case $basic_machine in + spu-*) + os=-elf + ;; + *-acorn) + os=-riscix1.2 + ;; + arm*-rebel) + os=-linux + ;; + arm*-semi) + os=-aout + ;; + c4x-* | tic4x-*) + os=-coff + ;; + # This must come before the *-dec entry. + pdp10-*) + os=-tops20 + ;; + pdp11-*) + os=-none + ;; + *-dec | vax-*) + os=-ultrix4.2 + ;; + m68*-apollo) + os=-domain + ;; + i386-sun) + os=-sunos4.0.2 + ;; + m68000-sun) + os=-sunos3 + # This also exists in the configure program, but was not the + # default. + # os=-sunos4 + ;; + m68*-cisco) + os=-aout + ;; + mips*-cisco) + os=-elf + ;; + mips*-*) + os=-elf + ;; + or32-*) + os=-coff + ;; + *-tti) # must be before sparc entry or we get the wrong os. + os=-sysv3 + ;; + sparc-* | *-sun) + os=-sunos4.1.1 + ;; + *-be) + os=-beos + ;; + *-haiku) + os=-haiku + ;; + *-ibm) + os=-aix + ;; + *-knuth) + os=-mmixware + ;; + *-wec) + os=-proelf + ;; + *-winbond) + os=-proelf + ;; + *-oki) + os=-proelf + ;; + *-hp) + os=-hpux + ;; + *-hitachi) + os=-hiux + ;; + i860-* | *-att | *-ncr | *-altos | *-motorola | *-convergent) + os=-sysv + ;; + *-cbm) + os=-amigaos + ;; + *-dg) + os=-dgux + ;; + *-dolphin) + os=-sysv3 + ;; + m68k-ccur) + os=-rtu + ;; + m88k-omron*) + os=-luna + ;; + *-next ) + os=-nextstep + ;; + *-sequent) + os=-ptx + ;; + *-crds) + os=-unos + ;; + *-ns) + os=-genix + ;; + i370-*) + os=-mvs + ;; + *-next) + os=-nextstep3 + ;; + *-gould) + os=-sysv + ;; + *-highlevel) + os=-bsd + ;; + *-encore) + os=-bsd + ;; + *-sgi) + os=-irix + ;; + *-siemens) + os=-sysv4 + ;; + *-masscomp) + os=-rtu + ;; + f30[01]-fujitsu | f700-fujitsu) + os=-uxpv + ;; + *-rom68k) + os=-coff + ;; + *-*bug) + os=-coff + ;; + *-apple) + os=-macos + ;; + *-atari*) + os=-mint + ;; + *) + os=-none + ;; +esac +fi + +# Here we handle the case where we know the os, and the CPU type, but not the +# manufacturer. We pick the logical manufacturer. +vendor=unknown +case $basic_machine in + *-unknown) + case $os in + -riscix*) + vendor=acorn + ;; + -sunos*) + vendor=sun + ;; + -aix*) + vendor=ibm + ;; + -beos*) + vendor=be + ;; + -hpux*) + vendor=hp + ;; + -mpeix*) + vendor=hp + ;; + -hiux*) + vendor=hitachi + ;; + -unos*) + vendor=crds + ;; + -dgux*) + vendor=dg + ;; + -luna*) + vendor=omron + ;; + -genix*) + vendor=ns + ;; + -mvs* | -opened*) + vendor=ibm + ;; + -os400*) + vendor=ibm + ;; + -ptx*) + vendor=sequent + ;; + -tpf*) + vendor=ibm + ;; + -vxsim* | -vxworks* | -windiss*) + vendor=wrs + ;; + -aux*) + vendor=apple + ;; + -hms*) + vendor=hitachi + ;; + -mpw* | -macos*) + vendor=apple + ;; + -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*) + vendor=atari + ;; + -vos*) + vendor=stratus + ;; + esac + basic_machine=`echo $basic_machine | sed "s/unknown/$vendor/"` + ;; +esac + +echo $basic_machine$os +exit + +# Local variables: +# eval: (add-hook 'write-file-hooks 'time-stamp) +# time-stamp-start: "timestamp='" +# time-stamp-format: "%:y-%02m-%02d" +# time-stamp-end: "'" +# End: diff --git a/modules/cfitsio/autoconf/configure.in b/modules/cfitsio/autoconf/configure.in new file mode 100644 index 0000000..fa34a48 --- /dev/null +++ b/modules/cfitsio/autoconf/configure.in @@ -0,0 +1,53 @@ +dnl -*- sh -*- +AC_INIT(src/cfitsio-module.c) +AC_PREFIX_DEFAULT(/usr/local) + +AC_CONFIG_AUX_DIR(autoconf) +AC_CANONICAL_HOST +AC_PROG_RANLIB +AC_PROG_INSTALL +AC_PROG_MAKE_SET + +JD_INIT +JD_ANSI_CC +JD_ELF_COMPILER +JD_IEEE_CFLAGS + +AC_PATH_XTRA + +dnl# JD_FIND_GENERIC(slang) +JD_WITH_LIBRARY(slang) +JD_WITH_LIBRARY(cfitsio, fitsio.h) + +JD_SLANG_MODULE_INSTALL_DIR + +dnl Check these header since they cause trouble +AC_CHECK_HEADERS( \ +stdlib.h \ +unistd.h \ +) +AC_CHECK_SIZEOF(short, 2) +AC_CHECK_SIZEOF(int, 4) +AC_CHECK_SIZEOF(long, 4) +AC_CHECK_SIZEOF(float, 4) +AC_CHECK_SIZEOF(double, 8) + +dnl #JD_SET_RPATH($libdir) +ELF_CFLAGS="$ELF_CFLAGS $IEEE_CFLAGS" +CFLAGS="$CFLAGS $IEEE_CFLAGS" + +AC_CONFIG_HEADER(src/config.h:src/config.hin) +AC_OUTPUT(Makefile:autoconf/Makefile.in src/Makefile) + +echo "" +echo "You are compiling with the following compiler configuration:" +echo " CC =" "$CC" +echo " CC_SHARED =" "$CC_SHARED" +echo " CFLAGS =" "$CFLAGS" +echo " LDFLAGS =" "$LDFLAGS" "$DYNAMIC_LINK_FLAGS" +echo "" +echo "The modules will be installed in $MODULE_INSTALL_DIR." +echo "Any associated .sl files will be install in $SL_FILES_INSTALL_DIR" +echo "" +echo "If any of these quantities are incorrect, edit src/Makefile accordingly." +echo "" diff --git a/modules/cfitsio/autoconf/install-sh b/modules/cfitsio/autoconf/install-sh new file mode 100755 index 0000000..e9de238 --- /dev/null +++ b/modules/cfitsio/autoconf/install-sh @@ -0,0 +1,251 @@ +#!/bin/sh +# +# install - install a program, script, or datafile +# This comes from X11R5 (mit/util/scripts/install.sh). +# +# Copyright 1991 by the Massachusetts Institute of Technology +# +# Permission to use, copy, modify, distribute, and sell this software and its +# documentation for any purpose is hereby granted without fee, provided that +# the above copyright notice appear in all copies and that both that +# copyright notice and this permission notice appear in supporting +# documentation, and that the name of M.I.T. not be used in advertising or +# publicity pertaining to distribution of the software without specific, +# written prior permission. M.I.T. makes no representations about the +# suitability of this software for any purpose. It is provided "as is" +# without express or implied warranty. +# +# Calling this script install-sh is preferred over install.sh, to prevent +# `make' implicit rules from creating a file called install from it +# when there is no Makefile. +# +# This script is compatible with the BSD install script, but was written +# from scratch. It can only install one file at a time, a restriction +# shared with many OS's install programs. + + +# set DOITPROG to echo to test this script + +# Don't use :- since 4.3BSD and earlier shells don't like it. +doit="${DOITPROG-}" + + +# put in absolute paths if you don't have them in your path; or use env. vars. + +mvprog="${MVPROG-mv}" +cpprog="${CPPROG-cp}" +chmodprog="${CHMODPROG-chmod}" +chownprog="${CHOWNPROG-chown}" +chgrpprog="${CHGRPPROG-chgrp}" +stripprog="${STRIPPROG-strip}" +rmprog="${RMPROG-rm}" +mkdirprog="${MKDIRPROG-mkdir}" + +transformbasename="" +transform_arg="" +instcmd="$mvprog" +chmodcmd="$chmodprog 0755" +chowncmd="" +chgrpcmd="" +stripcmd="" +rmcmd="$rmprog -f" +mvcmd="$mvprog" +src="" +dst="" +dir_arg="" + +while [ x"$1" != x ]; do + case $1 in + -c) instcmd="$cpprog" + shift + continue;; + + -d) dir_arg=true + shift + continue;; + + -m) chmodcmd="$chmodprog $2" + shift + shift + continue;; + + -o) chowncmd="$chownprog $2" + shift + shift + continue;; + + -g) chgrpcmd="$chgrpprog $2" + shift + shift + continue;; + + -s) stripcmd="$stripprog" + shift + continue;; + + -t=*) transformarg=`echo $1 | sed 's/-t=//'` + shift + continue;; + + -b=*) transformbasename=`echo $1 | sed 's/-b=//'` + shift + continue;; + + *) if [ x"$src" = x ] + then + src=$1 + else + # this colon is to work around a 386BSD /bin/sh bug + : + dst=$1 + fi + shift + continue;; + esac +done + +if [ x"$src" = x ] +then + echo "install: no input file specified" + exit 1 +else + true +fi + +if [ x"$dir_arg" != x ]; then + dst=$src + src="" + + if [ -d $dst ]; then + instcmd=: + chmodcmd="" + else + instcmd=mkdir + fi +else + +# Waiting for this to be detected by the "$instcmd $src $dsttmp" command +# might cause directories to be created, which would be especially bad +# if $src (and thus $dsttmp) contains '*'. + + if [ -f $src -o -d $src ] + then + true + else + echo "install: $src does not exist" + exit 1 + fi + + if [ x"$dst" = x ] + then + echo "install: no destination specified" + exit 1 + else + true + fi + +# If destination is a directory, append the input filename; if your system +# does not like double slashes in filenames, you may need to add some logic + + if [ -d $dst ] + then + dst="$dst"/`basename $src` + else + true + fi +fi + +## this sed command emulates the dirname command +dstdir=`echo $dst | sed -e 's,[^/]*$,,;s,/$,,;s,^$,.,'` + +# Make sure that the destination directory exists. +# this part is taken from Noah Friedman's mkinstalldirs script + +# Skip lots of stat calls in the usual case. +if [ ! -d "$dstdir" ]; then +defaultIFS=' +' +IFS="${IFS-${defaultIFS}}" + +oIFS="${IFS}" +# Some sh's can't handle IFS=/ for some reason. +IFS='%' +set - `echo ${dstdir} | sed -e 's@/@%@g' -e 's@^%@/@'` +IFS="${oIFS}" + +pathcomp='' + +while [ $# -ne 0 ] ; do + pathcomp="${pathcomp}${1}" + shift + + if [ ! -d "${pathcomp}" ] ; + then + $mkdirprog "${pathcomp}" + else + true + fi + + pathcomp="${pathcomp}/" +done +fi + +if [ x"$dir_arg" != x ] +then + $doit $instcmd $dst && + + if [ x"$chowncmd" != x ]; then $doit $chowncmd $dst; else true ; fi && + if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dst; else true ; fi && + if [ x"$stripcmd" != x ]; then $doit $stripcmd $dst; else true ; fi && + if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dst; else true ; fi +else + +# If we're going to rename the final executable, determine the name now. + + if [ x"$transformarg" = x ] + then + dstfile=`basename $dst` + else + dstfile=`basename $dst $transformbasename | + sed $transformarg`$transformbasename + fi + +# don't allow the sed command to completely eliminate the filename + + if [ x"$dstfile" = x ] + then + dstfile=`basename $dst` + else + true + fi + +# Make a temp file name in the proper directory. + + dsttmp=$dstdir/#inst.$$# + +# Move or copy the file name to the temp name + + $doit $instcmd $src $dsttmp && + + trap "rm -f ${dsttmp}" 0 && + +# and set any options; do chmod last to preserve setuid bits + +# If any of these fail, we abort the whole thing. If we want to +# ignore errors from any of these, just make sure not to ignore +# errors from the above "$doit $instcmd $src $dsttmp" command. + + if [ x"$chowncmd" != x ]; then $doit $chowncmd $dsttmp; else true;fi && + if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dsttmp; else true;fi && + if [ x"$stripcmd" != x ]; then $doit $stripcmd $dsttmp; else true;fi && + if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dsttmp; else true;fi && + +# Now rename the file to the real destination. + + $doit $rmcmd -f $dstdir/$dstfile && + $doit $mvcmd $dsttmp $dstdir/$dstfile + +fi && + + +exit 0 diff --git a/modules/cfitsio/autoconf/mkinsdir.sh b/modules/cfitsio/autoconf/mkinsdir.sh new file mode 100755 index 0000000..cd1fe0a --- /dev/null +++ b/modules/cfitsio/autoconf/mkinsdir.sh @@ -0,0 +1,32 @@ +#! /bin/sh +# mkinstalldirs --- make directory hierarchy +# Author: Noah Friedman +# Created: 1993-05-16 +# Public domain + +errstatus=0 + +for file +do + set fnord `echo ":$file" | sed -ne 's/^:\//#/;s/^://;s/\// /g;s/^#/\//;p'` + shift + + pathcomp= + for d in ${1+"$@"} ; do + pathcomp="$pathcomp$d" + case "$pathcomp" in + -* ) pathcomp=./$pathcomp ;; + esac + + if test ! -d "$pathcomp"; then + echo "mkdir $pathcomp" 1>&2 + mkdir "$pathcomp" || errstatus=$? + fi + + pathcomp="$pathcomp/" + done +done + +exit $errstatus + +# mkinstalldirs ends here diff --git a/modules/cfitsio/cfitsio.lis b/modules/cfitsio/cfitsio.lis new file mode 100644 index 0000000..2d649f2 --- /dev/null +++ b/modules/cfitsio/cfitsio.lis @@ -0,0 +1,29 @@ +@cfitsio.lis +@configure 0755 +@COPYRIGHT +@README +@INSTALL.txt + +@ChangeLog + +@share/readrmf.sl + +@autoconf/Makefile.in +@autoconf/aclocal.m4 +@autoconf/config.guess 0755 +@autoconf/config.sub 0755 +@autoconf/configure.in +@autoconf/install-sh 0755 +@autoconf/mkinsdir.sh 0755 + +@src/mkversion.sh 0755 +@src/Makefile.in +@src/cfitsio-module.c +@src/cfitsio.sl +@src/fits.sl +@src/fitswcs.sl +@src/config.hin + +@doc/fits.txt + + diff --git a/modules/cfitsio/doc/tm/Makefile b/modules/cfitsio/doc/tm/Makefile new file mode 100644 index 0000000..8c64689 --- /dev/null +++ b/modules/cfitsio/doc/tm/Makefile @@ -0,0 +1,93 @@ +# -*- sh -*- +# +# To create the SGML files, you will need to install the tm-utils +# package. See http://www.jedsoft.org/ for more information. +# +TMEXPAND = /aluche/d1/web/tm-dist/bin/tmexpand +SL2TM = sl2tm +MACRODIR = /aluche/d1/web/tm-dist/macros + +MODULE = cfitsio +HLPFUNS_TM = rtl/cfitsiofuns.tm fitsfuns.tm fitswcsfuns.tm +AUTOGEN_TM = fitswcsfuns.tm fitsfuns.tm +MODULE_DEPS = rtl/cfitsiofuns.tm $(AUTOGEN_TM) + +TXT_FILES = $(MODULE).txt +SGML_FILES = $(MODULE).sgml +HTML_FILES = $(MODULE).html +TEX_FILES = $(MODULE).tex +PS_FILES = $(MODULE).ps +PDF_FILES = $(MODULE).pdf +HLP_FILE = $(MODULE).hlp + +HLP_TM_FILE = helpfile.tm + +SGML2LATEX = sgml2latex -p letter -o tex +SGML2HTML = sgml2html +SGML2TXT = sgml2txt -f +LATEX = latex +PDFLATEX = pdflatex + +TEXTDIR = ../text +PSDIR = ../ps +HTMLDIR = ../html +SGMLDIR = ../sgml +PDFDIR = ../pdf +HELPDIR = ../help + +SUBDIRS = $(TEXTDIR) $(HTMLDIR) $(PSDIR) $(SGMLDIR) $(PDFDIR) $(HELPDIR) +SRCDIR = `pwd` + +all: $(SGML_FILES) $(HTML_FILES) $(TEX_FILES) $(TXT_FILES) +fitsfuns.tm: ../../src/fits.sl + $(SL2TM) ../../src/fits.sl > fitsfuns.tm +fitswcsfuns.tm: ../../src/fitswcs.sl + $(SL2TM) ../../src/fitswcs.sl > fitswcsfuns.tm +text-files: $(TXT_FILES) +#----- SGML Files ----------------------------------------------------------- +$(MODULE).sgml : $(MODULE).tm $(MODULE_DEPS) + $(TMEXPAND) -I$(MACRODIR) $(MODULE).tm $(MODULE).sgml +#----- HTML Files ----------------------------------------------------------- +$(MODULE).html : $(MODULE).sgml + $(SGML2HTML) $(MODULE).sgml +#----- TeX Files ------------------------------------------------------------ +$(MODULE).tex : $(MODULE).sgml + $(SGML2LATEX) $(MODULE).sgml + ./fixtex.sl $(MODULE).tex +#----- PDF Files ----------------------------------------------------------- +$(MODULE).pdf : $(MODULE).tex + $(MAKE) texclean + $(PDFLATEX) $(MODULE).tex + $(PDFLATEX) $(MODULE).tex + $(PDFLATEX) $(MODULE).tex +#----- PS Files ----------------------------------------------------------- +$(MODULE).ps : $(MODULE).tex texclean + $(LATEX) $(MODULE).tex + $(LATEX) $(MODULE).tex + $(LATEX) $(MODULE).tex + dvips -o $(MODULE).ps $(MODULE).dvi +#----- Text Files ----------------------------------------------------------- +$(MODULE).txt: $(MODULE).sgml + $(SGML2TXT) $(MODULE).sgml +#---------------------------------------------------------------------------- +help-files: $(HLP_FILE) +$(HLP_FILE): $(HLP_TM_FILE) $(HLPFUNS_TM) + $(TMEXPAND) -I$(MACRODIR) $(HLP_TM_FILE) $(HLP_FILE) +texclean: + -rm -f *.dvi *.log *.aux *.toc *.out +clean: texclean + -rm -f *~ rtl/*.BAK rtl/*~ *.tmp *-error +distclean: clean + -rm -f *.html *.ps $(HLP_FILE) $(TXT_FILES) $(TEX_FILES) $(SGML_FILES) $(PDF_FILES) $(AUTOGEN_TM) +install-txt: $(TXT_FILES) + -mv $(TXT_FILES) ../text +install-help: $(HLP_FILE) + -mkdir -p $(HELPDIR) + -mv $(HLP_FILE) $(HELPDIR) +install-all: all install-help install-txt $(PS_FILES) $(PDF_FILES) + -mkdir -p $(HTMLDIR) $(PSDIR) $(SGMLDIR) $(PDFDIR) + -mv *.html $(HTMLDIR) + -mv $(PS_FILES) ../ps + -mv $(SGML_FILES) ../sgml + -mv $(PDF_FILES) ../pdf +install: install-txt install-help diff --git a/modules/cfitsio/doc/tm/cfitsio.tm b/modules/cfitsio/doc/tm/cfitsio.tm new file mode 100644 index 0000000..e4bb18b --- /dev/null +++ b/modules/cfitsio/doc/tm/cfitsio.tm @@ -0,0 +1,848 @@ +#% -*- mode: tm; mode: fold -*- + +#%{{{Macros + +#i linuxdoc.tm +#d it#1 $1 + +#d slang \bf{S-lang} +#d exmp#1 \tt{$1} +#d var#1 \tt{$1} + +#d ivar#1 \tt{$1} +#d ifun#1 \tt{$1} +#d cvar#1 \tt{$1} +#d cfun#1 \tt{$1} +#d svar#1 \tt{$1} +#d sfun#1 \tt{$1} +#d icon#1 \tt{$1} + +#d chapter#1 $1

+#d preface +#d tag#1 $1 + +#d function#1 \sect1{$1\label{$1}} +#d variable#1 \sect1{$1\label{$1}} +#d function_sect#1 \sect{$1} +#d begin_constant_sect#1 \sect{$1} +#d constant#1 $1 +#d end_constant_sect + +#d synopsis#1 Synopsis $1 +#d keywords#1 Keywords $1 +#d usage#1 Usage $1 +#d description Description +#d example Example +#d notes Notes +#d seealso#1 See Also \linuxdoc_list_to_ref{$1} +#d done

+#d -1 -1 +#d 0 0 +#d 1 1 +#d 2 2 +#d 3 3 +#d 4 4 +#d 5 5 +#d 6 6 +#d 7 7 +#d 8 8 +#d 9 9 +#d NULL NULL +#d file#1 $1 + +#d documentstyle book + +#%}}} + +#d module#1 \tt{$1} + +\linuxdoc +\begin{\documentstyle} + +\title S-Lang CFITSIO Module Reference +\author John E. Davis, \tt{davis@space.mit.edu} +\date \__today__ + +\toc + +#d cfitsio_url http://heasarc.gsfc.nasa.gov/docs/software/fitsio/ +#d cfitsio_ref_url \ + http://heasarc.gsfc.nasa.gov/docs/software/fitsio/c/c_user/cfitsio.html +#d fits_url http://heasarc.gsfc.nasa.gov/docs/heasarc/fits.html +#d FITS FITS + +#d CFITSIO CFITSIO + +\chapter{Introduction} #%{{{ + + \url{\fits_url}{FITS} (Flexible Image Transport System) is a data + format that is in widespread use by the astronomical community. + \url{\cfitsio_ref_url}{CFITSIO} is a popular C library that + interfaces to such files and provides support for all features of the + format. Moreover \CFITSIO supports a number of unofficial or + proposed \FITS conventions that are in widespread use. + + This package makes use of the \CFITSIO library allow one to + manipulate \FITS files from the \slang interpreter. The package + consists of two interfaces: a high level interface and a low level + one. The low level interface is implemented as a module and is more + or less a straightforward wrapping of the functions of the \CFITSIO + library. Functions from this interface are prefixed with an + underscore to indicate that they are part of the low-level interface. + The high level interface is written in \slang and makes use of + functions from the low level interface. While there is some overlap + with the semantics of the \CFITSIO library, the high level interface + should be regarded as a separate interface to fits files. + + To illustrate the difference between the two interfaces, consider the + low-level \ifun{_fits_read_col} function and its high level + counterpart \sfun{fits_read_col}. The low-level function reads a + single column, specified via the column number, from a fits binary + table and performs a minimal amount of error checking. In contrast, + \sfun{fits_read_col} is a high level function that reads one or more + columns, specified either as column numbers or named columns, from a + table and does so in a way that takes into account the way \CFITSIO + performs buffering for maximum efficiency. Moreover, the high level + function checks for the presence of TDIM keywords or columns to give + the arrays it returns the proper dimensionality. If any errors + occur, the function will throw an exception. + +#%}}} + +\chapter{The high-level interface} + +\sect{Overview} #%{{{ + + The high-level interface consists of a number of functions that are + written in \slang and are designed to take some of the tedium out of + performing standard operations on fits files. To illustrate this + point, consider the creation of a fits file with a binary table + extension called called ``COSXSINX'': +#v+ + variable data = struct { x, cosx, sinx }; + data.x = [0:2*PI:0.01]; + data.cosx = cos(data.x); + data.sinx = sin(data.x); + fits_write_binary_table ("foo.fits", "COSXSINX", data); +#v- + It can't get much easier than that! + +#%}}} + +\sect{Opening and Closing Files} #%{{{ + + In general the high-level functions take an argument that represents + the fits file to be manipulated. It may be either an already open + file pointer such as one returned by \sfun{fits_open_file}, or the + name of a file to be opened. In the documentation for the functions, + this fact is indicated by +#v+ + Fits_File_Type or String_Type fd; +#v- + showing that the file descriptor may be either an open file pointer + or a string. + + If specified as a string, then a fits file of that name will be + opened in a mode that is compatible with the operation being + performed, with the current HDU (header-data unit) set to the first + ``most interesting'' one. Here, ``first most interesting'' + means the first HDU with a non-zero value for the NAXIS keyword. + + For example, sometimes one simply wants to read some keywords from a + file. In such a case it is not necessary to explicitly call + \sfun{fits_open_file}. Rather simply pass the name of the file to + the appropriate function: +#v+ + (object, ra_targ, dec_targ) + = fits_read_key ("foo.fits", "OBJECT", "RA_TARG", "DEC_TARG"); +#v- + It may be necessary to specify which HDU should be used if the + ``first most interesting'' one is not the desired HDU. The easiest way + to do that is to specify the extension using \CFITSIO's virtual file + syntax, e.g., +#v+ + (object, ra_targ, dec_targ) + = fits_read_key ("foo.fits+1", "OBJECT", "RA_TARG", "DEC_TARG"); + (object, ra_targ, dec_targ) + = fits_read_key ("foo.fits[EVENTS]", "OBJECT", "RA_TARG", "DEC_TARG"); +#v- + + If one is going to make a number of calls to functions in the + high-level interface using the same file, then it is a good idea to + explicitly open the file, e.g., +#v+ + fptr = fits_open_file ("foo.fits[EVENTS]", "w"); +#v- + opens the file for both reading and writing and sets the current HDU + to the ``EVENTS'' extension. + + The object returned by the \sfun{fits_open_file} function is an + object of type \var{Fits_File_Type}. It is automatically destroyed + when it goes out of scope. When this happens, the fits file + attached to it will be silently closed. Consider: +#v+ + define write_image_to_file (file, img) + { + variable fptr = fits_open_file ("new.fits", "c"); + fits_write_image (fptr, NULL, img, NULL, NULL); + fits_write_date (fptr); + } +#v- + Here, the \exmp{write_image_to_file} function will create a new file + called \file{new.fits} and write the specified image to the file. In + this example, the file pointer object was not explicitly closed. + Since the \exmp{fptr} variable goes out of scope when the function + returns, the cfitsio module will silently close the file. While + this is a convenient feature for many purposes, it is always better + to explicitly close a file when it has been modified. The reason + for this is that \CFITSIO writes to internal buffers and then + flushes those to the disk. Often some buffers will not get written + to the disk until the file is closed. If the disk is full, or + something else goes wrong then the file will not be properly closed + resulting in a incomplete or corrupt file. Hence it is strongly + recommended that one explicitly close a file after writing to a + file, i.e., +#v+ + define write_image_to_file (file, img) + { + variable fptr = fits_open_file ("new.fits", "c"); + fits_write_image (fptr, NULL, img, NULL, NULL); + fits_write_date (fptr); + fits_close_file (fptr); + } +#v- + +#%}}} + +\sect{Keywords} + + The high-level interface contains several functions for manipulating + header keywords and records. + + \sect1{Reading Header Keywords} #%{{{ + + The \sfun{fits_read_key} may be used to read the values of one or + more keywords. Suppose that the file \file{casA.fits} contains the + following keywords in an extension called ``EVENTS'': +#v+ + TELESCOP= 'CHANDRA ' / Telescope + INSTRUME= 'ACIS ' / Instrument + DETNAM = 'ACIS-7 ' / Detector + GRATING = 'NONE ' / Grating + OBJECT = 'CAS A ' / Source name + RA_NOM = 350.91781217089 / Nominal RA + DEC_NOM = 58.792819089577 / Nominal Dec + ROLL_NOM= 323.38710408328 / Nominal Roll +#v- + The \sfun{fits_read_key} function may be used to read, e.g, the + OBJECT and RA_NOM keywords: +#v+ + (obj, ra) = fits_read_key ("casA.fits[EVENTS]", "OBJECT", "RA_NOM"); +#v- + After the function call, the variables \exmp{obj} and \exmp{ra} will + have the data types \var{String_Type} and \var{Double_Type}, resp. + If the requested keyword does not exist in the header, the function + will return \NULL to signal its not existence: +#v+ + exptime = fits_read_key ("casA.fits[EVENTS]", "EXPTIME"); + if (exptime == NULL) + { + message ("*** Warning: EXPTIME does not exist. Assuming 3.2); + exptime = 3.2; + } +#v- + + The \sfun{fits_read_key_struct} is an alternative to + \sfun{fits_read_key} that returns a structure with field names that + correspond to the keyword names. In most cases, a field name will + just be the lower case version of the keyword name. However, if the + keyword name does not start with an alphabetic character or contains + a hyphen, then it will be normalized as follows: +\begin{enum} + \item The keyword name will be lowercased. + \item All non-alphanumeric characters will be changed to an underscore. + \item If the first character of the resulting name is numeric, then + the name will be prefixed with an underscore. +\end{enum} + To illustrate the normalization process, consider: +#v+ + keys = fits_read_key_struct ("foo.fits", "OBJECT", "2CRVL3", + "DATE-OBS"); +#v- + After the function call, \exmp{keys} will be a structure with the 3 + fields: \exmp{object}, \exmp{_2crvl3}, and \exmp{date_obs}. If any + of these keywords do not exist in the header, the value of the + corresponding structure field will be NULL. + +#%}}} + + \sect1{Writing Header Keywords} #%{{{ + + The \sfun{fits_update_key} function may be used to write or update + the value of a keyword. If a keyword of the specified name exists, + then the value of the keyword will be updated to the new value. + Otherwise a new keyword will be appended to the header. + + Other specialized keyword writing routines include + \sfun{fits_write_date}, which write the current date in the required + format, and \sfun{fits_write_chksum}, which computes and updates the + checksum of the HDU. Finally the \sfun{fits_write_comment} and + \sfun{fits_write_history} functions may be used to write comments + and history records to the header, respectively. + +#%}}} + +\sect{Binary Tables} + + \sect1{Reading Binary Tables} #%{{{ + + There are a several functions for reading binary tables. The + simplest one, \sfun{fits_read_table} reads the entire binary table + into a structure, whose fields correspond to the names of the columns + in the table. (If a column has a name that contains non-alphanumeric + characters, or does not start with an alphabetic character, then the + structure field name for the column will be undergo the normalization + process described for keywords.) For example, consider a file called + \exmp{foo.fits} with a binary table whose structure is defined by the + FITS header: +#v+ + XTENSION= 'BINTABLE' + BITPIX = 8 + NAXIS = 2 + NAXIS1 = 34 + NAXIS2 = 500 + PCOUNT = 0 + GCOUNT = 1 + TFIELDS = 4 + TTYPE1 = 'TIME ' + TFORM1 = 'D ' + TTYPE2 = 'X ' + TFORM2 = 'E ' + TTYPE3 = 'Y ' + TFORM3 = 'E ' + TTYPE4 = 'PHAS ' + TFORM4 = '9I ' + EXTNAME = 'EXAMPLE ' + TDIM4 = '(3,3) ' +#v- + This header shows that the binary table is 500 rows in length and + contains 4 columns with names TIME, X, Y, and PHAS. The table may be + read via +#v+ + tbl = fits_read_table ("foo.fits[EXAMPLE]"); +#v- + assigning a structure to the \exmp{tbl} variable. The structure has + fields with names \exmp{time}, \exmp{x}, \exmp{y}, and \exmp{phas}, + which be displayed via +#v+ + vmessage ("tbl.time = %S", tbl.time); + vmessage ("tbl.x = %S", tbl.x); + vmessage ("tbl.y = %S", tbl.y); + vmessage ("tbl.phas = %S", tbl.y); +#v- + producing: +#v+ + tbl.time = Double_Type[500] + tbl.x = Float_Type[500] + tbl.y = Float_Type[500] + tbl.z = Short_Type[500,3,3] +#v- + Note that the \exmp{fits_read_table} function not only read the data + in a way that preserved the data type, but it also correctly + identified the \exmp{phas} column as one containing a 3x3 image in + every row! + + Often one is interested in only a few columns of a table. Instead of + reading the entire table, which could use a lot of memory for a large + table, the \exmp{fits_read_table} function may also be used to read + just the specified columns, e.g., +#v+ + tbl = fits_read_table ("foo.fits[EXAMPLE]", "x", "y"); +#v- + will read just the \exmp{X} and \exmp{Y} columns. + + An alternative interface with much the same functionality is provided + by the \exmp{fits_read_col} function. Instead of returning the data + as a structure, it returns the data as multiple return values, e.g., +#v+ + t = fits_read_col ("foo.fits[EXAMPLE]", "time"); + (x,y) = fits_read_col ("foo.fits[EXAMPLE]", "x", "y"); +#v- + + The \sfun{fits_read_cell} function may be used to read a single cell + in the table. For example +#v+ + phas = fits_read_cell ("foo.fits[EXAMPLE]", "phas", 4); +#v- + will return the 3x3 array of the ``phas'' column in the fourth row. + Finally, the \exmp{fits_read_cells} function may be used to read a + specified range of rows in the table. For instance, +#v+ + (x,y) = fits_read_cells ("foo.fits[EXAMPLE]", "x", "y", 1, 1000); +#v- + will read the first 1000 rows of the \exmp{X} and \exmp{Y} columns in + the table. + +#%}}} + + \sect1{Writing Binary Tables} #%{{{ + + The high-level interface has several functions that are useful for + the creation of a binary table. Chief among them is the + \sfun{fits_write_binary_table} function, which supports several + methods of calling it. The simplest use was illustrated earlier. + Here more complicated uses will be considered. + + As a first step, suppose that the binary table is to contain data for + the Lissajous curve constructed as follows: +#v+ + A_x = 10.0; omega_x = 3.0; phi_x = 0.0; + A_y = 20.0; omega_y = 7.0; phi_y = 1.0; + t = [0:100:0.01]; + x = A_x * cos (omega_x*t + phi_x); + y = A_y * cos (omega_y*t + phi_y); +#v- + The goal is to write out arrays \exmp{t}, \exmp{x}, and \exmp{y} to a + binary table called LISSAJOUS, and with columns of the corresponding + names. The easiest way is to use: +#v+ + data = struct {t, x, y}; data.t = t; data.x = x; data.y = y; + fits_write_binary_table ("foo.fits", "LISSAJOUS", data); +#v- + Now suppose that it is desired to write the parameters defining the + Lissajous pattern as keywords and to write a history record to the + file. One way to do this is via the \exmp{fits_update_key}, + \sfun{fits_write_history}, and \sfun{fits_write_comment} functions: +#v+ + fp = fits_open_file ("foo.fits[LISSAJOUS]"); + fits_write_comment (fp, "This table contains data for a Lissajous pattern"); + fits_update_key (fp, "A_X", A_x, "x(t) Amplitude"); + fits_update_key (fp, "A_Y", A_y, "y(t) Amplitude"); + fits_update_key (fp, "OMEGA_X", omega_x, "x(t) omega"); + fits_update_key (fp, "OMEGA_Y", omega_y, "y(t) omega"); + fits_update_key (fp, "PHI_X", phi_x, "x(t) phase"); + fits_update_key (fp, "PHI_Y", phi_y, "y(t) phase"); + fits_write_history (fp, "This was written as an example for the " + + "documentation of the slang cfitsio module"); + fits_close_file (fp); +#v- + The advantage of using the \exmp{fits_update_key} is that it allows + control over the comment associated with the keyword; however, + repeated calls to \sfun{fits_update_key} can become tedious. + + A simpler mechanism to achieve this goal is to pass the keywords and + history information to the \sfun{fits_write_binary_table} function as + an optional arguments, +#v+ + keys = struct {A_x, omega_x, phi_x, A_y, omega_y, phi_y}; + set_struct_fields (keys, A_x, omega_x, phi_x, A_y, omega_y, phi_y); + hist = struct {history, comment}; + hist.comment = "This table contains data for a Lissajous pattern"; + hist.history = "This was written as an example for the " + + "documentation of the slang cfitsio module"; + fits_write_binary_table ("foo.fits", "LISSAJOUS", data, keys, hist); +#v- + to produce: +#v+ + XTENSION= 'BINTABLE' / binary table extension + BITPIX = 8 / 8-bit bytes + NAXIS = 2 / 2-dimensional binary table + NAXIS1 = 24 / width of table in bytes + NAXIS2 = 10000 / number of rows in table + PCOUNT = 0 / size of special data area + GCOUNT = 1 / one data group (required keyword) + TFIELDS = 3 / number of fields in each row + TTYPE1 = 't ' / label for field 1 + TFORM1 = 'D ' / data format of field: 8-byte DOUBLE + TTYPE2 = 'x ' / label for field 2 + TFORM2 = 'D ' / data format of field: 8-byte DOUBLE + TTYPE3 = 'y ' / label for field 3 + TFORM3 = 'D ' / data format of field: 8-byte DOUBLE + EXTNAME = 'LISSAJOUS' / name of this binary table extension + A_X = 10 + OMEGA_X = 3 + PHI_X = 0 + A_Y = 20 + OMEGA_Y = 7 + PHI_Y = 1 + COMMENT This table contains data for a Lissajous pattern + HISTORY This was written as an example for the documentation of the slang cfitsi + HISTORY o module +#v- + + It is important to note that in the the above examples, the name of + the file to contain the binary table was explicitly passed to the + \sfun{fits_write_binary_table} function. This causes + \sfun{fits_write_binary_table} to create a \em{new} file containing + the binary table, and if a file of that name exists, \em{it will be + deleted} before the new one is created. + + To append a table to an existing file, first open it using the + \sfun{fits_open_file} function, and then use the file pointer in + place of the name: +#v+ + fp = fits_open_file ("foo.fits", "w"); % <<-- note the "w" + . + . + fits_write_binary_table (fp, ....); + fits_close_file (fp); +#v- + This technique must also be used to create a file containing + multiple binary tables: +#v+ + fp = fits_open_file ("foo.fits", "c"); % <<-- note the "c" + . + . + fits_write_binary_table (fp, ....); % first table + . + . + fits_write_binary_table (fp, ....); % second table + fits_close_file (fp); +#v- + +#%}}} + +\sect{Images} + + \sect1{Preliminaries} #%{{{ + + Dealing with FITS images in \slang is easy as long as one understands + that FITS stores images in FORTRAN \em{column-major} order, whereas + \slang utilizes a C \em{row-major} order. That is, the first + dimension of a FITS array varies fastest whereas it is the last + dimension of a \slang array that varies fastest. This difference is + automatically accounted for by the underlying \module{cfitsio} + module. In other words, images may be used in \slang scope as + ordinary \slang arrays where the first dimension varies slowest, and + the \module{cfitsio} module will make the necessary translations when + reading or writing an image from a file. An easy way to remember the + \slang or C ordering is that for a 2-d array, the first index is a + row index and the second a column--- the same as matrices are indexed + in linear algebra. Do not fall into the trap of indexing a \slang array + the same as you would of indexing a point in Cartesian space (x,y), + instead think in terms of rows and columns. + + +#%}}} + + \sect1{Reading and Writing Images} #%{{{ + + The \sfun{fits_read_img} may be used to read the image from the + primary FITS HDU or a FITS image extension. It is not designed to + read images that are stored in binary tables--- there are other + functions for that purpose. The \sfun{fits_read_img} function + simply returns the data as an array of the appropriate type and + dimensions (in row-major order) with any scaling defined via the + BZERO and BSCALE header keywords applied. + + Writing an image HDU is somewhat more involved than reading one because + in addition to writing the image data, the header must first be set up to + describe the image. Fortunately, the high-level functions make this + easy. + + Suppose that one has created an image array via, e.g., the + \module{histogram} module's \ifun{hist2d} function from the X and Y + columns of a binary table: +#v+ + (x,y) = fits_read_col ("evt2.fits[EVENTS]", "X","Y"); + xgrid = 3840.5 + [0:1023:2]; + ygrid = 3840.5 + [0:1023:2]; + img = hist2d (y, x, ygrid, xgrid); +#v- + and that one wants to write this out to a fits file called + \file{img.fits}. The simplest way to do this is using + \sfun{fits_write_image_hdu}: +#v+ + fits_write_image_hdu ("img.fits", NULL, img); +#v- + + Note that the data-type of the image array controls the type of image + written to the fits file. If the image array is an array of + \exmp{Double_Type}s, then the image will be written with BITPIX set + to -64. To have such an array out as 16 bit integers, then the array + must first be scaled to the range of a 16 bit integer and then + typecast to \var{Int16_Type}: +#v+ + int16_image = typecast (img, Int16_Type); +#v- + + Additional keywords may be written to the image HDU using the + \sfun{fits_update_key} function. And like + \sfun{fits_write_binary_table}, the \sfun{fits_write_image_hdu} + function takes optional parameters that specify additional keywords, + history, and comments to be written. The reader is referred to the + discussion of the \sfun{fits_write_binary_table} function for more + information. + +#%}}} + +#% \sect{Copying Headers} + +\sect{WCS Routines} + + \sect1{Introduction} + + The FITS package includes a set of routines for reading and + writing \url{http://fits.gsfc.nasa.gov/fits_wcs.html}{WCS} keywords + in the form proposed by + \url{http://www.atnf.csiro.au/people/mcalabre/WCS/wcs.pdf}{Greisen + and Calabretta}. + Although they are part of the high-level interface, the routines are + somewhat experimental and as such must be loaded separately via: +#v+ + require ("fitswcs"); +#v- + + The routines in this interface deal with a structure that describes + the WCS via the following fields: +\begin{descrip} + \tag{naxis} + The number of axes to transform (Int_Type) + \tag{ctype} + Specifies the WCS transformation (String_Type[naxis]) + \tag{cunit} + Units (String_Type[naxis]) + \tag{crval} + WCS values at the reference pixel (Double_Type[naxis]) + \tag{crpix} + The coordinates of the reference pixel (Double_Type[naxis]) + \tag{cdelt} + Species the gradient at the reference pixel (Double_Type[naxis]) + \tag{pc} + An array used to linearly transform the WCS. + (Double_Type[naxis,naxis] or NULL) + \tag{pv} + An array of addition parameters used to specify the WCS (NULL in + most cases) + \tag{ps} + An array of additional string parameters (NULL in most cases). + \tag{wcsname} + A name given to this coordinate system. +\end{descrip} + + While the user is encouraged to understand the FITS WCS conventions + and the precise meanings of these fields, the \exmp{fitswcs} interface + provides routines to make the use of this structure as transparent + as possible for the most common uses. A few examples will + illustrate this. + + \sect1{Examples} + + Consider once again the example of creating a FITS image by binning + two columns of a FITS binary table: +#v+ + (x,y) = fits_read_col ("evt2.fits[EVENTS]", "X","Y"); + xgrid = 3840.5 + [0:1023:2]; + ygrid = 3840.5 + [0:1023:2]; + img = hist2d (y, x, ygrid, xgrid); + fits_write_image_hdu ("img.fits", NULL, img); +#v- + Unfortunately the resulting file will contain none of the WCS + information that was attached to the X and Y columns from which the + image was constructed. One might be tempted to simply copy that + information to the output file with the aid of the \exmp{fitswcs} + routines via +#v+ + wcs = fitswcs_get_column_wcs ("evt2.fits[EVENTS]", ["Y", "X"]); + fitswcs_put_img_wcs ("img.fits", wcs); +#v- + The problem with this approach is that the WCS read from the binary + table does not describe the image created from it because it knows + nothing about how the image was binned nor how the image pixel + coordinates relate back to the X and Y columns. That information is + contained in the definition of the grids passed to the \ifun{hist2d} + function: +#v+ + xgrid = 3840.5 + [0:1023:2]; + ygrid = 3840.5 + [0:1023:2]; +#v- + These grids describe a simple linear transformation from image pixel + coordinates to the (X,Y) coordinates of the binary table. Since the + transformation is linear, the \exmp{fitswcs_bin_wcs} function may be + used to transform the WCS: +#v+ + wcs = fitswcs_bin_wcs (wcs, ygrid, xgrid); +#v- + It is the transformed WCS that is to be written out: +#v+ + fitswcs_put_img_wcs ("img.fits", wcs); +#v- + + It is important to note the order in which the X and Y arguments + were used. Recall that FITS stores images in a FORTRAN column-major + order whereas \slang uses a row-major order. For this reason, + ``row-like'' parameters come before ``column-like'' parameters in + statements such as +#v+ + img = hist2d (y, x, ygrid, xgrid); + wcs = fitswcs_get_column_wcs ("evt2.fits[EVENTS]", ["Y", "X"]); + wcs = fitswcs_bin_wcs (wcs, ygrid, xgrid); +#v- + + \sect1{Alternate WCS} + + Sometimes it is useful to attach more than one coordinate system to + an image. For example, it is useful to have a coordinate system + that maps the pixel coordinates back to (X,Y) coordinates from which + they were derived. The \sfun{fitswcs_new_img_wcs} may be used to + construct a linear WCS corresponding to the linear coordinate grids + of the image: +#v+ + wcsP = fitswcs_new_img_wcs (ygrid, xgrid); + wcsP.wcsname = "PHYSICAL"; + fitswcs_put_img_wcs ("img.fits", wcsP, 'P'); +#v- + Note that the WCS was given the name ``PHYSICAL''. While not + required, this enables this alternate coordinate system to be + displayed as the physical system by the DS9 image display program. + + \sect1{Degenerate Axes} + + Consider a FITS file \exmp{hydra.fits} containing an + image HDU with the following FITS header: +#v+ + SIMPLE = T / file does conform to FITS standard + BITPIX = -32 / number of bits per data pixel + NAXIS = 4 / number of data axes + NAXIS1 = 657 / length of data axis + NAXIS2 = 657 / length of data axis + NAXIS3 = 1 / length of data axis + NAXIS4 = 1 / length of data axis + CTYPE1 = 'RA---SIN' + CRVAL1 = 139.5235701 + CRPIX1 = 330 + CDELT1 = -0.0004166666768 + CTYPE2 = 'DEC--SIN' + CRVAL2 = -12.0955450949 + CRPIX2 = 328 + CDELT2 = 0.0004166666768 + PC1_1 = 1 + PC1_2 =-1.7318465835227e-09 + PC2_1 = 1.7318465835227e-09 + PC2_2 = 1 + CTYPE3 = 'FREQ ' + CRVAL3 = 332902343.75 + CRPIX3 = 1 + CDELT3 = 2490234.5 + CTYPE4 = 'STOKES ' + CRVAL4 = 1 + CRPIX4 = 1 + CDELT4 = 1 +#v- + This particular image had so-called ``degenerate axes'' added, which + had the effect of increasing its dimensionality from 2 to 4. As such, + this image may be rejected by some image display programs that expect + a 2-d image. In fact, +#v+ + img = fits_read_img ("hydra.fits"); + wcs = fitswcs_get_img_wcs ("hydra.fits"); +#v- + will read the image as a \exmp{Float_Type[1,1,657,657]} object, and + the WCS as a 4-d with wcs.ctype equal to +#v+ + ["STOKES", "FREQ", "DEC--SIN", "RA---SIN"] +#v- + + The degenerate dimensions may be removed from the image via +#v+ + img = img[0,0,*,*]; +#v- + producing a 2d image of type \exmp{Float_Type[657,657]}. The + corresponding wcs may be obtained using the \sfun{fitswcs_slice} + function to extract the last two dimensions of the WCS: +#v+ + wcs = fitswcs_slice (wcs, [2,3]); +#v- + + Another use of the \sfun{fitswcs_slice} is to reorder the dimensions + of the WCS. For example, earlier it was pointed out that when + constructing an image from columns in a table, that one read the WCS + in a row-major order. If the reverse order was used when obtaining + the WCS from the columns of a binary table, e.g., +#v+ + wcs = fitswcs_get_column_wcs ("evt2.fits[EVENTS]", ["X", "Y"]); +#v- + then it would have been necessary to reverse the order of the + dimensions of the WCS structure. The \sfun{fitswcs_slice} may be + used to swap the dimensions of the WCS, e.g., +#v+ + wcs = fitswcs_slice (wcs, [1,0]); +#v- + +#%+ +(Recall that the FITS convention is to assign the pixel coordinate + (0.5,0.5) to the extreme corner of the first pixel, whereas many + systems, including \slang, use (0,0) for that position and regard + the center of the pixel as being at (0.5,0.5). +#%- + +#% \sect{Examples} + +\sect{High-level Function Reference} +#i fitsfuns.tm + +\sect{WCS Function Reference} +#i fitswcsfuns.tm + +\chapter{The low-level interface} + +\sect{Overview} #%{{{ + + Functions in the low-level module are usually needed when it is + necessary to perform some task that is not readily achievable using + the high-level interface. This module may be loaded using +#v+ + require ("cfitsio"); +#v- + When mixing functions from both interfaces, it is not necessary to + explicitly load the \module{cfitsio} module in this manner since it + is loaded automatically by the high-level interface. + + For the most part, for those functions that have been wrapped, the + \module{cfitsio} module represents a 1-1 mapping between the + functions of the cfitsio library and those of the module. For this + reason a detailed description of the functions in the + \module{cfitsio} module will not be given here; the reader is + referred to the documentation for the \CFITSIO library itself for the + details. Here only the semantic differences between the functions in + the module and those of the library, and how the functions are + documented. + + Most \CFITSIO functions adhere to a so-called ``inherited status'' + convention via a ``status'' argument as the last parameter. In + addition functions also return the error status as a return value. + For simplicity the wrapping by the module does not respect this + convention. That is, none of the module's functions take a status + argument. For example, the \CFITSIO documentation for the + \exmp{fits_get_num_hdus} specifies that it is to be called from C + via: +#v+ + status = fits_get_num_hdus (fptr, &hdunum, &status); +#v- + This function has been wrapped such that it is to be called from + \slang via +#v+ + status = _fits_get_num_hdus (fptr, &hdunum); +#v- + +#%}}} + +\sect{Low-level Function Reference} + + +#s+ +#i mkindex.sl +#s- +#d iflatex#2 <#if output=latex2e>$1<#unless output=latex2e>$2 +#d ifhtml#2 <#if output=html>$1<#unless output=html>$2 + +#d xreferences#1 This function is a wrapper around the cfitsio library \ + function \exmp{$1}. \ + See \ifhtml{\url{\cfitsio_fun_url{$1}}{its documentation}}{its documentation}\ + for additional information. + +#d cfitsioxref#1 \ifhtml{\url{\cfitsio_fun_url{$1}}{$1}}{\exmp{$1}} + +#i rtl/cfitsiofuns.tm + +\end{\documentstyle} diff --git a/modules/cfitsio/doc/tm/fitsfuns.tm b/modules/cfitsio/doc/tm/fitsfuns.tm new file mode 100644 index 0000000..fb86378 --- /dev/null +++ b/modules/cfitsio/doc/tm/fitsfuns.tm @@ -0,0 +1,575 @@ +#c __FILE__: ../../src/fits.sl +#c __LINE__: 43 +\function{fits_open_file} +\synopsis{Open a fits file} +\usage{Fits_File_Type fits_open_file (String_Type filename, String_Type mode)} +\description + The \var{fits_open_file} function can be used to open and existing fits + file for reading or updating, or to create a new fits file, depending upon + the value of the \var{mode} parameter. Specifically, if \var{mode} is + \exmp{"r"}, the file will be opened for reading. If \var{mode} is \exmp{"w"}, + the file will be opened for updating (both reading and writing). Otherwise, + \var{mode} must be \var{"c"}, which indicates that a new file is to be created. + In the latter case, if a file already exists with the specified name, it will + get deleted and a new one created in its place. + + If the function fails, it will signal an error; otherwise an open file + pointer will be returned. +\seealso{fits_close_file, fits_create_binary_table} +\done +#c __LINE__: 78 +\function{fits_close_file} +\synopsis{Close a fits file} +\usage{fits_close_file (Fits_File_Type f)} +\description + The \var{fits_close_file} closes a previously opened fits file. The function + will signal an error if the operation fails. +\notes + This function could fail if it fails to write out any buffered data because + of filesystem errors (disk full, etc.). +\seealso{fits_open_file} +\done +#c __LINE__: 178 +\function{fits_move_to_interesting_hdu} +\synopsis{Move to an extension that looks interesting} +\usage{fits_move_to_interesting_hdu (fp [, hdu_type]} +#v+ + Fits_File_Type fp; + Int_Type hdu_type; +#v- +\description + The function move the fits file pointer \var{fp} forward to an HDU that looks + interesting. By definition, an interesting HDU is one in which NAXIS is + non-zero. The first parameter \var{fp} must be a pointer to an already open + fits file. The second parameter, if present, may be used to specifiy the + type of HDU, e.g., either an image (\exmp{hdu_type=_FITS_IMAGE_HDU}) or a + binary table (\exmp{hdu_type=_FITS_BINARY_TBL}). + + If the function fails to find an interesting HDU of the appropriate type, + an exception will be generated. +\seealso{fits_open_file} +\done +#c __LINE__: 246 +\function{fits_key_exists} +\synopsis{Check for the existence of a keyword} +\usage{Int_Type fits_key_exists (fd, key)} +#v+ + Fits_File_Type or String_Type fd; + String_Type key; +#v- +\description + The \var{fits_key_exists} function checks for the existence of a specified + keyword in the file specified by the descriptor \var{fd}, which must specify + the name of a file or an open file pointer. + + If the specified key exists, the function return \1, otherwise it returns \0. +\seealso{fits_read_key, fits_read_header} +\done +#c __LINE__: 304 +\function{fits_get_colnum} +\synopsis{Get the column numbers of specified columns} +\usage{column_num = fits_get_colnum (fd, column_name)} +#v+ + Fits_File_Type or String_Type fd; + String_Type column_name; +#v- +\description + This function returns the column number of the column with the specified name. + The file-descriptor \exmp{fd} must specify the name of a file, or an open + fits file pointer. +\seealso{fits_binary_table_column_exists} +\done +#c __LINE__: 336 +\function{fits_binary_table_column_exists} +\synopsis{Check for the existence of a binary table column} +\usage{Int_Type fits_binary_table_column_exists (fd, col)} +#v+ + Fits_File_Type or String_Type fd; + String_Type col; +#v- +\description + This function may be used to determine whether or not a named column + exists in a binary table. The table is specified via the \var{fd} + parameter which must either be the name of a file containing the binary + table, or an file pointer. + + If the specified column exists, \1 will be returned; otherwise the function + will return \0. +\seealso{fits_key_exists, fits_open_file} +\done +#c __LINE__: 522 +\function{fits_read_col} +\synopsis{Read one or more columns from a FITS binary table} +\usage{(x1, ...xN) = fits_read_col (file, c1, ... cN)} +#v+ + Fits_File_Type or String_Type file; + Int_Type or String_Type c1, ...cN; +#v- +\description + This function returns one or more vectors containing objects in the + specified columns of the binary table indicated by \var{file}. If + \var{file} is a string, then the file will be opened via the virtual + file specification implied by \var{file}. Otherwise, \var{file} + should represent an already opened FITS file. The column parameters + may either be strings denoting the column names, or integers + representing the column numbers. +\seealso{fits_read_cell, fits_read_row, fits_read_table} +\done +#c __LINE__: 560 +\function{fits_read_col_struct} +\synopsis{Read one or more columns from a FITS binary table} +\usage{struct = fits_read_col_struct (file, col1, ...)} +#v+ + Fits_File_Type or String_Type file; + String_Type col1, ...; +#v- +\description + This function works exactly like \var{fits_read_col} except it returns the + values in a structure. See the documentation on that function for more + information. + +\seealso{fits_read_col, fits_read_key_struct, fits_read_row, fits_read_header} +\done +#c __LINE__: 588 +\function{fits_read_cell} +\synopsis{Read a cell from a FITS binary table} +\usage{X = fits_read_cell (file, c, r)} +#v+ + Fits_File_Type or String_Type file; + Int_Type r, c; +#v- +\description + This function returns the object in the column \var{c} and row + \var{r} of the binary table indicated by \var{file}. If \var{file} + is a string, then the file will be opened via the virtual file + specification implied by \var{file}. Otherwise, \var{file} should + represent an already opened FITS file. +\seealso{fits_read_col, fits_read_row} +\done +#c __LINE__: 644 +\function{fits_read_row} +\synopsis{Read a row from a FITS binary table} +\usage{Struct_Type fits_read_cell (file, r)} +#v+ + Fits_File_Type or String_Type file; + Int_Type r; +#v- +\description + This function returns a structure containing the data in the columns + of the row \var{r} of the binary table indicated by \var{file}. If + \var{file} is a string, then the file will be opened via the virtual + file specification implied by \var{file}. Otherwise, \var{file} + should represent an already opened FITS file. +\seealso{fits_read_col, fits_read_cell} +\done +#c __LINE__: 666 +\function{fits_read_header} +\synopsis{Read a FITS header} +\usage{Struct_Type fits_read_header (file)} +#v+ + Fits_File_Type or String_Type file; +#v- +\description + This function reads the header of the fits file given by the + \var{file} parameter and returns it as a structure. If \var{file} is + a string, then the file will be opened via the virtual file + specification implied by \var{file}. Otherwise, \var{file} should + represent an already opened FITS file. +\seealso{fits_read_table} +\done +#c __LINE__: 695 +\function{fits_read_table} +\synopsis{Read a FITS table} +\usage{Struct_Type fits_read_table (file [,columns...])} +#v+ + Fits_File_Type or String_Type file; +#v- +\description + \var{fits_read_table} reads the data in a table of the FITS file + specified by \var{file} and returns it as a structure. If the optional + column name parameters are specified, then only those columns will be read. + Otherwise, the entire table will be returned. + + If \var{file} is a string, then the file will be opened via the virtual file + specification implied by \var{file}. Otherwise, \var{file} should + represent an already opened FITS file. +\seealso{fits_read_col, fits_read_cell, fits_read_row, fits_read_header} +\done +#c __LINE__: 772 +\function{fits_read_key} +\synopsis{Read one or more keywords from a FITS file} +\usage{(val1,...) = fits_read_key (file, key1, ...)} +#v+ + Fits_File_Type or String_Type file; + String_Type key1, ...; +#v- +\description + \var{fits_read_key} reads the values of one or more keywords in the fits + file specified by \var{file} and returns them. If \var{file} + is a string, then the file will be opened via the virtual file + specification implied by \var{file}. Otherwise, \var{file} should + represent an already opened FITS file. If any of the keywords do not exist, + a value of \NULL will be returned for the corresponding keyword. +\seealso{fits_read_key_struct, fits_read_col, fits_read_cell, fits_read_row, fits_read_header} +\done +#c __LINE__: 818 +\function{fits_read_key_struct} +\synopsis{Read one or more keywords from a FITS file} +\usage{struct = fits_read_key (file, key1, ...)} +#v+ + Fits_File_Type or String_Type file; + String_Type key1, ...; +#v- +\description + This function works exactly like \var{fits_read_key} excepts returns the + values in a structure. See the documentation on that function for more + information. +\seealso{fits_read_key, fits_read_col, fits_read_cell, fits_read_row, fits_read_header} +\done +#c __LINE__: 859 +\function{fits_create_binary_table} +\synopsis{Prepare a binary table} +\usage{fits_create_binary_table (file, extname, nrows, ttype, tform, tunit)} +#v+ + Fits_File_Type or String_Type file; + String_Type extname; + Int_Type nrows; + String_Type ttype[]; + String_Type tform[]; + String_Type tunit[]; +#v- +\description + This creates a new binary table with the specified structure. The parameters + \var{ttype}, \var{tform}, and \var{tunit} are string arrays that specify + the column names, column data type, and column units, respectively. + The binary table will be given the extension name \var{extname}. +\seealso{fits_write_binary_table, fits_open_file} +\done +#c __LINE__: 894 +\function{fits_write_binary_table} +\synopsis{Write a binary table} +\usage{fits_write_binary_table (file, extname, sdata, [skeys [,hist]])} +#v+ + Fits_File_Type or String_Type file; + String_Type extname; + Struct_Type sdata; + Struct_Type skeys; + Struct_Type hist; +#v- +\description + The \var{fits_write_binary_table} function creates a new binary table in + the specified file. The parameter \var{file} specifies either a filename or + an open file pointer. The \var{extname} parameter specifies the extension + name of the binary table. The data written to table are specified in the + \var{sdata} structure, where the name of the structure field specifies the + column name. If \var{skeys} is non-NULL, then it is a structure indicating + additional keywords to be written to the header of the binary table. If the + optional parameter \var{hist} is present and non-NULL, then it is a structure + whose fields indicate either comment or history information to be written + to the header. +\example + The following code +#v+ + variable data = struct { x, cosx, sinx }; + data.x = [0:2*PI:0.01]; + data.cosx = cos(data.x); + data.sinx = sin(data.x); + + variable keys = struct { hduname, username}; + keys.hduname = "COSXSINX"; + keys.username = "John Doe"; + + variable hist = struct { history, comment}; + hist.history = ["This is a history record", "This is another"]; + hist.comment = ["This is a comment", "And this is another"]; + + fits_write_binary_table ("foo.fits", "COSXSINX", data, keys, hist); +#v- + produces a binary table with the header: +#v+ + XTENSION= 'BINTABLE' / binary table extension + BITPIX = 8 / 8-bit bytes + NAXIS = 2 / 2-dimensional binary table + NAXIS1 = 24 / width of table in bytes + NAXIS2 = 629 / number of rows in table + PCOUNT = 0 / size of special data area + GCOUNT = 1 / one data group (required keyword) + TFIELDS = 3 / number of fields in each row + TTYPE1 = 'x ' / label for field 1 + TFORM1 = 'D ' / data format of field: 8-byte DOUBLE + TTYPE2 = 'cosx ' / label for field 2 + TFORM2 = 'D ' / data format of field: 8-byte DOUBLE + TTYPE3 = 'sinx ' / label for field 3 + TFORM3 = 'D ' / data format of field: 8-byte DOUBLE + EXTNAME = 'COSXSINX' / name of this binary table extension + HDUNAME = 'COSXSINX' + USERNAME= 'John Doe' + HISTORY This is a history record + HISTORY This is another + COMMENT This is a comment + COMMENT And this is another +#v- +\notes + This function provides no mechanism to mix comments and keyword records. As + the example shows, this function places the comment and history records at + the end of the table. +\seealso{fits_create_binary_table, fits_open_file} +\done +#c __LINE__: 1188 +\function{fits_update_key} +\synopsis{Update the value of a keyword} +\usage{fits_update_key (fd, key, val [,comment])} +#v+ + String_Type or Fits_File_Type fd; + String_Type key; + Any type val; + String_Type comment; +#v- +\description + The \var{fits_update_key} function updates the value and comment fields + of an existing keyword with the specified name. If the keyword does not + exist, a new keyword will be appended to the end of the header. +\seealso{fits_update_logical, fits_read_key} +\done +#c __LINE__: 1219 +\function{fits_update_logical} +\synopsis{Update the value of a logical (boolean) keyword} +\usage{fits_update_logical (fd, key, val, comment)} +#v+ + String_Type or Fits_File_Type fd; + String_Type key; + Any type val; + String_Type comment; +#v- +\description + The \var{fits_update_logical} function updates the value and comment fields + of an existing keyword of the specified name with the specified boolean value. + If the keyword does not exist, a new keyword will be appended to the end of + the header. +\seealso{fits_update_key} +\done +#c __LINE__: 1244 +\function{fits_write_comment} +\synopsis{Write a comment to the header} +\usage{fits_write_comment (fd, comment)} +#v+ + Fits_File_Type or String_Type fd; + String_Type comment; +#v- +\description + As the name indicates, this function writes a comment record to the specified + fits file. The file-descriptor \exmp{fd} must either be the name of a fits + file or an open fits file pointer. +\seealso{fits_update_key, fits_write_history} +\done +#c __LINE__: 1266 +\function{fits_write_history} +\synopsis{Write a history record to the header} +\usage{fits_write_history (fd, history)} +#v+ + Fits_File_Type or String_Type fd; + String_Type history; +#v- +\description + As the name indicates, this function writes a history record to the specified + fits file. The file-descriptor \exmp{fd} must either be the name of a fits + file or an open fits file pointer. +\seealso{fits_update_key, fits_write_comment} +\done +#c __LINE__: 1288 +\function{fits_write_date} +\synopsis{Write the DATE keyword to the current HDU} +\usage{fits_write_date (fd)} +#v+ + Fits_File_Type or String_Type fd; +#v- +\description + The \sfun{fits_write_date} function calls \ifun{_fits_write_date} to write + the DATE to the header of the specified file descriptor, which must either + be the name of a fits file or an open fits file pointer. +\seealso{fits_update_key} +\done +#c __LINE__: 1308 +\function{fits_write_chksum} +\synopsis{Compute and write the DATASUM and CHECKSUM keywords} +\usage{fits_write_chksum (fd)} +#v+ + Fits_File_Type or String_Type fd; +#v- +\description + The \sfun{fits_write_chksum} function calls \ifun{_fits_write_comment} to + compute and write the DATASUM and CHECKSUM keywords to the + header of the specified file descriptor, which must either + be the name of a fits file or an open fits file pointer. +\seealso{fits_update_key, fits_verify_chksum} +\done +#c __LINE__: 1329 +\function{fits_verify_chksum} +\synopsis{Verify the checksums for the current HDU} +\usage{isok = fits_verify_chksum (fd [,dataok, hduok])} +#v+ + Fits_File_Type or String_Type fd; + Ref_Type dataok, hduok; +#v- +\description + The \sfun{fits_verify_chksum} function calls \ifun{_fits_verify_chksum} to + verify the header and data checksums of the current HDU. A non-zero return value + signifies that the checksums are ok, otherwise the function returns 0 to indicate + that the checksums are invalid. The individual checksums of the HDU or data + can be checked through the use of the optional parameters. +\seealso{fits_write_chksum} +\done +#c __LINE__: 1367 +\function{fits_read_records} +\synopsis{Read all the records in a fits header} +\usage{String_Type[] fits_read_records (Fits_File_Type or String_Type fp)} +\description + This function returns a list of all the header records associated with the + fits file descriptor as an array of strings. +\seealso{fits_write_records, fits_read_key} +\done +#c __LINE__: 1399 +\function{fits_write_records} +\synopsis{Write records to fits header} +\usage{fits_write_records (fd, records)} +#v+ + Fits_File_Type or String_Type fd; + Array_Type records; +#v- +\description + This function uses the \ifun{_fits_write_record} function to write a series + of records to the current HDU. +\seealso{fits_read_records} +\done +#c __LINE__: 1435 +\function{fits_get_keyclass} +\synopsis{Obtain the key classes for a set of cards} +\usage{Int_Type[] = fits_get_keyclass (Array_Type cards)} +\description + This function uses the \ifun{_fits_get_keyclass} function to obtain the + key-classes associated with one or more cards. The function returns an + integer-valued array of the same length as the \exmp{cards} array. +\example + Obtain set of header cards to those that are not associated with the cards + describing the structure of the HDU: +#v+ + variable cards = fits_read_records ("evt2.fits[EVENTS]"); + variable classes = fits_get_keyclass (cards); + cards = cards[where (classes != _FITS_TYP_STRUC_KEY)]; +#v- +\seealso{fits_read_records, fits_read_key} +\done +#c __LINE__: 1467 +\function{fits_get_bitpix} +\synopsis{Get the fits bitpix value for an array} +\usage{Int_Type fits_get_bitpix (array)} +\description + This function may be used to obtain the bitpix value for a specified image + array. The array must be an integer or floating point type, otherwise + and error will be generated. The bitpix value is returned. +\seealso{fits_write_image_hdu, fits_read_img} +\done +#c __LINE__: 1498 +\function{fits_read_img} +\synopsis{Read image data from a fits file} +\usage{Array_Type fits_read_img (fd)} +#v+ + Fits_File_Type or String_Type fd; +#v- +\description + This function reads an image from the specified file descriptor. + The file descriptor must be either the name of an existing file, or an + open file pointer. It returns the image upon sucess, or signals an error + upon failure. +\seealso{fits_read_table, fits_read_col, fits_open_file, fits_write_img} +\done +#c __LINE__: 1529 +\function{fits_create_image_hdu} +\synopsis{Create a primary array or image extension} +\usage{fits_create_image_hdu (fd, extname, type, dims)} +#v+ + Fits_File_Type or String_Type fd; + String_Type extname; + Array_Type dims; + DataType_Type type; +#v- +\description + This function make use of the \ifun{_fits_create_img} function to create an + image extension or primary array of the specified type and size. If the + \exmp{extname} parameter is non-NULL, then an EXTNAME keyword will be + written out with the value of the extname parameter. + The \exmp{dims} parameter must be a 1-d integer array that corresponds + to the dimensions of the array to be written. + + If \exmp{fd} is specified as a string, then a new file of that name will be + created. If a file by that name already exists, it will be deleted and + a new one created. If this behavior is undesired, then explicitly open the + file and pass this routine the resulting file pointer. +\seealso{fits_write_image_hdu} +\done +#c __LINE__: 1572 +\function{fits_write_image_hdu} +\synopsis{Write an image extension} +\usage{fits_write_image_hdu (file, extname, image [,skeys [,hist]])} +#v+ + Fits_File_Type or String_Type file; + String_Type extname; + Any_Type image + Struct_Type skeys; + Struct_Type hist; +#v- +\description + The \var{fits_write_image_hdu} function creates a new image extension in + the specified file. The parameter \var{file} specifies either a filename or + an open file pointer. The \var{extname} parameter specifies the extension + name of the image, or NULL for the primary image. The image data written + to the file are specified by the \var{image} parameter. + If the optional parameter \var{skeys} is non-NULL, then it is a + structure indicating additional keywords to be written to the HDU. + If the optional parameter \var{hist} is present and non-NULL, + then it is a structure whose fields indicate either comment or history + information to be written to the header. +\example + The following code +#v+ + variable img = [1:128*128]; reshape (img, [128,128]); + variable keys = struct { hduname, username}; + keys.hduname = "MY_IMAGE"; + keys.username = "John Doe"; + variable hist = struct { history, comment}; + hist.history = ["This is a history record", "This is another"]; + hist.comment = ["This is a comment", "And this is another"]; + fits_write_image_hdu ("foo.fits", NULL, img, keys, hist); +#v- + produces an image HDU with the header: +#v+ + SIMPLE = T / file does conform to FITS standard + BITPIX = 32 / number of bits per data pixel + NAXIS = 2 / number of data axes + NAXIS1 = 128 / length of data axis 1 + NAXIS2 = 128 / length of data axis 2 + EXTEND = T / FITS dataset may contain extensions + COMMENT FITS (Flexible Image Transport System) format is defined in 'Astronomy + COMMENT and Astrophysics', volume 376, page 359; bibcode: 2001A&A...376..359H + HDUNAME = 'MY_IMAGE' + USERNAME= 'John Doe' + HISTORY This is a history record + HISTORY This is another + COMMENT This is a comment + COMMENT And this is another +#v- +\notes + This function provides no mechanism to mix comments and keyword records. As + the example shows, this function places the comment and history records at + the end of the table. +\seealso{fits_create_binary_table, fits_open_file} +\done +#c __LINE__: 1708 +\function{fits_write_img} +\synopsis{Write the image data to an Image HDU} +\usage{fits_write_img (Fits_File_Type fptr, Any_Type data)} +\description + This function writes the image data out to current HDU, assumed to be + an Image HDU. +\seealso{fits_write_image_hdu, fits_create_image_hdu} +\done diff --git a/modules/cfitsio/doc/tm/fitswcsfuns.tm b/modules/cfitsio/doc/tm/fitswcsfuns.tm new file mode 100644 index 0000000..708ac41 --- /dev/null +++ b/modules/cfitsio/doc/tm/fitswcsfuns.tm @@ -0,0 +1,163 @@ +#c __FILE__: ../../src/fitswcs.sl +#c __LINE__: 96 +\function{fitswcs_new} +\synopsis{Create a new-ndimensional linear WCS} +\usage{wcs = fitswcs_new (Int_Type naxis)} +\description + This function returns a new WCS structure of the specified dimensionality + that represents an identity (linear) transformation. +\seealso{fitswcs_get_img_wcs, fitswcs_get_column_wcs, fitswcs_get_vector_wcs} +\done +#c __LINE__: 121 +\function{fitswcs_slice} +\synopsis{Form a new wcs from one or more axes of another} +\usage{new_wcs = fitswcs_slice (wcs, dims)} +\description + This function may be used to construct a new wcs from another by rearranging + its axes or by using a subset of them. The \exmp{dims} argument specifies + the dimensions to use. +\example + Suppose that \exmp{wcs} represents a 4 dimensional WCS. Then +#v+ + wcs2 = fitswcs_slice (wcs, [0,1]); +#v- + will result in a 2 dimensional WCS from the first 2 axis of the input WCS. + Similarly, +#v+ + wcs2 = fitswcs_slice (wcs, [1,0]); +#v- + will produce a 2d WCS with the first two axes swapped. +\seealso{fitswcs_get_img_wcs, fitswcs_get_column_wcs, fitswcs_get_vector_wcs} +\done +#c __LINE__: 312 +\function{fitswcs_get_img_wcs} +\synopsis{Read a WCS for a FITS image} +\usage{wcs = fitswcs_get_img_wcs (fp [,alt])} +\description + The \sfun{fitswcs_get_img_wcs} returns a structure representing a WCS from + the specified file descriptor \exmp{fp} corresponding to an image HDU. + An optional parameter may be used to specified an alternate WCS. +\example +#v+ + wcs = fitswcs_get_img_wcs ("img.fits[IMAGE]", 'P'); +#v- +\seealso{fitswcs_put_img_wcs, fitswcs_get_column_wcs, fitswcs_get_vector_wcs} +\done +#c __LINE__: 371 +\function{fitswcs_get_column_wcs} +\synopsis{Get the WCS attached to one or more columns of a binary table} +\usage{fitswcs_get_column_wcs (fp, columns-array [,alt]} +\description + This function may be used to obtain the WCS associated with one or more + columns of a binary table. The file descriptor \exmp{fp} must specify + a binary table. The \exmp{columns-array} parameter should be an array + of columns names. The third parameter is optional and is used to specify + an alternate WCS. +\example +#v+ + wcs = fitswcs_get_column_wcs ("evt1.fits[EVENTS]", ["X","Y"]); +#v- +\seealso{fitswcs_put_column_wcs, fitswcs_get_img_wcs, fitswcs_get_vector_wcs} +\done +#c __LINE__: 480 +\function{fitswcs_get_vector_wcs} +\synopsis{Get the WCS of an image in a specified table cell} +\usage{wcs = fitswcs_get_vector_wcs (fp, column_name, row [,alt])} +\description + This function reads the WCS of an image in a specified cell of a binary + table given by \exmp{fp} parameter. The second and third parameters specify + the column name and row number of the cell. An optional fourth parameter + may be used to obtain the corresponding alternate WCS. +\example + This example reads the WCS associated with the image in the second row + of the QEU column of the binary table with HDUNAME equal to AXAF_QEU1 + in the file "HRCQEU.fits": +#v+ + wcs = fitswcs_get_vector_wcs ("HRCQEU.fits[AXAF_QEU1], "QEU", 2); +#v- +\notes + The current implementation does not yet support references to the WCS + of other cells. +\seealso{fitswcs_get_column_wcs, fitswcs_get_img_wcs} +\done +#c __LINE__: 577 +\function{fitswcs_new_img_wcs} +\synopsis{Create a linear WCS for an image} +\usage{wcs = fitswcs_new_img_wcs (grid0,grid1,...)} +\description + This function may be used to construct a linear WCS for an image with the + specified grids. The grids are assumed to be linear. +\example + Use the histogram module's hist2d function to create an image from the X + and Y columns in a file, and the construct a corresponding WCS: +#v+ + (x,y) = fits_read_col ("table.fits", "X", "Y"); + gridx = [min(x):max(x):0.5]; + gridy = [min(y):max(y):0.5]; + img = hist2d (y,x,gridy,gridx); + wcs = fitswcs_new_img_wcs (gridy, gridx); +#v- +\seealso{fitswcs_new, fitswcs_get_img_wcs} +\done +#c __LINE__: 628 +\function{fitswcs_put_img_wcs} +\synopsis{Write a WCS out to an image header} +\usage{fitswcs_put_img_wcs (fp, wcs [,alt])} +\description + The \sfun{fitswcs_put_img_wcs} may be used to write the specified wcs + out to the image HDU specified by the \exmp{fp} parameter. An optional + third parameter may be used to specify an alternate WCS. +\example +#v+ + fp = fits_open_file ("img.fits", "w"); + . + . + . + fits_put_img_wcs (fp, wcs, 'P'); + fits_close_file (fp); +#v- +\seealso{fitswcs_put_column_wcs} +\done +#c __LINE__: 705 +\function{fitswcs_put_column_wcs} +\synopsis{Write the WCS attached to one or more table columns} +\usage{fitswcs_put_column_wcs (fp, wcs, columns-array [,alt])} +\description + This function may be used to attach a WCS to one or more columns of a binary + table. The dimensionality of the specified WCS must match the length of the + array specifying the column names. The first parameter, \exmp{fp} must specify + a binary table extension. The fourth parameter is optional and may be used + to specify an alternate WCS. +\example +#v+ + fitswcs_put_column_wcs ("evt2.fits[EVENTS], wcs, ["X","Y"]); +#v- +\seealso{fitswcs_get_column_wcs, fitswcs_put_img_wcs, fitswcs_get_img_wcs} +\done +#c __LINE__: 818 +\function{fitswcs_linear_transform_wcs} +\synopsis{Apply a linear transformation to a WCS} +\usage{wcs1 = fitswcs_linear_transform_wcs (wcs, X0, CD, I0)} +#v+ + wcs: The specified WCS to transform + X0,I0: 1-d arrays + CD: 2-d array +#v- +\description + This function may be used to create a new WCS by applying a linear + transformation to an existing one. +\notes + The dimensionality of the WCS is limited to 2 in the + current implementation. +\seealso{fitswcs_rebin_wcs} +\done +#c __LINE__: 907 +\function{fitswcs_rebin_wcs} +\synopsis{This function may be used to obtain the wcs for a rebinned image} +\usage{wcs1 = fitswcs_rebin_wcs (wcs, grid0, grid1, ...)} +\description + This function may be used to construct the WCS for a rebinned image from + the WCS of of the unbinned image. The grid parameters specify the linear + grids the new image. +\seealso{fitswcs_linear_transform_wcs, fitswcs_slice} +\done diff --git a/modules/cfitsio/doc/tm/fixtex.sl b/modules/cfitsio/doc/tm/fixtex.sl new file mode 100644 index 0000000..4ad4142 --- /dev/null +++ b/modules/cfitsio/doc/tm/fixtex.sl @@ -0,0 +1,131 @@ +#!/usr/bin/env jed-script + +% Version 0.3.2-0 + +if (__argc != 2) +{ + message ("Usage: ./fixtex.sl "); + quit_jed (); +} + +variable file = __argv[1]; +() = read_file (file); + +% Patch up the >,< signs +bob (); +replace ("$<$", "<"); +replace ("$>$", ">"); + +% It appears that sgml2tex screws up _for in section titles, producing \_{for}. +replace ("ion\\_{", "ion{\\_"); + +% Make the first chapter a preface +bob (); +if (bol_fsearch ("\\chapter{Preface}")) +{ + push_spot (); + push_mark (); + go_right (8); insert ("*"); % \chapter{ --> \chapter*{ + () = bol_fsearch ("\\chapter{"); + push_spot (); + + insert("\\tableofcontents\n"); + eol (); + insert ("\n\\pagenumbering{arabic}"); + + pop_spot (); + narrow (); + bob (); + replace ("\\section{", "\\section*{"); + widen (); + + if (bol_bsearch ("\\tableofcontents")) + delete_line (); + + pop_spot (); + if (bol_bsearch ("\\maketitle")) + insert ("\\pagenumbering{roman}\n"); + +} + +static define fixup_urldefs () +{ + % pdflatex cannot grok urldef + bob (); + while (bol_fsearch("\\urldef{") and ffind ("\\url{")) + { + variable line = line_as_string (); + bol (); + insert ("\\ifpdf\n"); + + deln (7); insert ("\\newcommand"); + push_mark (); + ()=ffind ("}"); + variable macro = bufsubstr (); + () = ffind ("\\url"); + go_left (1); + trim (); + insert("{"); + + % pdflatex cannot grok # in urls. Nuke em. + if (ffind ("#")) + { + del_eol (); + insert ("}"); + } + eol (); + insert ("}\n\\else\n"); + insert (line); newline (); + insert ("\\fi\n"); + } +} + +static define remove_repeated_urls () +{ + variable name, url; + variable names = Assoc_Type[Int_Type, 0]; + while (bol_fsearch ("{\\em ")) + { + go_right (4); + skip_white (); + push_mark (); + () = ffind ("}"); + !if (looking_at ("} {\\tt ")) + { + pop_mark(0); + continue; + } + name = bufsubstr (); + if (names[name]) + { + go_right(1); + push_mark (); + () = ffind ("}"); + go_right(1); + del_region (); + } + else + { + names[name] = 1; + go_right(1); + () = ffind ("}"); + go_right (1); + } + + % Now remove empty lines inserted by the broken sgml2latex program. + skip_white (); + !if (eolp ()) + continue; + go_right(1); + skip_white (); + if (eolp ()) + del (); + } +} + +fixup_urldefs (); +remove_repeated_urls (); +save_buffer (); +quit_jed (); + + diff --git a/modules/cfitsio/doc/tm/helpfile.tm b/modules/cfitsio/doc/tm/helpfile.tm new file mode 100644 index 0000000..ee58683 --- /dev/null +++ b/modules/cfitsio/doc/tm/helpfile.tm @@ -0,0 +1,9 @@ +#i slhlp.tm + +#d xreferences#1 \ +This function is a wrapper around the CFITSIO function \exmp{$1}.\__newline__\ + See its documentation for additional information. +#d cfitsioxref#1 $1 +#i rtl/cfitsiofuns.tm +#i fitsfuns.tm +#i fitswcsfuns.tm diff --git a/modules/cfitsio/doc/tm/mkindex.sl b/modules/cfitsio/doc/tm/mkindex.sl new file mode 100644 index 0000000..463f61a --- /dev/null +++ b/modules/cfitsio/doc/tm/mkindex.sl @@ -0,0 +1,69 @@ +% The code here constructs an index for the low-level routines. It uses +% the index page at listed off +% http://heasarc.gsfc.nasa.gov/docs/software/fitsio/c/c_user/cfitsio.html +% Each function is indexed using: +% fits_clear_errmark +% [*] +% + +static variable Index_Page = "node119.html"; +static variable CFitsio_Root_URL + = "http://heasarc.gsfc.nasa.gov/docs/software/fitsio/c/c_user"; + +static variable Wget_Cmd + = "wget --quiet"; + +static define retrieve_url (url, outfile) +{ + vmessage ("Obtaining the cfitsio index from heasarc..."); + () = system (sprintf ("%s -O '%s' '%s'", Wget_Cmd, outfile, url)); +} + +static define mkindex () +{ + variable cbuf = whatbuf (); + variable index_url = strcat (CFitsio_Root_URL, "/", Index_Page); + variable tmpfile = sprintf ("/tmp/cfitsio_index_%d_%d", getpid(),_time()); + retrieve_url (index_url, tmpfile); + () = read_file (tmpfile); + () = remove (tmpfile); + + variable index = Assoc_Type[String_Type]; + + bob (); + while (bol_fsearch ("fits_")) + { + () = ffind ("fits_"); + push_mark (); + () = ffind (""); + variable fun = bufsubstr (); + go_down(1); + if (0 == ffind ("35] out.fit (copy rows with pi>35)"); + message("fitscopy in.fit[events][bin X,Y] out.fit (bin an image) "); + message("fitscopy in.fit[events][col x=.9*y] out.fit (new x column)"); + message("fitscopy in.fit[events][gtifilter()] out.fit (time filter)"); + message("fitscopy in.fit[2][regfilter(\"pow.reg\")] out.fit (spatial filter)"); + message(""); + message("Note that it may be necessary to enclose the input file name"); + message("in single quote characters on the Unix command line."); +} + +define slsh_main () +{ + if (__argc != 3) + { + usage (); + exit (1); + } + + variable fpin = fits_open_file (__argv[1], "r"); + variable fpout = fits_open_file (__argv[2], "c"); + variable status = _fits_copy_file(fpin, fpout, 1, 1, 1); + if (status) + verror ("%s", _fits_get_errstatus (status)); + + fits_close_file(fpout); +} diff --git a/modules/cfitsio/examples/mkimgcont b/modules/cfitsio/examples/mkimgcont new file mode 100755 index 0000000..1607eba --- /dev/null +++ b/modules/cfitsio/examples/mkimgcont @@ -0,0 +1,28 @@ +#!/usr/bin/env slsh +require ("fits"); +import ("pgplot"); + +static define read_and_display_image (file) +{ + variable img = fits_read_image (file); + variable dims; (dims,,) = array_info (img); + variable nx = dims[1], ny = dims[0]; + variable z0 = min(img), z1 = max(img); + + variable z = [z0:z1:(z1-z0)/10.0]; + + _pgopen("/xwin"); + _pgenv(0,nx-1,0,ny-1,0,0); + _pgpap (0, 1); + _pgcont(img,0,ny-1,0,nx-1, z, [0,1,0,0,0,1], 1); + _pgend(); +} + +if (__argc != 2) +{ + () = fprintf (stderr, "Usage: %s fits-image-file\n", __argv[0]); + exit (1); +} +read_and_display_image (__argv[1]); +exit(0); + diff --git a/modules/cfitsio/examples/viewimage b/modules/cfitsio/examples/viewimage new file mode 100755 index 0000000..69878ce --- /dev/null +++ b/modules/cfitsio/examples/viewimage @@ -0,0 +1,32 @@ +#!/usr/bin/env slsh +%_traceback = 0; +require ("fits"); +require ("stats"); +import ("pgplot"); +static define read_and_display_image (file) +{ + variable img = fits_read_image (file); + + variable dims; (dims,,) = array_info (img); + variable nx = dims[1], ny = dims[0]; + + variable mean_img = mean (img); + variable stddev_img = stddev (img); + variable g0 = mean_img - 3*stddev_img; + variable g1 = mean_img + 3*stddev_img; + + _pgopen("/xwin"); + _pgenv(0,nx,0,ny,0,0); + _pgpap (0, 1); + _pgimag(img,0,ny-1,0,nx-1, g0, g1, [0,1,0,0,0,1]); + _pgend(); +} + +if (__argc != 2) +{ + () = fprintf (stderr, "Usage: %s fits-image-file\n", __argv[0]); + exit (1); +} +read_and_display_image (__argv[1]); +exit(0); + diff --git a/modules/cfitsio/share/readrmf.sl b/modules/cfitsio/share/readrmf.sl new file mode 100644 index 0000000..d77b487 --- /dev/null +++ b/modules/cfitsio/share/readrmf.sl @@ -0,0 +1,99 @@ +require ("histogram"); +require ("fits"); +static define convert_to_array_type (a) +{ + if (_typeof (a) == Array_Type) + return; + + variable dims, ndims, type; + (dims, ndims, type) = array_info (a); + variable nrows = dims[0]; + variable aa = Array_Type[nrows]; + _for (0, nrows-1, 1) + { + variable i = (); + aa[i] = a[i, *]; + } + return aa; +} + + +public define fits_read_rmf (file) +{ + variable rmf = struct + { + energ_lo, energ_hi, n_grp, f_chan, n_chan, matrix, + e_min, e_max, channel + }; + + variable t = fits_read_table (file + "[MATRIX]"); + rmf.energ_lo = t.energ_lo; + rmf.energ_hi = t.energ_hi; + rmf.n_grp = t.n_grp; + + variable f_chan = t.f_chan; + variable n_chan = t.n_chan; + variable matrix = t.matrix; + variable nrows = length (rmf.energ_lo); + + f_chan = convert_to_array_type (f_chan); + n_chan = convert_to_array_type (n_chan); + + _for (0, nrows-1, 1) + { + variable i = (); + variable a; + a = f_chan[i]; + reshape (a, [length (a)]); + a = n_chan[i]; + reshape (a, [length (a)]); + a = matrix[i]; + reshape (a, [length (a)]); + } + rmf.f_chan = f_chan; + rmf.n_chan = n_chan; + rmf.matrix = matrix; + + (rmf.e_min, rmf.e_max, rmf.channel) = fits_read_col (file+"[EBOUNDS]", "e_min","e_max","channel"); + rmf.channel = int (rmf.channel + 0.5); + return rmf; +} + +public define eval_rmf_E(rmf, e) +{ + variable channels = rmf.channel; + variable num_channels = max (channels); + variable num_energies = length (e); + variable i_list = hist_bsearch (e, rmf.energ_lo); + + variable matrix = rmf.matrix; + variable r = @Array_Type(_typeof(matrix[0]), [num_energies, num_channels]); + + variable min_chan = min (channels); + _for (0, num_energies-1, 1) + { + variable ii = (); + variable i = i_list[ii]; + variable n_chan = rmf.n_chan[i]; + variable f_chan = rmf.f_chan[i]; + variable matrix_i = matrix[i]; + + variable matrix_start = 0; + _for (0, rmf.n_grp[i]-1, 1) + { + variable j = (); + variable n = n_chan[j]; + variable start_chan = f_chan[j]; + variable stop_chan = start_chan + (n-1); + variable chans = [start_chan:stop_chan]; + variable matrix_stop = matrix_start + (n-1); + r[ii,chans] = matrix_i[[matrix_start:matrix_stop]]; + matrix_start = matrix_stop+1; + } + } + + if (typeof(e) != Array_Type) + reshape (r, [num_channels]); + + return r; +} diff --git a/modules/cfitsio/src/Makefile.in b/modules/cfitsio/src/Makefile.in new file mode 100644 index 0000000..9b341ff --- /dev/null +++ b/modules/cfitsio/src/Makefile.in @@ -0,0 +1,121 @@ +# -*- sh -*- + +#--------------------------------------------------------------------------- +# List of modules and associated .sl files to install +#--------------------------------------------------------------------------- +MODULES = cfitsio-module.so +SL_FILES = cfitsio.sl fits.sl fitswcs.sl +HLP_FILES = ../doc/help/cfitsio.hlp +MODULE_VERSION = `./mkversion.sh` + +#--------------------------------------------------------------------------- +# Installation Directories +#--------------------------------------------------------------------------- +prefix = @prefix@ +exec_prefix = @exec_prefix@ +MODULE_INSTALL_DIR = @MODULE_INSTALL_DIR@ +SL_FILES_INSTALL_DIR = @SL_FILES_INSTALL_DIR@ +HLP_FILES_INSTALL_DIR = $(SL_FILES_INSTALL_DIR)/help + +#--------------------------------------------------------------------------- +# C Compiler to create a shared library +#--------------------------------------------------------------------------- +CC_SHARED = @CC_SHARED@ + +#--------------------------------------------------------------------------- +# Location of the S-Lang library and its include file +#--------------------------------------------------------------------------- +SLANG_INC = @SLANG_INC@ +SLANG_LIB = @SLANG_LIB@ -lslang + +#--------------------------------------------------------------------------- +# Additional Libraries required by the module +#--------------------------------------------------------------------------- +CFITSIO_INC = @CFITSIO_INC@ +CFITSIO_LIB = @CFITSIO_LIB@ -lcfitsio +OTHER_LIBS = @X_EXTRA_LIBS@ +MODULE_LIBS = $(CFITSIO_LIB) $(OTHER_LIBS) +RPATH = @RPATH@ + +#--------------------------------------------------------------------------- +# Misc Programs required for installation +#--------------------------------------------------------------------------- +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +MKINSDIR = ../autoconf/mkinsdir.sh +RM = rm -f +LN = ln -s +#--------------------------------------------------------------------------- +# DESTDIR is designed to facilitate making packages. Normally it is empty +#--------------------------------------------------------------------------- +DESTDIR = +DEST_MODULE_INSTALL_DIR = $(DESTDIR)$(MODULE_INSTALL_DIR) +DEST_SL_FILES_INSTALL_DIR = $(DESTDIR)$(SL_FILES_INSTALL_DIR) +DEST_HLP_FILES_INSTALL_DIR = $(DESTDIR)$(HLP_FILES_INSTALL_DIR) +#--------------------------------------------------------------------------- +LIBS = $(SLANG_LIB) $(MODULE_LIBS) $(RPATH) $(DL_LIB) -lm +INCS = $(SLANG_INC) $(CFITSIO_INC) + +all: $(MODULES) + +#--------------------------------------------------------------------------- +# Put Rules to create the modules here +#--------------------------------------------------------------------------- +cfitsio-module.so: cfitsio-module.c version.h + $(CC_SHARED) $(INCS) cfitsio-module.c -o cfitsio-module.so $(LIBS) +#--------------------------------------------------------------------------- +# Regression tests +#--------------------------------------------------------------------------- +test: + @for X in tests/test_*.sl; \ + do \ + slsh $$X; \ + done +#--------------------------------------------------------------------------- +# Installation Rules +#--------------------------------------------------------------------------- +install_directories: + $(MKINSDIR) $(DEST_MODULE_INSTALL_DIR) + $(MKINSDIR) $(DEST_SL_FILES_INSTALL_DIR) + $(MKINSDIR) $(DEST_HLP_FILES_INSTALL_DIR) + +install_modules: + @for X in $(MODULES); \ + do \ + Y=$$X.$(MODULE_VERSION); \ + YDEST=$(DEST_MODULE_INSTALL_DIR)/$$Y; \ + echo $(INSTALL_DATA) $$X $$YDEST; \ + $(INSTALL_DATA) $$X $$YDEST; \ + if [ "$$?" != "0" ]; then \ + exit 1; \ + fi; \ + $(RM) $(DEST_MODULE_INSTALL_DIR)/$$X; \ + $(LN) $$Y $(DEST_MODULE_INSTALL_DIR)/$$X; \ + done + +install_slfiles: + @for X in $(SL_FILES); \ + do \ + echo $(INSTALL_DATA) $$X $(DEST_SL_FILES_INSTALL_DIR); \ + $(INSTALL_DATA) $$X $(DEST_SL_FILES_INSTALL_DIR); \ + if [ "$$?" != "0" ]; then \ + exit 1; \ + fi; \ + done + +install_hlpfiles: + @for X in $(HLP_FILES); \ + do \ + echo $(INSTALL_DATA) $$X $(DEST_HLP_FILES_INSTALL_DIR); \ + $(INSTALL_DATA) $$X $(DEST_HLP_FILES_INSTALL_DIR); \ + if [ "$$?" != "0" ]; then \ + exit 1; \ + fi; \ + done + +install: all install_directories install_modules install_slfiles install_hlpfiles + +clean: + -/bin/rm -f $(MODULES) *~ \#* +distclean: clean + -/bin/rm -f config.h Makefile $(MODULES) *.fit diff --git a/modules/cfitsio/src/cfitsio-module.c b/modules/cfitsio/src/cfitsio-module.c new file mode 100644 index 0000000..2f49256 --- /dev/null +++ b/modules/cfitsio/src/cfitsio-module.c @@ -0,0 +1,2590 @@ +/* cfitsio interface */ +#include "config.h" +#include +#include +#include +#include + +#include + +#include + +#ifdef __cplusplus +extern "C" +{ +#endif +SLANG_MODULE(cfitsio); +#ifdef __cplusplus +} +#endif + +#include "version.h" + +/* This is a hack that works for all 32 and 64 bit systems that I know */ +/* The CFITSIO_INT*_TYPE objects must refer to the corresponding C type + * and have the approriate length. + */ +#if SIZEOF_SHORT == 2 +# define SLANG_UINT16_TYPE SLANG_USHORT_TYPE +# define SLANG_INT16_TYPE SLANG_SHORT_TYPE +# define CFITSIO_INT16_TYPE TSHORT +# define CFITSIO_UINT16_TYPE TUSHORT +typedef short int16_type; +#endif + +#if SIZEOF_INT == 4 +# define SLANG_INT32_TYPE SLANG_INT_TYPE +# define SLANG_UINT32_TYPE SLANG_UINT_TYPE +# define CFITSIO_INT32_TYPE TINT +# define CFITSIO_UINT32_TYPE TUINT +typedef int int32_type; +#endif + +#ifdef TLONGLONG +# if (SIZEOF_LONG == 8) +# define SLANG_INT64_TYPE SLANG_LONG_TYPE +# define CFITSIO_INT64_TYPE TLONG +# else +# define SLANG_INT64_TYPE SLANG_LLONG_TYPE +# define CFITSIO_INT64_TYPE TLONGLONG +# endif +#endif + +typedef struct +{ + fitsfile *fptr; +} +FitsFile_Type; + +static SLtype Fits_Type_Id = 0; + +static int map_fitsio_type_to_slang (int *typep, long *repeat, SLtype *stype) +{ + int type = *typep; + int sgn = (type < 0) ? -1 : 1; + + /* Variable length objects have negative type values */ + if (sgn == -1) + type = -type; + + switch (type) + { + case TSHORT: /* cfitsio 16 bit type */ + *stype = SLANG_INT16_TYPE; + *typep = sgn * CFITSIO_INT16_TYPE; + break; + + case TUSHORT: /* cfitsio 16 bit type */ + *stype = SLANG_UINT16_TYPE; + *typep = sgn * CFITSIO_UINT16_TYPE; + break; + + case TINT: + *stype = SLANG_INT_TYPE; + break; + +#ifdef TUINT + case TUINT: + *stype = SLANG_UINT_TYPE; + break; +#endif + + case TLONG: /* cfitsio 32 bit value */ + *stype = SLANG_INT32_TYPE; + *typep = sgn * CFITSIO_INT32_TYPE; + break; + + case TULONG: + *stype = SLANG_UINT32_TYPE; + *typep = sgn * CFITSIO_UINT32_TYPE; + break; + +#ifdef TLONGLONG + case TLONGLONG: + *stype = SLANG_INT64_TYPE; + break; +#endif + case TDOUBLE: + *stype = SLANG_DOUBLE_TYPE; + break; + + case TFLOAT: + *stype = SLANG_FLOAT_TYPE; + break; + + case TLOGICAL: + case TBYTE: + *stype = SLANG_UCHAR_TYPE; + break; + case TBIT: + /* Make sure these all map to SIGNED types -- not unsigned. This + * way they will be written out as SIGNED types and avoid the + * bit corruption that takes place when cfitsio adds, e.g., 0x7FFFFFFF + * to push the value into the unsigned range. + */ + if (*repeat <= 8) + { + *repeat = 1; + *stype = SLANG_CHAR_TYPE; + break; + } + if (*repeat <= 16) + { + *repeat = 1; + *stype = SLANG_INT16_TYPE; + break; + } + if (*repeat <= 32) + { + *repeat = 1; + *stype = SLANG_INT32_TYPE; + break; + } + SLang_verror (SL_NOT_IMPLEMENTED, "bit type %ldX is not supported", *repeat); + return -1; + + case TSTRING: + *stype = SLANG_STRING_TYPE; + break; + + default: + SLang_verror (SL_NOT_IMPLEMENTED, "Fits column type %d is not supported", + type); + return -1; + } + + return 0; +} + +static int open_file (SLang_Ref_Type *ref, char *filename, char *mode) +{ + fitsfile *fptr; + int status; + FitsFile_Type *ft; + SLang_MMT_Type *mmt; + + if (-1 == SLang_assign_to_ref (ref, SLANG_NULL_TYPE, NULL)) + return -1; + + status = 0; + fptr = NULL; + switch (*mode) + { + case 'r': + (void) fits_open_file (&fptr, filename, READONLY, &status); + break; + + case 'w': + (void) fits_open_file (&fptr, filename, READWRITE, &status); + break; + + case 'c': + if ((-1 == remove (filename)) + && (errno != ENOENT)) + { + SLang_verror (SL_OBJ_NOPEN, "Unable to create a new version of %s--- check permissions", filename); + return -1; + } + (void) fits_create_file (&fptr, filename, &status); + break; + + default: + SLang_verror (SL_INVALID_PARM, "fits_open_file: iomode \"%s\" is invalid", mode); + return -1; + } + + if (status) + return status; + + if (fptr == NULL) + return -1; + + ft = (FitsFile_Type *) SLmalloc (sizeof (FitsFile_Type)); + if (ft == NULL) + { + fits_close_file (fptr, &status); + return -1; + } + memset ((char *) ft, 0, sizeof (FitsFile_Type)); + + ft->fptr = fptr; + + if (NULL == (mmt = SLang_create_mmt (Fits_Type_Id, (VOID_STAR) ft))) + { + fits_close_file (fptr, &status); + SLfree ((char *) fptr); + return -1; + } + + if (-1 == SLang_assign_to_ref (ref, Fits_Type_Id, &mmt)) + { + SLang_free_mmt (mmt); /* This will close the file */ + return -1; + } + + return status; +} + +static int delete_file (FitsFile_Type *ft) +{ + int status = 0; + + if (ft->fptr != NULL) + fits_delete_file (ft->fptr, &status); + ft->fptr = NULL; + return status; +} + +static int close_file (FitsFile_Type *ft) +{ + int status = 0; + + status = 0; + if (ft->fptr != NULL) + { + (void) fits_close_file (ft->fptr, &status); + ft->fptr = NULL; + } + return status; +} + +static int movnam_hdu (FitsFile_Type *ft, int *hdutype, char *extname, int *extvers) +{ + int status = 0; + if (ft->fptr == NULL) + return -1; + return fits_movnam_hdu (ft->fptr, *hdutype, extname, *extvers, &status); +} + +static int movabs_hdu (FitsFile_Type *ft, int *n) +{ + int status = 0; + if (ft->fptr == NULL) + return -1; + return fits_movabs_hdu (ft->fptr, *n, NULL, &status); +} + +static int movrel_hdu (FitsFile_Type *ft, int *n) +{ + int status = 0; + if (ft->fptr == NULL) + return -1; + return fits_movrel_hdu (ft->fptr, *n, NULL, &status); +} + +static int get_num_hdus (FitsFile_Type *ft, SLang_Ref_Type *ref) +{ + int status = 0; + int num; + + if (ft->fptr == NULL) + return -1; + + if (0 == fits_get_num_hdus (ft->fptr, &num, &status)) + { + if (-1 == SLang_assign_to_ref (ref, SLANG_INT_TYPE, &num)) + return -1; + } + + return status; +} + +static int get_hdu_num (FitsFile_Type *ft) +{ + int num; + if (ft->fptr == NULL) + return -1; + return fits_get_hdu_num (ft->fptr, &num); +} + + +static int get_hdu_type (FitsFile_Type *ft, SLang_Ref_Type *ref) +{ + int hdutype; + int status = 0; + + if (ft->fptr == NULL) + return -1; + if (0 == fits_get_hdu_type (ft->fptr, &hdutype, &status)) + { + if (-1 == SLang_assign_to_ref (ref, SLANG_INT_TYPE, &hdutype)) + return -1; + } + return status; +} + +static int copy_file (FitsFile_Type *ft, FitsFile_Type *gt, + int *prev, int *cur, int *next) +{ + int status = 0; + + if ((ft->fptr == NULL) || (gt->fptr == NULL)) + return -1; +#ifndef fits_copy_file + (void) status; (void) prev; (void) cur; (void) next; + SLang_verror (SL_NOT_IMPLEMENTED, "Not supported by this version of cfitsio"); + return -1; +#else + return fits_copy_file (ft->fptr, gt->fptr, *prev, *cur, *next, &status); +#endif +} + +static int copy_hdu (FitsFile_Type *ft, FitsFile_Type *gt, int *morekeys) +{ + int status = 0; + + if ((ft->fptr == NULL) || (gt->fptr == NULL)) + return -1; + + return fits_copy_hdu (ft->fptr, gt->fptr, *morekeys, &status); +} + +static int copy_header (FitsFile_Type *ft, FitsFile_Type *gt) +{ + int status = 0; + + if ((ft->fptr == NULL) || (gt->fptr == NULL)) + return -1; + + return fits_copy_header (ft->fptr, gt->fptr, &status); +} + + +static int delete_hdu (FitsFile_Type *ft) +{ + int status = 0; + + if (ft->fptr == NULL) + return -1; + + return fits_delete_hdu (ft->fptr, NULL, &status); +} + + +static int pop_string_or_null (char **s) +{ + if (SLANG_NULL_TYPE == SLang_peek_at_stack ()) + { + *s = NULL; + return SLang_pop_null (); + } + + return SLang_pop_slstring (s); +} + +static int pop_array_or_null (SLang_Array_Type **a) +{ + if (SLANG_NULL_TYPE == SLang_peek_at_stack ()) + { + *a = NULL; + return SLang_pop_null (); + } + return SLang_pop_array (a, 1); +} + + +static FitsFile_Type *pop_fits_type (SLang_MMT_Type **mmt) +{ + FitsFile_Type *ft; + + if (NULL == (*mmt = SLang_pop_mmt (Fits_Type_Id))) + return NULL; + + if (NULL == (ft = (FitsFile_Type *) SLang_object_from_mmt (*mmt))) + { + SLang_free_mmt (*mmt); + *mmt = NULL; + } + return ft; +} + +static int create_img (FitsFile_Type *ft, int *bitpix, + SLang_Array_Type *at_naxes) +{ + long *axes; + unsigned int i, imax; + int status = 0; + + if (ft->fptr == NULL) + return -1; + + if (at_naxes->data_type != SLANG_INT_TYPE) + { + SLang_verror (SL_TYPE_MISMATCH, + "fits_create_img: naxis must be an integer array"); + return -1; + } + + imax = at_naxes->num_elements; + axes = (long *) SLmalloc ((imax+1) * sizeof (long)); + if (axes == NULL) + return -1; + + /* Transpose to FORTRAN order */ + for (i = 0; i < imax; i++) + axes[i] = ((int *) at_naxes->data)[imax-(i+1)]; + + (void) fits_create_img (ft->fptr, *bitpix, imax, axes, &status); + SLfree ((char *) axes); + return status; +} + +static int write_img (FitsFile_Type *ft, SLang_Array_Type *at) +{ + int type; + int status = 0; + + if (ft->fptr == NULL) + return -1; + + switch (at->data_type) + { + case SLANG_STRING_TYPE: + type = TSTRING; + break; + + case SLANG_DOUBLE_TYPE: + type = TDOUBLE; + break; + + case SLANG_FLOAT_TYPE: + type = TFLOAT; + break; + + case SLANG_INT16_TYPE: + type = CFITSIO_INT16_TYPE; + break; + + case SLANG_UINT16_TYPE: + type = CFITSIO_UINT16_TYPE; + break; + + case SLANG_INT32_TYPE: + type = CFITSIO_INT32_TYPE; + break; + + case SLANG_UINT32_TYPE: + type = CFITSIO_UINT32_TYPE; + break; + + case SLANG_CHAR_TYPE: + case SLANG_UCHAR_TYPE: + type = TBYTE; + break; + +#ifdef SLANG_INT64_TYPE + case SLANG_INT64_TYPE: + type = CFITSIO_INT64_TYPE; + break; +#endif + + default: + SLang_verror (SL_NOT_IMPLEMENTED, + "fits_write_img: %s not supported", + SLclass_get_datatype_name (at->data_type)); + return -1; + } + + return fits_write_img (ft->fptr, type, 1, at->num_elements, + at->data, &status); +} + +static int read_img (FitsFile_Type *ft, SLang_Ref_Type *ref) +{ + int status = 0; + int anynul = 0; + int type, stype; + int num_dims, i; + long ldims[SLARRAY_MAX_DIMS]; + int dims[SLARRAY_MAX_DIMS]; + SLang_Array_Type *at; + + if (ft->fptr == NULL) + return -1; + +#ifdef fits_get_img_equivtype + status = fits_get_img_equivtype (ft->fptr, &type, &status); +#else + status = fits_get_img_type (ft->fptr, &type, &status); +#endif + if (status) + return status; + + switch (type) + { + case BYTE_IMG: + stype = SLANG_UCHAR_TYPE; + type = TBYTE; + break; + + case SHORT_IMG: /* 16 bit image */ + stype = SLANG_INT16_TYPE; + type = CFITSIO_INT16_TYPE; + break; + + case USHORT_IMG: /* 16 bit image */ + stype = SLANG_UINT16_TYPE; + type = CFITSIO_UINT16_TYPE; + break; + + case LONG_IMG: /* 32 bit image */ + stype = SLANG_INT32_TYPE; + type = CFITSIO_INT32_TYPE; + break; + + case ULONG_IMG: /* 32 bit image */ + stype = SLANG_UINT32_TYPE; + type = CFITSIO_UINT32_TYPE; + break; + +#ifdef TLONGLONG + case LONGLONG_IMG: /* 64 bit image */ + stype = SLANG_INT64_TYPE; + type = CFITSIO_INT64_TYPE; + break; +#endif + + case DOUBLE_IMG: + stype = SLANG_DOUBLE_TYPE; + type = TDOUBLE; + break; + + case FLOAT_IMG: + default: + stype = SLANG_FLOAT_TYPE; + type = TFLOAT; + break; + } + + if (fits_get_img_dim (ft->fptr, &num_dims, &status)) + return status; + + if ((num_dims > SLARRAY_MAX_DIMS) || (num_dims < 0)) + { + SLang_verror (SL_NOT_IMPLEMENTED, "Image dimensionality is not supported"); + return -1; + } + + if (fits_get_img_size (ft->fptr, num_dims, ldims, &status)) + return status; + +#if 0 + for (i = 0; i < num_dims; i++) dims[i] = (int) ldims[i]; +#else + for (i = 0; i < num_dims; i++) dims[num_dims-1-i] = (int) ldims[i]; +#endif + + if (NULL == (at = SLang_create_array (stype, 0, NULL, dims, num_dims))) + return -1; + + status = fits_read_img (ft->fptr, type, 1, at->num_elements, NULL, + at->data, &anynul, &status); + + if (status) + { + SLang_free_array (at); + return status; + } + + if (-1 == SLang_assign_to_ref (ref, SLANG_ARRAY_TYPE, (VOID_STAR)&at)) + status = -1; + + SLang_free_array (at); + return status; +} + +static int create_binary_tbl (void) +{ + SLang_MMT_Type *mmt; + FitsFile_Type *ft; + SLang_Array_Type *at_ttype, *at_tform, *at_tunit; + char *extname; + int tfields, nrows; + int status; + + status = -1; + at_ttype = at_tform = at_tunit = NULL; + mmt = NULL; + ft = NULL; + + if (-1 == pop_string_or_null (&extname)) + return -1; + + if (-1 == pop_array_or_null (&at_tunit)) + goto free_and_return; + + if (-1 == SLang_pop_array (&at_tform, 1)) + goto free_and_return; + + if (-1 == SLang_pop_array (&at_ttype, 1)) + goto free_and_return; + + if (-1 == SLang_pop_integer (&nrows)) + goto free_and_return; + + if (NULL == (ft = pop_fits_type (&mmt))) + goto free_and_return; + + if (ft->fptr == NULL) + goto free_and_return; + + + tfields = (int) at_ttype->num_elements; + + if (at_ttype->data_type != SLANG_STRING_TYPE) + { + SLang_verror (SL_TYPE_MISMATCH, + "fits_create_binary_tbl: ttype must be String_Type[%d]", + tfields); + goto free_and_return; + } + + if ((tfields != (int) at_tform->num_elements) + || (at_tform->data_type != SLANG_STRING_TYPE)) + { + SLang_verror (SL_TYPE_MISMATCH, + "fits_create_binary_tbl: tform must be String_Type[%d]", + tfields); + goto free_and_return; + } + + if ((at_tunit != NULL) + && ((tfields != (int) at_tunit->num_elements) + || (at_tunit->data_type != SLANG_STRING_TYPE))) + { + SLang_verror (SL_TYPE_MISMATCH, + "fits_create_binary_tbl: tunit must be String_Type[%d]", + tfields); + goto free_and_return; + } + + status = 0; + fits_create_tbl (ft->fptr, BINARY_TBL, nrows, tfields, + (char **) at_ttype->data, + (char **) at_tform->data, + ((at_tunit == NULL) ? NULL : (char **) at_tunit->data), + extname, &status); + + /* drop */ + + free_and_return: + SLang_free_array (at_ttype); + SLang_free_array (at_tform); + SLang_free_array (at_tunit); + SLang_free_mmt (mmt); + SLang_free_slstring (extname); + + return status; +} + +static int update_key (void) +{ + SLang_MMT_Type *mmt; + FitsFile_Type *ft; + char *comment; + int i; + double d; + char *s; + char *key; + int type; + VOID_STAR v; + int status; + + if (-1 == pop_string_or_null (&comment)) + return -1; + + key = s = NULL; + mmt = NULL; + status = -1; + + type = SLang_peek_at_stack (); + switch (type) + { + case SLANG_STRING_TYPE: + type = TSTRING; + if (-1 == SLang_pop_slstring (&s)) + goto free_and_return; + v = (VOID_STAR) s; + break; + + case SLANG_INT_TYPE: + type = TINT; + if (-1 == SLang_pop_integer (&i)) + goto free_and_return; + v = (VOID_STAR) &i; + break; + + case SLANG_NULL_TYPE: + if (-1 == SLang_pop_null ()) + goto free_and_return; + v = NULL; + break; + + case -1: /* stack underflow */ + goto free_and_return; + + case SLANG_DOUBLE_TYPE: + default: + type = TDOUBLE; +#if SLANG_VERSION < 20000 + if (-1 == SLang_pop_double (&d, NULL, NULL)) + goto free_and_return; +#else + if (-1 == SLang_pop_double (&d)) + goto free_and_return; +#endif + v = (VOID_STAR) &d; + break; + } + + if (-1 == SLang_pop_slstring (&key)) + goto free_and_return; + + if (NULL == (ft = pop_fits_type (&mmt))) + goto free_and_return; + + if (ft->fptr == NULL) + goto free_and_return; + + status = 0; + if (v != NULL) + { + if (type == TSTRING) + fits_update_key_longstr (ft->fptr, key, (char *)v, comment, &status); + else + fits_update_key (ft->fptr, type, key, v, comment, &status); + } + else + fits_update_key_null (ft->fptr, key, comment, &status); + + free_and_return: + + SLang_free_mmt (mmt); + SLang_free_slstring (key); + SLang_free_slstring (comment); + SLang_free_slstring (s); + + return status; +} + +static int update_logical (void) +{ + SLang_MMT_Type *mmt; + FitsFile_Type *ft; + char *comment; + int i; + char *key; + int status; + + if (-1 == pop_string_or_null (&comment)) + return -1; + + key = NULL; + mmt = NULL; + status = -1; + + if ((0 == SLang_pop_integer (&i)) + && (0 == SLang_pop_slstring (&key)) + && (NULL != (ft = pop_fits_type (&mmt))) + && (ft->fptr != NULL)) + { + status = 0; + fits_update_key (ft->fptr, TLOGICAL, key, + (VOID_STAR) &i, comment, &status); + } + + SLang_free_mmt (mmt); + SLang_free_slstring (key); + SLang_free_slstring (comment); + + return status; +} + +static int write_comment (FitsFile_Type *ft, char *comment) +{ + int status = 0; + if (ft->fptr == NULL) + return -1; + return fits_write_comment (ft->fptr, comment, &status); +} + +static int write_history (FitsFile_Type *ft, char *comment) +{ + int status = 0; + if (ft->fptr == NULL) + return -1; + return fits_write_history (ft->fptr, comment, &status); +} + +static int write_date (FitsFile_Type *ft) +{ + int status = 0; + if (ft->fptr == NULL) + return -1; + return fits_write_date (ft->fptr, &status); +} + +static int write_record (FitsFile_Type *ft, char *card) +{ + int status = 0; + + if (ft->fptr == NULL) + return -1; + + /* How robust is fits_write_record to cards that are not 80 characters long? */ + return fits_write_record (ft->fptr, card, &status); +} + +static int insert_record (FitsFile_Type *ft, int *keynum, char *card) +{ + int status = 0; + + if (ft->fptr == NULL) + return -1; + + return fits_insert_record (ft->fptr, *keynum, card, &status); +} + + + +static int modify_name (FitsFile_Type *ft, char *oldname, char *newname) +{ + int status = 0; + if (ft->fptr == NULL) + return -1; + return fits_modify_name (ft->fptr, oldname, newname, &status); +} + +static int do_get_keytype (fitsfile *f, char *name, int *stype) +{ + int status = 0; + char type; + int s; + char card [FLEN_CARD + 1]; + char value [FLEN_CARD + 1]; + + if (f == NULL) + return -1; + + if (0 != fits_read_card (f, name, card, &status)) + return status; + + if (0 != fits_parse_value (card, value, NULL, &status)) + return status; + + if (0 != fits_get_keytype (value, &type, &status)) + return status; + + switch (type) + { + case 'C': + s = SLANG_STRING_TYPE; + break; + + case 'L': + s = SLANG_INT_TYPE; + break; + + case 'F': + s = SLANG_DOUBLE_TYPE; + break; + + case 'X': + s = SLANG_COMPLEX_TYPE; + break; + + case 'I': + default: + s = SLANG_INT_TYPE; + break; + } + *stype = s; + + return 0; +} + + + +static int read_key (int type) +{ + SLang_MMT_Type *mmt; + FitsFile_Type *ft; + int status; + char *name; + char comment_buf [FLEN_COMMENT]; + SLang_Ref_Type *comment_ref, *v_ref; + int ival; + double dval; + char *sval = NULL; + int ftype; + VOID_STAR v; + + v_ref = comment_ref = NULL; + name = NULL; + mmt = NULL; + status = -1; + + if (SLANG_NULL_TYPE == SLang_peek_at_stack ()) + { + if (-1 == SLang_pop_null ()) + return -1; + } + else if (-1 == SLang_pop_ref (&comment_ref)) + return -1; + + if (-1 == SLang_pop_ref (&v_ref)) + goto free_and_return; + + if (-1 == SLang_pop_slstring (&name)) + goto free_and_return; + + if (NULL == (ft = pop_fits_type (&mmt))) + goto free_and_return; + + if (ft->fptr == NULL) + goto free_and_return; + + if (type == SLANG_VOID_TYPE) + { + if (0 != (status = do_get_keytype (ft->fptr, name, &type))) + goto free_and_return; + + status = -1; + } + + switch (type) + { + case SLANG_INT_TYPE: + v = (VOID_STAR) &ival; + ftype = TINT; + ival = 0; + break; + + case SLANG_DOUBLE_TYPE: + ftype = TDOUBLE; + v = (VOID_STAR) &dval; + dval = 0.0; + break; + + case SLANG_STRING_TYPE: + ftype = TSTRING; + v = (VOID_STAR) &sval; + break; + + default: + SLang_verror (SL_INVALID_PARM, + "fits_read_key: type %s not supported", + SLclass_get_datatype_name (type)); + goto free_and_return; + } + + status = 0; + if (ftype == TSTRING) + fits_read_key_longstr (ft->fptr, name, &sval, comment_buf, &status); + else + fits_read_key (ft->fptr, ftype, name, v, comment_buf, &status); + + if (status == 0) + { + if (comment_ref != NULL) + { + char *cptr = comment_buf; + if (-1 == SLang_assign_to_ref (comment_ref, + SLANG_STRING_TYPE, (VOID_STAR) &cptr)) + { + status = -1; + goto free_and_return; + } + } + if (-1 == SLang_assign_to_ref (v_ref, type, v)) + { + status = -1; + goto free_and_return; + } + } + + free_and_return: + SLfree (sval); + SLang_free_ref (comment_ref); + SLang_free_ref (v_ref); + SLang_free_slstring (name); + SLang_free_mmt (mmt); + return status; +} + +static int read_key_integer (void) +{ + return read_key (SLANG_INT_TYPE); +} + +static int read_key_double (void) +{ + return read_key (SLANG_DOUBLE_TYPE); +} + +static int read_key_string (void) +{ + return read_key (SLANG_STRING_TYPE); +} + +static int read_generic_key (void) +{ + return read_key (SLANG_VOID_TYPE); +} + +static int read_record (FitsFile_Type *ft, int *keynum, SLang_Ref_Type *ref) +{ + int status = 0; + char card[FLEN_CARD+1]; + + if (ft->fptr == NULL) + return -1; + + if (0 == fits_read_record (ft->fptr, *keynum, card, &status)) + { + char *c = card; + if (-1 == SLang_assign_to_ref (ref, SLANG_STRING_TYPE, &c)) + return -1; + } + + return status; +} + +static int delete_key (FitsFile_Type *ft, char *key) +{ + int status = 0; + if (ft->fptr == NULL) + return -1; + return fits_delete_key (ft->fptr, key, &status); +} + + +static int get_colnum (FitsFile_Type *ft, char *name, SLang_Ref_Type *ref) +{ + int status = 0; + int col; + + if (ft->fptr == NULL) + return -1; + /* FIXME: fits_get_colnum may be used to get columns matching a pattern */ + col = 1; + fits_get_colnum (ft->fptr, CASEINSEN, name, &col, &status); + + if (-1 == SLang_assign_to_ref (ref, SLANG_INT_TYPE, (VOID_STAR) &col)) + status = -1; + + return status; +} + +static int insert_rows (FitsFile_Type *ft, int *first, int *num) +{ + int status = 0; + if (ft->fptr == NULL) + return -1; + if ((*first <= 0) || (*num < 0)) + { + SLang_verror (SL_INVALID_PARM, "fits_insert_rows: first and num must be positive"); + return -1; + } + + return fits_insert_rows (ft->fptr, *first, *num, &status); +} + +static int delete_rows (FitsFile_Type *ft, int *first, int *num) +{ + int status = 0; + if (ft->fptr == NULL) + return -1; + if ((*first <= 0) || (*num < 0)) + { + SLang_verror (SL_INVALID_PARM, "fits_delete_rows: first and num must be positive"); + return -1; + } + + return fits_delete_rows (ft->fptr, *first, *num, &status); +} + +static int insert_cols (FitsFile_Type *ft, int *colnum, + SLang_Array_Type *at_ttype, + SLang_Array_Type *at_tform) +{ + int ncols; + char **ttype, **tform; + int i; + int status = 0; + + if (ft->fptr == NULL) + return -1; + ncols = at_ttype->num_elements; + if ((ncols < 0) || (ncols != (int) at_tform->num_elements) + || (at_ttype->data_type != SLANG_STRING_TYPE) + || (at_tform->data_type != SLANG_STRING_TYPE)) + { + SLang_verror (SL_INVALID_PARM, + "fits_insert_cols: ttype and tform must be string arrays of same size"); + return -1; + } + + if (*colnum <= 0) + { + SLang_verror (SL_INVALID_PARM, "fits_insert_cols: colnum must be positive"); + return -1; + } + + tform = (char **)at_tform->data; + ttype = (char **)at_ttype->data; + + for (i = 0; i < ncols; i++) + { + if ((tform[i] == NULL) || (ttype[i] == NULL)) + { + SLang_verror (SL_INVALID_PARM, + "fits_insert_cols: ttype and tform elements muts be non NULL"); + return -1; + } + } + return fits_insert_cols (ft->fptr, *colnum, ncols, ttype, tform, &status); +} + +static int delete_col (FitsFile_Type *ft, int *col) +{ + int status = 0; + if (ft->fptr == NULL) + return -1; + return fits_delete_col (ft->fptr, *col, &status); +} + +static int get_num_rows (FitsFile_Type *ft, SLang_Ref_Type *ref) +{ + long nrows; + int status = 0; + + if (ft->fptr == NULL) + return -1; + if (0 == fits_get_num_rows (ft->fptr, &nrows, &status)) + { + int inrows = (int) nrows; + if (-1 == SLang_assign_to_ref (ref, SLANG_INT_TYPE, (VOID_STAR) &inrows)) + return -1; + } + return status; +} + +static int get_rowsize (FitsFile_Type *ft, SLang_Ref_Type *ref) +{ + long nrows; + int status = 0; + + if (ft->fptr == NULL) + return -1; + if (0 == fits_get_rowsize (ft->fptr, &nrows, &status)) + { + int inrows = (int) nrows; + if (-1 == SLang_assign_to_ref (ref, SLANG_INT_TYPE, (VOID_STAR) &inrows)) + return -1; + } + return status; +} + +static int get_num_cols (FitsFile_Type *ft, SLang_Ref_Type *ref) +{ + int ncols; + int status = 0; + + if (ft->fptr == NULL) + return -1; + if (0 == fits_get_num_cols (ft->fptr, &ncols, &status)) + { + if (-1 == SLang_assign_to_ref (ref, SLANG_INT_TYPE, (VOID_STAR) &ncols)) + return -1; + } + return status; +} + +static void byte_swap32 (unsigned char *ss, unsigned int n) +{ + unsigned char *p, *pmax, ch; + + p = (unsigned char *) ss; + pmax = p + 4 * n; + while (p < pmax) + { + ch = *p; + *p = *(p + 3); + *(p + 3) = ch; + + ch = *(p + 1); + *(p + 1) = *(p + 2); + *(p + 2) = ch; + p += 4; + } +} + +static void byte_swap16 (unsigned char *p, unsigned int nread) +{ + unsigned char *pmax, ch; + + pmax = p + 2 * nread; + while (p < pmax) + { + ch = *p; + *p = *(p + 1); + *(p + 1) = ch; + p += 2; + } +} + + +/* MAJOR HACK!!!! */ +static int hack_write_bit_col (fitsfile *f, unsigned int col, + unsigned int row, unsigned int firstelem, + unsigned int sizeof_type, unsigned int num_elements, + unsigned char *bytes) +{ + static int status = 0; + tcolumn *colptr; + long trepeat; + int tcode; + + if ((f == NULL) || (f->Fptr == NULL) + || (NULL == (colptr = (f->Fptr)->tableptr))) + return WRITE_ERROR; + + colptr += (col - 1); /* offset to correct column structure */ + trepeat = colptr->trepeat; + tcode = colptr->tdatatype; + + colptr->tdatatype = TBYTE; + colptr->trepeat = sizeof_type; + + + (void) fits_write_col (f, TBYTE, col, row, firstelem, + num_elements*sizeof_type, bytes, &status); + + colptr->tdatatype = tcode; + colptr->trepeat = trepeat; + + return status; +} + +static int write_tbit_col (fitsfile *f, unsigned int col, unsigned int row, + unsigned int firstelem, unsigned int repeat, + unsigned int width, SLang_Array_Type *at) +{ + int status = 0; + unsigned int num_elements; + unsigned int sizeof_type; + unsigned char *data, *buf; + unsigned short s; + void (*bs) (unsigned char *, unsigned int); + + (void) width; + num_elements = at->num_elements; + sizeof_type = at->sizeof_type; + data = (unsigned char *) at->data; + + if (8 * sizeof_type != repeat) + { + SLang_verror (SL_NOT_IMPLEMENTED, "Writing a %dX bit column requires the appropriately sized integer", + repeat); + return -1; + } + + s = 0x1234; + if ((*(unsigned char *) &s == 0x12) + || (sizeof_type == 1)) + { + return hack_write_bit_col (f, col, row, firstelem, + sizeof_type, num_elements, data); + } + + /* Sigh. Need to byteswap */ + switch (sizeof_type) + { + case 2: + bs = byte_swap16; + break; + + case 4: + bs = byte_swap32; + break; + + default: + SLang_verror (SL_NOT_IMPLEMENTED, "writing to a %dX column is not supported", repeat); + return -1; + } + + buf = (unsigned char *) SLmalloc (num_elements * sizeof_type); + if (buf == NULL) + return -1; + + memcpy (buf, data, num_elements * sizeof_type); + (*bs) (buf, num_elements); + + status = hack_write_bit_col (f, col, row, firstelem, + sizeof_type, num_elements, buf); + + SLfree ((char *) buf); + return status; +} + +#ifdef fits_get_eqcoltype +# define GET_COL_TYPE fits_get_eqcoltype +#else +# define GET_COL_TYPE my_fits_get_coltype +static int my_fits_get_coltype (fitsfile *fptr, int col, int *type, + long *repeat, long *width, int *statusp) +{ + int status = *statusp; + char tscaln[32]; + char tzeron[32]; + double tscal, tzero; + double min_val, max_val; + + if (ft->fptr == NULL) + return -1; + + if (0 != fits_get_coltype (fptr, col, type, repeat, width, &status)) + { + *statusp = status; + return status; + } + + sprintf (tscaln, "TSCAL%d", col); + sprintf (tzeron, "TZERO%d", col); + + if (0 != fits_read_key (fptr, TDOUBLE, tscaln, &tscal, NULL, &status)) + { + fits_clear_errmsg (); + tscal = 1.0; + } + + if (0 != fits_read_key (fptr, TDOUBLE, tzeron, &tzero, NULL, &status)) + { + fits_clear_errmsg (); + tzero = 0; + } + + switch (*type) + { + case TSHORT: + min_val = -32768.0; + max_val = 32767.0; + break; + + case TLONG: + min_val = -2147483648.0; + max_val = 2147483647.0; + break; + + default: + return 0; + } + + min_val = tzero + tscal * min_val; + max_val = tzero + tscal * max_val; + + if (min_val > max_val) + { + double tmp = max_val; + max_val = min_val; + min_val = tmp; + } + + if ((min_val >= -32768.0) && (max_val <= 32767.0)) + { + *type = TSHORT; + return 0; + } + + if ((min_val >= 0) && (max_val <= 65535.0)) + { + *type = TUSHORT; + return 0; + } + + if ((min_val >= -2147483648.0) && (max_val <= 2147483647.0)) + { + *type = TLONG; + return 0; + } + + if ((min_val >= 0.0) && (max_val <= 4294967295.0)) + { + *type = TULONG; + return 0; + } + + *type = TDOUBLE; + return 0; +} +#endif + +static int write_col (FitsFile_Type *ft, int *colnum, + int *firstrow, int *firstelem, SLang_Array_Type *at) +{ + int type; + int status = 0; + int col; + long repeat; + long width; + + if (ft->fptr == NULL) + return -1; + + col = *colnum; + + if (0 != GET_COL_TYPE (ft->fptr, col, &type, &repeat, &width, &status)) + return status; + + if (type == TBIT) + return write_tbit_col (ft->fptr, col, *firstrow, *firstelem, + repeat, width, at); + + switch (at->data_type) + { + case SLANG_INT16_TYPE: + type = CFITSIO_INT16_TYPE; + break; + case SLANG_UINT16_TYPE: + type = CFITSIO_UINT16_TYPE; + break; + case SLANG_INT32_TYPE: + type = CFITSIO_INT32_TYPE; + break; + case SLANG_UINT32_TYPE: + type = CFITSIO_UINT32_TYPE; + break; +#ifdef CFITSIO_INT64_TYPE + case SLANG_INT64_TYPE: + type = CFITSIO_INT64_TYPE; + break; +#endif + + case SLANG_DOUBLE_TYPE: + type = TDOUBLE; + break; + + case SLANG_FLOAT_TYPE: + type = TFLOAT; + break; + + case SLANG_STRING_TYPE: + type = TSTRING; + break; + + case SLANG_CHAR_TYPE: + case SLANG_UCHAR_TYPE: + type = TBYTE; + break; + + default: + SLang_verror (SL_NOT_IMPLEMENTED, + "fits_write_col: %s not suppported", + SLclass_get_datatype_name (at->data_type)); + return -1; + } + + return fits_write_col (ft->fptr, type, *colnum, *firstrow, *firstelem, + at->num_elements, at->data, &status); +} + +static int read_string_cell (fitsfile *f, unsigned int row, unsigned int col, + unsigned int len, char **sp) +{ + char *s; + char *sls; + int status = 0; + int anynul; + + *sp = NULL; + + if (f == NULL) + return -1; + + if (NULL == (s = SLmalloc (len + 1))) + return -1; + + /* Note that the number of elements passed to this must be 1 */ + if (0 != fits_read_col (f, TSTRING, col, row, 1, 1, NULL, + &s, &anynul, &status)) + { + SLfree (s); + return status; + } + sls = SLang_create_slstring (s); + SLfree (s); + if (sls == NULL) + return -1; + + *sp = sls; + return 0; +} + +static int read_string_column (fitsfile *f, int is_var, long repeat, + int col, unsigned int firstrow, unsigned int numrows, + SLang_Array_Type **atp) +{ + int num_elements; + char **ats; + unsigned int i; + int status = 0; + SLang_Array_Type *at; + + *atp = NULL; + + if (f == NULL) + return -1; + + num_elements = (int) numrows; + at = SLang_create_array (SLANG_STRING_TYPE, 0, NULL, &num_elements, 1); + if (at == NULL) + return -1; + + ats = (char **) at->data; + + for (i = 0; i < numrows; i++) + { + long offset; + long row; + + row = firstrow + i; + if (is_var) + { + if (0 != fits_read_descript (f, col, row, &repeat, &offset, &status)) + { + SLang_free_array (at); + return status; + } + } + + status = read_string_cell (f, row, col, repeat, ats+i); + if (status != 0) + { + SLang_free_array (at); + return status; + } + } + + *atp = at; + return 0; +} + + + +static int read_bit_column (fitsfile *f, unsigned int col, unsigned int row, + unsigned int firstelem, unsigned int num_elements, + unsigned char *data, unsigned int bytes_per_elem, + unsigned int bits_per_elem) +{ + int status, anynul; + unsigned short s; + + if (f == NULL) + return -1; + + status = 0; + if (0 != fits_read_col (f, TBYTE, col, row, + firstelem, num_elements*bytes_per_elem, + NULL, data, &anynul, &status)) + return status; + + s = 0x1234; + if (*(unsigned char *) &s == 0x12) + return status; + + /* Otherwise, byteswap */ + switch (bytes_per_elem) + { + SLuindex_Type i; + int shift; + int16_type *data16; + int32_type *data32; + + case 1: + shift = 8*bytes_per_elem - bits_per_elem; + if (shift) for (i = 0; i < num_elements; i++) + { + data[i] = (data[i] >> shift); + } + break; + + case 2: + byte_swap16 (data, num_elements); + shift = 8*bytes_per_elem - bits_per_elem; + data16 = (int16_type *)data; + if (shift) for (i = 0; i < num_elements; i++) + { + data16[i] = (data16[i] >> shift); + } + break; + + case 4: + byte_swap32 (data, num_elements); + shift = 8*bytes_per_elem - bits_per_elem; + data32 = (int32_type *)data; + if (shift) for (i = 0; i < num_elements; i++) + { + data32[i] = (data32[i] >> shift); + } + break; + + default: + SLang_verror (SL_NOT_IMPLEMENTED, "%u byte integers are unsupported", + bytes_per_elem); + return -1; + } + + + return 0; +} + + + +static int read_column_values (fitsfile *f, int type, SLtype datatype, + unsigned int row, unsigned int col, unsigned int num_rows, + int repeat, int repeat_orig, SLang_Array_Type **atp) +{ + int num_elements; + int status = 0; + int anynul; + SLang_Array_Type *at; + int dims[2]; + int num_dims; + + *atp = NULL; + + if (f == NULL) + return -1; + + num_elements = num_rows * repeat; + if (num_rows <= 1) + { + dims[0] = num_elements; + num_dims = 1; + } + else /* was repeat>1 */ + { + dims[0] = num_rows; + dims[1] = repeat; + num_dims = 2; + } + + at = SLang_create_array (datatype, 0, NULL, dims, num_dims); + if (at == NULL) + return -1; + + if (num_elements) + { + if (type == TBIT) + status = read_bit_column (f, col, row, 1, num_elements, (unsigned char *)at->data, at->sizeof_type, repeat_orig); + else + (void) fits_read_col (f, type, col, row, 1, num_elements, NULL, + at->data, &anynul, &status); + } + + if (status) + { + SLang_free_array (at); + return status; + } + + *atp = at; + return 0; +} + +static int read_var_column (fitsfile *f, int ftype, SLtype datatype, + int col, unsigned int firstrow, unsigned int num_rows, + SLang_Array_Type **atp) +{ + int num_elements; + unsigned int i; + SLang_Array_Type **ati; + SLang_Array_Type *at; + + *atp = NULL; + if (f == NULL) + return -1; + + num_elements = (int) num_rows; + + at = SLang_create_array (SLANG_ARRAY_TYPE, 0, NULL, &num_elements, 1); + if (at == NULL) + return -1; + + ati = (SLang_Array_Type **) at->data; + for (i = 0; i < num_rows; i++) + { + long offset; + long repeat; + unsigned int row; + int status = 0; + + row = firstrow + i; + if (0 != fits_read_descript (f, col, row, &repeat, &offset, &status)) + { + SLang_free_array (at); + return status; + } + + status = read_column_values (f, ftype, datatype, row, col, 1, repeat, repeat, ati+i); + if (status) + { + SLang_free_array (at); + return status; + } + } + + *atp = at; + return 0; +} + +static int read_col (FitsFile_Type *ft, int *colnum, int *firstrowp, + int *num_rowsp, SLang_Ref_Type *ref) +{ + SLang_Array_Type *at; + int type; + long num_rows; + long width; + int status; + SLtype datatype; + int num_columns; + int firstrow; + long repeat, save_repeat; + int col; + + if (ft->fptr == NULL) + return -1; + + status = 0; + if (0 != fits_get_num_cols (ft->fptr, &num_columns, &status)) + return status; + + if (0 != fits_get_num_rows (ft->fptr, &num_rows, &status)) + return status; + + if (*num_rowsp <= 0) + { + SLang_verror (SL_INVALID_PARM, "Number of rows must positive"); + return -1; + } + + col = *colnum; + + if ((col <= 0) || (col > num_columns)) + { + SLang_verror (SL_INVALID_PARM, "Column number out of range"); + return -1; + } + firstrow = *firstrowp; + if ((firstrow <= 0) || (firstrow > num_rows)) + { + SLang_verror (SL_INVALID_PARM, "Row number out of range"); + return -1; + } + + if (firstrow + *num_rowsp > num_rows + 1) + num_rows = num_rows - (firstrow - 1); + else + num_rows = *num_rowsp; + + if (0 != GET_COL_TYPE (ft->fptr, col, &type, &repeat, &width, &status)) + return status; + + save_repeat = repeat; + if (-1 == map_fitsio_type_to_slang (&type, &repeat, &datatype)) + return -1; + + + if (datatype == SLANG_STRING_TYPE) + { + /* This assumes an ASCII_TBL, which will always have a + * repeat of 1, and the number of bytes is given by the + * width field. In contrast, a BINARY_TBL will have + * repeat = number of bytes, and width represents the + * number of bytes in a substring. + */ + if ((repeat == 1) && (width != 1)) + repeat = width; + status = read_string_column (ft->fptr, (type < 0), repeat, col, firstrow, num_rows, &at); + } + else if (type < 0) + status = read_var_column (ft->fptr, -type, datatype, col, firstrow, num_rows, &at); + else + status = read_column_values (ft->fptr, type, datatype, firstrow, col, num_rows, repeat, save_repeat, &at); + + if (status) + return status; + + if (-1 == SLang_assign_to_ref (ref, SLANG_ARRAY_TYPE, (VOID_STAR)&at)) + status = -1; + + SLang_free_array (at); + return status; +} + +typedef struct +{ + int type; + long repeat, width; + long repeat_orig; /* used for tbit columns */ + SLtype datatype; + unsigned int data_offset; +} +Column_Info_Type; + +static int read_var_column_data (fitsfile *f, int ftype, SLtype datatype, + int col, unsigned int firstrow, unsigned int num_rows, + SLang_Array_Type **at_data) +{ + unsigned int i; + + for (i = 0; i < num_rows; i++) + { + long offset; + long repeat; + unsigned int row; + int status = 0; + + row = firstrow + i; + if (0 != fits_read_descript (f, col, row, &repeat, &offset, &status)) + return status; + + status = read_column_values (f, ftype, datatype, row, col, 1, repeat, repeat, at_data+i); + if (status) + return status; + } + return 0; +} + +static int read_string_column_data (fitsfile *f, int is_var, long repeat, int col, + long firstrow, unsigned int num_rows, + char **strs) +{ + unsigned int i; + int status = 0; + + for (i = 0; i < num_rows; i++) + { + long offset; + long row; + + row = firstrow + i; + if (is_var) + { + if (0 != fits_read_descript (f, col, row, &repeat, &offset, &status)) + return status; + } + + status = read_string_cell (f, row, col, repeat, strs + i); + if (status != 0) + return status; + } + return 0; +} + + +/* Usage: read_cols (ft, [columns...], firstrow, nrows, &ref) */ +static int read_cols (void) +{ + SLang_MMT_Type *mmt; + FitsFile_Type *ft; + fitsfile *f; + int status; + int num_columns_in_table; + long num_rows_in_table, delta_rows; + int num_rows; + int firstrow; + int *cols; + int num_cols; + int i; + SLang_Ref_Type *ref; + Column_Info_Type *ci = NULL; + SLang_Array_Type *data_arrays_at = NULL; + SLang_Array_Type **data_arrays = NULL; + SLang_Array_Type *columns_at = NULL; + + if (-1 == SLang_pop_ref (&ref)) + return -1; + if ((-1 == SLang_pop_integer (&num_rows)) + || (-1 == SLang_pop_integer (&firstrow)) + || (-1 == SLang_pop_array (&columns_at, 1))) + { + SLang_free_ref (ref); + return -1; + } + if (NULL == (ft = pop_fits_type (&mmt))) + { + SLang_free_array (columns_at); + SLang_free_ref (ref); + return -1; + } + + status = -1; + f = ft->fptr; + if (f == NULL) + goto free_and_return_status; + + status = 0; + if ((0 != fits_get_num_cols (f, &num_columns_in_table, &status)) + || (0 != fits_get_num_rows (f, &num_rows_in_table, &status))) + goto free_and_return_status; + + if (num_rows < 0) + { + SLang_verror (SL_INVALID_PARM, "Number of rows must be non-negative"); + status = -1; + goto free_and_return_status; + } + + if ((firstrow <= 0) + || ((firstrow > num_rows_in_table) && (num_rows > 0))) + { + SLang_verror (SL_INVALID_PARM, "Row number out of range"); + return -1; + } + + if (firstrow + num_rows > num_rows_in_table + 1) + num_rows = num_rows_in_table - (firstrow - 1); + + cols = (int *)columns_at->data; + num_cols = columns_at->num_elements; + + if (NULL == (ci = (Column_Info_Type *) SLmalloc (num_cols*sizeof (Column_Info_Type)))) + { + status = -1; + goto free_and_return_status; + } + + data_arrays_at = SLang_create_array (SLANG_ARRAY_TYPE, 0, NULL, &num_cols, 1); + if (data_arrays_at == NULL) + { + status = -1; + goto free_and_return_status; + } + data_arrays = (SLang_Array_Type **)data_arrays_at->data; + + for (i = 0; i < num_cols; i++) + { + SLang_Array_Type *at; + SLtype datatype; + long repeat; + int type; + int col; + + col = cols[i]; + if ((col <= 0) || (col > num_columns_in_table)) + { + SLang_verror (SL_INVALID_PARM, "Column number out of range"); + status = -1; + goto free_and_return_status; + } + + if (0 != GET_COL_TYPE (f, col, &type, &repeat, &ci[i].width, &status)) + goto free_and_return_status; + + ci[i].repeat_orig = repeat; + if (-1 == map_fitsio_type_to_slang (&type, &repeat, &datatype)) + { + status = -1; + goto free_and_return_status; + } + ci[i].repeat = repeat; + ci[i].type = type; + ci[i].datatype = datatype; + ci[i].data_offset = 0; + + if (datatype == SLANG_STRING_TYPE) + { + at = SLang_create_array (SLANG_STRING_TYPE, 0, NULL, &num_rows, 1); + } + else if (type < 0) /* variable length */ + { + if (-type == TBIT) + { + SLang_verror (SL_NOT_IMPLEMENTED, "Read bit-data from the heap is not supported. Please report this problem"); + status = -1; + goto free_and_return_status; + } + at = SLang_create_array (SLANG_ARRAY_TYPE, 0, NULL, &num_rows, 1); + } + else + { + int dims[2]; + int num_dims = 1; + dims[0] = num_rows; + if (repeat > 1) + { + dims[1] = repeat; + num_dims++; + } + at = SLang_create_array (datatype, 0, NULL, dims, num_dims); + } + + if (at == NULL) + { + status = -1; + goto free_and_return_status; + } + data_arrays[i] = at; + } + + if (fits_get_rowsize (f, &delta_rows, &status)) + goto free_and_return_status; + + if (delta_rows < 1) + delta_rows = 1; + + while (num_rows) + { + if (num_rows < delta_rows) + delta_rows = num_rows; + + for (i = 0; i < num_cols; i++) + { + SLtype datatype = ci[i].datatype; + int type = ci[i].type; + long repeat = ci[i].repeat; + int col = cols[i]; + SLang_Array_Type *at = data_arrays[i]; + unsigned int data_offset = ci[i].data_offset; + + if (datatype == SLANG_STRING_TYPE) + { + /* This assumes an ASCII_TBL, which will always have a + * repeat of 1, and the number of bytes is given by the + * width field. In contrast, a BINARY_TBL will have + * repeat = number of bytes, and width represents the + * number of bytes in a substring. + */ + if ((repeat == 1) && (ci[i].width != 1)) + repeat = ci[i].width; + + status = read_string_column_data (f, (type < 0), repeat, col, firstrow, delta_rows, + (char **)at->data + data_offset); + data_offset += delta_rows; + } + else if (type < 0) + { + status = read_var_column_data (f, -type, datatype, col, firstrow, delta_rows, + (SLang_Array_Type **)at->data + data_offset); + data_offset += delta_rows; + } + else + { + unsigned int num_elements = repeat * delta_rows; + unsigned char *data = (unsigned char *)at->data + data_offset; + /* int anynul; */ + + if (type == TBIT) + status = read_bit_column (f, col, firstrow, 1, num_elements, data, at->sizeof_type, ci[i].repeat_orig); + else + (void) fits_read_col (f, type, col, firstrow, 1, num_elements, NULL, + data, NULL, &status); + + data_offset += num_elements * at->sizeof_type; + } + ci[i].data_offset = data_offset; + + if (status) + goto free_and_return_status; + } + firstrow += delta_rows; + num_rows -= delta_rows; + } + + if (status) + return status; + + if (-1 == SLang_assign_to_ref (ref, SLANG_ARRAY_TYPE, (VOID_STAR)&data_arrays_at)) + status = -1; + + /* drop */ + + free_and_return_status: + SLfree ((char *)ci); + SLang_free_mmt (mmt); + SLang_free_array (columns_at); + SLang_free_ref (ref); + SLang_free_array (data_arrays_at); + + return status; +} + +static void clear_errmsg (void) +{ + fits_clear_errmsg (); +} + +static void get_errstatus (int *status) +{ + char errbuf [FLEN_ERRMSG]; + + *errbuf = 0; + fits_get_errstatus (*status, errbuf); + (void) SLang_push_string (errbuf); +} + +static void read_errmsg (void) +{ + char errbuf [FLEN_ERRMSG]; + + if (0 == fits_read_errmsg (errbuf)) + (void) SLang_push_null (); + else + (void) SLang_push_string (errbuf); +} + +static int get_num_keys (FitsFile_Type *f, SLang_Ref_Type *ref) +{ + int status = 0; + int nkeys; + + if (f->fptr == NULL) + return -1; + if (0 == fits_get_hdrspace (f->fptr, &nkeys, NULL, &status)) + return SLang_assign_to_ref (ref, SLANG_INT_TYPE, (VOID_STAR) &nkeys); + + return status; +} + + +static int get_keytype (FitsFile_Type *f, char *name, SLang_Ref_Type *v) +{ + int status = 0; + int type; + + if (f->fptr == NULL) + return -1; + if (0 == (status = do_get_keytype (f->fptr, name, &type))) + return SLang_assign_to_ref (v, SLANG_DATATYPE_TYPE, (VOID_STAR) &type); + + return status; +} + +#if 0 +static int _read_key_n (FitsFile_Type *f, SLang_Ref_Type *v, SLang_Ref_Type *c) +{ + int status = 0; + + if (fits_get_keytype (card, &type, &status)) + return status; + switch (type) + { + case 'C': /* string */ + break; + + case 'L': /* logical */ + break; + + case 'I': /* integer */ + break; + + case 'F': /* floating point */ + break; + + case 'X': /* complex */ + break; + } +} +#endif + +static void get_version (void) +{ + float v; + (void) fits_get_version (&v); + (void) SLang_push_float (v); +} + +static int get_keyclass (char *card) +{ + return fits_get_keyclass (card); +} + +static int do_fits_fun_f(int (*fun)(fitsfile *, int *), FitsFile_Type *f) +{ + int status = 0; + + if (f->fptr == NULL) + return -1; + + (void) (*fun) (f->fptr, &status); + return status; +} + +static int write_chksum (FitsFile_Type *f) +{ + return do_fits_fun_f (fits_write_chksum, f); +} +static int update_chksum (FitsFile_Type *f) +{ + return do_fits_fun_f (fits_update_chksum, f); +} + +static int verify_chksum (FitsFile_Type *f, SLang_Ref_Type *dataok, SLang_Ref_Type *hduok) +{ + int status = 0; + int dok=0, hok=0; + + if (f->fptr == NULL) + return -1; + + if (0 == fits_verify_chksum (f->fptr, &dok, &hok, &status)) + { + if ((-1 == SLang_assign_to_ref (dataok, SLANG_INT_TYPE, (VOID_STAR)&dok)) + || (-1 == SLang_assign_to_ref (hduok, SLANG_INT_TYPE, (VOID_STAR)&hok))) + status = -1; + } + return status; +} + +static int get_chksum (FitsFile_Type *f, SLang_Ref_Type *datasum, SLang_Ref_Type *hdusum) +{ + int status = 0; + unsigned long dsum, hsum; + + if (f->fptr == NULL) + return -1; + + if (0 == fits_get_chksum (f->fptr, &dsum, &hsum, &status)) + { + if ((-1 == SLang_assign_to_ref (datasum, SLANG_ULONG_TYPE, (VOID_STAR)&dsum)) + || (-1 == SLang_assign_to_ref (hdusum, SLANG_ULONG_TYPE, (VOID_STAR)&hsum))) + status = -1; + } + return status; +} + +static int set_bscale (FitsFile_Type *f, double *scale, double *zero) +{ + int status = 0; + + if (f->fptr == NULL) + return -1; + + return fits_set_bscale (f->fptr, *scale, *zero, &status); +} + +static int set_tscale (FitsFile_Type *f, int *colp, double *scale, double *zero) +{ + int status = 0; + + if (f->fptr == NULL) + return -1; + + return fits_set_tscale (f->fptr, *colp, *scale, *zero, &status); +} + +/* DUMMY_FITS_FILE_TYPE is a temporary hack that will be modified to the true + * id once the interpreter provides it when the class is registered. See below + * for details. The reason for this is simple: for a module, the type-id + * must be assigned dynamically. + */ +#define DUMMY_FITS_FILE_TYPE 255 +#define I SLANG_INT_TYPE +#define S SLANG_STRING_TYPE +#define F DUMMY_FITS_FILE_TYPE +#define R SLANG_REF_TYPE +#define A SLANG_ARRAY_TYPE +#define T SLANG_DATATYPE_TYPE +#define D SLANG_DOUBLE_TYPE + + +static SLang_Intrin_Fun_Type Fits_Intrinsics [] = +{ + MAKE_INTRINSIC_0("_fits_clear_errmsg", clear_errmsg, SLANG_VOID_TYPE), + MAKE_INTRINSIC_0("_fits_read_errmsg", read_errmsg, SLANG_VOID_TYPE), + MAKE_INTRINSIC_I("_fits_get_errstatus", get_errstatus, SLANG_VOID_TYPE), + MAKE_INTRINSIC_3("_fits_open_file", open_file, I, R, S, S), + MAKE_INTRINSIC_1("_fits_delete_file", delete_file, I, F), + MAKE_INTRINSIC_1("_fits_close_file", close_file, SLANG_INT_TYPE, F), + + /* HDU Access Routines */ + MAKE_INTRINSIC_2("_fits_movabs_hdu", movabs_hdu, I, F, I), + MAKE_INTRINSIC_2("_fits_movrel_hdu", movrel_hdu, I, F, I), + MAKE_INTRINSIC_4("_fits_movnam_hdu", movnam_hdu, I, F, I, S, I), + MAKE_INTRINSIC_2("_fits_get_num_hdus", get_num_hdus, I, F, R), + MAKE_INTRINSIC_1("_fits_get_hdu_num", get_hdu_num, I, F), + MAKE_INTRINSIC_2("_fits_get_hdu_type", get_hdu_type, I, F, R), + MAKE_INTRINSIC_5("_fits_copy_file", copy_file, I, F, F, I, I, I), + MAKE_INTRINSIC_3("_fits_copy_hdu", copy_hdu, I, F, F, I), + MAKE_INTRINSIC_2("_fits_copy_header", copy_header, I, F, F), + MAKE_INTRINSIC_1("_fits_delete_hdu", delete_hdu, I, F), + + MAKE_INTRINSIC_3("_fits_create_img", create_img, I, F, I, A), + MAKE_INTRINSIC_2("_fits_write_img", write_img, I, F, A), + MAKE_INTRINSIC_2("_fits_read_img", read_img, I, F, R), + + /* Keword Writing Routines */ + MAKE_INTRINSIC_0("_fits_create_binary_tbl", create_binary_tbl, I), + MAKE_INTRINSIC_0("_fits_update_key", update_key, I), + MAKE_INTRINSIC_0("_fits_update_logical", update_logical, I), + MAKE_INTRINSIC_2("_fits_write_comment", write_comment, I, F, S), + MAKE_INTRINSIC_2("_fits_write_history", write_history, I, F, S), + MAKE_INTRINSIC_1("_fits_write_date", write_date, I, F), + MAKE_INTRINSIC_2("_fits_write_record", &write_record, I, F, S), + MAKE_INTRINSIC_3("_fits_insert_record", &insert_record, I, F, I, S), + + MAKE_INTRINSIC_3("_fits_modify_name", modify_name, I, F, S, S), + MAKE_INTRINSIC_2("_fits_get_num_keys", get_num_keys, I, F, R), + MAKE_INTRINSIC_0("_fits_read_key_integer", read_key_integer, I), + MAKE_INTRINSIC_0("_fits_read_key_string", read_key_string, I), + MAKE_INTRINSIC_0("_fits_read_key_double", read_key_double, I), + MAKE_INTRINSIC_0("_fits_read_key", read_generic_key, I), + MAKE_INTRINSIC_3("_fits_read_record", read_record, I, F, I, R), + + MAKE_INTRINSIC_2("_fits_delete_key", delete_key, I, F, S), + MAKE_INTRINSIC_3("_fits_get_colnum", get_colnum, I, F, S, R), + + MAKE_INTRINSIC_3("_fits_insert_rows", insert_rows, I, F, I, I), + MAKE_INTRINSIC_3("_fits_delete_rows", delete_rows, I, F, I, I), + + MAKE_INTRINSIC_4("_fits_insert_cols", insert_cols, I, F, I, A, A), + MAKE_INTRINSIC_2("_fits_delete_col", delete_col, I, F, I), + + MAKE_INTRINSIC_2("_fits_get_num_cols", get_num_cols, I, F, R), + MAKE_INTRINSIC_2("_fits_get_rowsize", get_rowsize, I, F, R), + MAKE_INTRINSIC_2("_fits_get_num_rows", get_num_rows, I, F, R), + MAKE_INTRINSIC_5("_fits_write_col", write_col, I, F, I, I, I, A), + MAKE_INTRINSIC_5("_fits_read_col", read_col, I, F, I, I, I, R), + MAKE_INTRINSIC_3("_fits_get_keytype", get_keytype, I, F, S, R), + MAKE_INTRINSIC_1("_fits_get_keyclass", get_keyclass, I, S), + + MAKE_INTRINSIC_0("_fits_read_cols", read_cols, I), + MAKE_INTRINSIC_3("_fits_set_bscale", set_bscale, I, F, D, D), + MAKE_INTRINSIC_4("_fits_set_tscale", set_tscale, I, F, I, D, D), + + /* checksum routines */ + MAKE_INTRINSIC_1("_fits_write_chksum", write_chksum, I, F), + MAKE_INTRINSIC_1("_fits_update_chksum", update_chksum, I, F), + MAKE_INTRINSIC_3("_fits_verify_chksum", verify_chksum, I, F, R, R), + MAKE_INTRINSIC_3("_fits_get_chksum", get_chksum, I, F, R, R), + + MAKE_INTRINSIC_0("_fits_get_version", get_version, SLANG_VOID_TYPE), + SLANG_END_INTRIN_FUN_TABLE +}; + +static SLang_IConstant_Type IConst_Table [] = +{ + MAKE_ICONSTANT("_FITS_BINARY_TBL", BINARY_TBL), + MAKE_ICONSTANT("_FITS_ASCII_TBL", ASCII_TBL), + MAKE_ICONSTANT("_FITS_IMAGE_HDU", IMAGE_HDU), + + MAKE_ICONSTANT("_FITS_SAME_FILE", SAME_FILE), + MAKE_ICONSTANT("_FITS_TOO_MANY_FILES", TOO_MANY_FILES), + MAKE_ICONSTANT("_FITS_FILE_NOT_OPENED", FILE_NOT_OPENED), + MAKE_ICONSTANT("_FITS_FILE_NOT_CREATED", FILE_NOT_CREATED), + MAKE_ICONSTANT("_FITS_WRITE_ERROR", WRITE_ERROR), + MAKE_ICONSTANT("_FITS_END_OF_FILE", END_OF_FILE), + MAKE_ICONSTANT("_FITS_READ_ERROR", READ_ERROR), + MAKE_ICONSTANT("_FITS_FILE_NOT_CLOSED", FILE_NOT_CLOSED), + MAKE_ICONSTANT("_FITS_ARRAY_TOO_BIG", ARRAY_TOO_BIG), + MAKE_ICONSTANT("_FITS_READONLY_FILE", READONLY_FILE), + MAKE_ICONSTANT("_FITS_MEMORY_ALLOCATION", MEMORY_ALLOCATION), + MAKE_ICONSTANT("_FITS_BAD_FILEPTR", BAD_FILEPTR), + MAKE_ICONSTANT("_FITS_NULL_INPUT_PTR", NULL_INPUT_PTR), + MAKE_ICONSTANT("_FITS_SEEK_ERROR", SEEK_ERROR), + MAKE_ICONSTANT("_FITS_BAD_URL_PREFIX", BAD_URL_PREFIX), + MAKE_ICONSTANT("_FITS_TOO_MANY_DRIVERS", TOO_MANY_DRIVERS), + MAKE_ICONSTANT("_FITS_DRIVER_INIT_FAILED", DRIVER_INIT_FAILED), + MAKE_ICONSTANT("_FITS_NO_MATCHING_DRIVER", NO_MATCHING_DRIVER), + MAKE_ICONSTANT("_FITS_URL_PARSE_ERROR", URL_PARSE_ERROR), + MAKE_ICONSTANT("_FITS_HEADER_NOT_EMPTY", HEADER_NOT_EMPTY), + MAKE_ICONSTANT("_FITS_KEY_NO_EXIST", KEY_NO_EXIST), + MAKE_ICONSTANT("_FITS_KEY_OUT_BOUNDS", KEY_OUT_BOUNDS), + MAKE_ICONSTANT("_FITS_VALUE_UNDEFINED", VALUE_UNDEFINED), + MAKE_ICONSTANT("_FITS_NO_QUOTE", NO_QUOTE), + MAKE_ICONSTANT("_FITS_BAD_KEYCHAR", BAD_KEYCHAR), + MAKE_ICONSTANT("_FITS_BAD_ORDER", BAD_ORDER), + MAKE_ICONSTANT("_FITS_NOT_POS_INT", NOT_POS_INT), + MAKE_ICONSTANT("_FITS_NO_END", NO_END), + MAKE_ICONSTANT("_FITS_BAD_BITPIX", BAD_BITPIX), + MAKE_ICONSTANT("_FITS_BAD_NAXIS", BAD_NAXIS), + MAKE_ICONSTANT("_FITS_BAD_NAXES", BAD_NAXES), + MAKE_ICONSTANT("_FITS_BAD_PCOUNT", BAD_PCOUNT), + MAKE_ICONSTANT("_FITS_BAD_GCOUNT", BAD_GCOUNT), + MAKE_ICONSTANT("_FITS_BAD_TFIELDS", BAD_TFIELDS), + MAKE_ICONSTANT("_FITS_NEG_WIDTH", NEG_WIDTH), + MAKE_ICONSTANT("_FITS_NEG_ROWS", NEG_ROWS), + MAKE_ICONSTANT("_FITS_COL_NOT_FOUND", COL_NOT_FOUND), + MAKE_ICONSTANT("_FITS_BAD_SIMPLE", BAD_SIMPLE), + MAKE_ICONSTANT("_FITS_NO_SIMPLE", NO_SIMPLE), + MAKE_ICONSTANT("_FITS_NO_BITPIX", NO_BITPIX), + MAKE_ICONSTANT("_FITS_NO_NAXIS", NO_NAXIS), + MAKE_ICONSTANT("_FITS_NO_NAXES", NO_NAXES), + MAKE_ICONSTANT("_FITS_NO_XTENSION", NO_XTENSION), + MAKE_ICONSTANT("_FITS_NOT_ATABLE", NOT_ATABLE), + MAKE_ICONSTANT("_FITS_NOT_BTABLE", NOT_BTABLE), + MAKE_ICONSTANT("_FITS_NO_PCOUNT", NO_PCOUNT), + MAKE_ICONSTANT("_FITS_NO_GCOUNT", NO_GCOUNT), + MAKE_ICONSTANT("_FITS_NO_TFIELDS", NO_TFIELDS), + MAKE_ICONSTANT("_FITS_NO_TBCOL", NO_TBCOL), + MAKE_ICONSTANT("_FITS_NO_TFORM", NO_TFORM), + MAKE_ICONSTANT("_FITS_NOT_IMAGE", NOT_IMAGE), + MAKE_ICONSTANT("_FITS_BAD_TBCOL", BAD_TBCOL), + MAKE_ICONSTANT("_FITS_NOT_TABLE", NOT_TABLE), + MAKE_ICONSTANT("_FITS_COL_TOO_WIDE", COL_TOO_WIDE), + MAKE_ICONSTANT("_FITS_COL_NOT_UNIQUE", COL_NOT_UNIQUE), + MAKE_ICONSTANT("_FITS_BAD_ROW_WIDTH", BAD_ROW_WIDTH), + MAKE_ICONSTANT("_FITS_UNKNOWN_EXT", UNKNOWN_EXT), + MAKE_ICONSTANT("_FITS_UNKNOWN_REC", UNKNOWN_REC), + MAKE_ICONSTANT("_FITS_END_JUNK", END_JUNK), + MAKE_ICONSTANT("_FITS_BAD_HEADER_FILL", BAD_HEADER_FILL), + MAKE_ICONSTANT("_FITS_BAD_DATA_FILL", BAD_DATA_FILL), + MAKE_ICONSTANT("_FITS_BAD_TFORM", BAD_TFORM), + MAKE_ICONSTANT("_FITS_BAD_TFORM_DTYPE", BAD_TFORM_DTYPE), + MAKE_ICONSTANT("_FITS_BAD_TDIM", BAD_TDIM), + MAKE_ICONSTANT("_FITS_BAD_HDU_NUM", BAD_HDU_NUM), + MAKE_ICONSTANT("_FITS_BAD_COL_NUM", BAD_COL_NUM), + MAKE_ICONSTANT("_FITS_NEG_FILE_POS", NEG_FILE_POS), + MAKE_ICONSTANT("_FITS_NEG_BYTES", NEG_BYTES), + MAKE_ICONSTANT("_FITS_BAD_ROW_NUM", BAD_ROW_NUM), + MAKE_ICONSTANT("_FITS_BAD_ELEM_NUM", BAD_ELEM_NUM), + MAKE_ICONSTANT("_FITS_NOT_ASCII_COL", NOT_ASCII_COL), + MAKE_ICONSTANT("_FITS_NOT_LOGICAL_COL", NOT_LOGICAL_COL), + MAKE_ICONSTANT("_FITS_BAD_ATABLE_FORMAT", BAD_ATABLE_FORMAT), + MAKE_ICONSTANT("_FITS_BAD_BTABLE_FORMAT", BAD_BTABLE_FORMAT), + MAKE_ICONSTANT("_FITS_NO_NULL", NO_NULL), + MAKE_ICONSTANT("_FITS_NOT_VARI_LEN", NOT_VARI_LEN), + MAKE_ICONSTANT("_FITS_BAD_DIMEN", BAD_DIMEN), + MAKE_ICONSTANT("_FITS_BAD_PIX_NUM", BAD_PIX_NUM), + MAKE_ICONSTANT("_FITS_ZERO_SCALE", ZERO_SCALE), + MAKE_ICONSTANT("_FITS_NEG_AXIS", NEG_AXIS), + + /* get_keyclass return value */ + MAKE_ICONSTANT("_FITS_TYP_STRUC_KEY",TYP_STRUC_KEY), + MAKE_ICONSTANT("_FITS_TYP_CMPRS_KEY",TYP_CMPRS_KEY), + MAKE_ICONSTANT("_FITS_TYP_SCAL_KEY", TYP_SCAL_KEY), + MAKE_ICONSTANT("_FITS_TYP_NULL_KEY", TYP_NULL_KEY), + MAKE_ICONSTANT("_FITS_TYP_DIM_KEY", TYP_DIM_KEY), + MAKE_ICONSTANT("_FITS_TYP_RANG_KEY", TYP_RANG_KEY), + MAKE_ICONSTANT("_FITS_TYP_UNIT_KEY", TYP_UNIT_KEY), + MAKE_ICONSTANT("_FITS_TYP_DISP_KEY", TYP_DISP_KEY), + MAKE_ICONSTANT("_FITS_TYP_HDUID_KEY",TYP_HDUID_KEY), + MAKE_ICONSTANT("_FITS_TYP_CKSUM_KEY",TYP_CKSUM_KEY), + MAKE_ICONSTANT("_FITS_TYP_WCS_KEY", TYP_WCS_KEY), + MAKE_ICONSTANT("_FITS_TYP_REFSYS_KEY",TYP_REFSYS_KEY), + MAKE_ICONSTANT("_FITS_TYP_COMM_KEY", TYP_COMM_KEY), + MAKE_ICONSTANT("_FITS_TYP_CONT_KEY", TYP_CONT_KEY), + MAKE_ICONSTANT("_FITS_TYP_USER_KEY", TYP_USER_KEY), + + + MAKE_ICONSTANT("_cfitsio_module_version", MODULE_VERSION_NUMBER), + + SLANG_END_ICONST_TABLE +}; + +static SLang_Intrin_Var_Type Intrin_Vars[] = +{ + MAKE_VARIABLE("_cfitsio_module_version_string", &Module_Version_String, SLANG_STRING_TYPE, 1), + SLANG_END_INTRIN_VAR_TABLE +}; + +static void patchup_intrinsic_table (void) +{ + SLang_Intrin_Fun_Type *f; + + f = Fits_Intrinsics; + while (f->name != NULL) + { + unsigned int i, nargs; + SLtype *args; + + nargs = f->num_args; + args = f->arg_types; + for (i = 0; i < nargs; i++) + { + if (args[i] == DUMMY_FITS_FILE_TYPE) + args[i] = Fits_Type_Id; + } + + /* For completeness */ + if (f->return_type == DUMMY_FITS_FILE_TYPE) + f->return_type = Fits_Type_Id; + + f++; + } +} + + +static void free_fits_file_type (SLtype type, VOID_STAR f) +{ + FitsFile_Type *ft; + int status = 0; + + (void) type; + + ft = (FitsFile_Type *) f; + if (ft->fptr != NULL) + fits_close_file (ft->fptr, &status); + + SLfree ((char *) ft); +} + +static int check_version (void) +{ + float compiled_version = 0; + float linked_version = 0; + float tol = 0.0001; + +#ifdef CFITSIO_VERSION + compiled_version = CFITSIO_VERSION; + (void) fits_get_version (&linked_version); +#endif + + if (fabs (linked_version - compiled_version) <= tol) + return 0; + + fprintf (stderr, "\n\ +***WARNING: The version of CFITSIO that this module is linked against (%g)\n\ + is not the same as the version it was compiled against (%g).\n\ + As the CFITSIO developers make no guarantees of binary compatibility,\n\ + you may experience problems with this module. You are stongly urged to\n\ + recompile the module.\n\n\ +", linked_version, compiled_version); + + return -1; +} + +int init_cfitsio_module_ns (char *ns_name) +{ + SLang_NameSpace_Type *ns; + + ns = SLns_create_namespace (ns_name); + if (ns == NULL) + return -1; + + if (Fits_Type_Id == 0) + { + SLang_Class_Type *cl; + + (void) check_version (); + + cl = SLclass_allocate_class ("Fits_File_Type"); + if (cl == NULL) return -1; + (void) SLclass_set_destroy_function (cl, free_fits_file_type); + + /* By registering as SLANG_VOID_TYPE, slang will dynamically allocate a + * type. + */ + if (-1 == SLclass_register_class (cl, SLANG_VOID_TYPE, + sizeof (FitsFile_Type), + SLANG_CLASS_TYPE_MMT)) + return -1; + + Fits_Type_Id = SLclass_get_class_id (cl); + patchup_intrinsic_table (); + } + + if (-1 == SLns_add_intrin_fun_table (ns, Fits_Intrinsics, "__CFITSIO__")) + return -1; + + if (-1 == SLns_add_iconstant_table (ns, IConst_Table, NULL)) + return -1; + + if (-1 == SLns_add_intrin_var_table (ns, Intrin_Vars, NULL)) + return -1; + + return 0; +} + diff --git a/modules/cfitsio/src/cfitsio.sl b/modules/cfitsio/src/cfitsio.sl new file mode 100644 index 0000000..0bafbfe --- /dev/null +++ b/modules/cfitsio/src/cfitsio.sl @@ -0,0 +1 @@ +import ("cfitsio"); diff --git a/modules/cfitsio/src/config.hin b/modules/cfitsio/src/config.hin new file mode 100644 index 0000000..4cfe151 --- /dev/null +++ b/modules/cfitsio/src/config.hin @@ -0,0 +1,15 @@ +/* -*- c -*- */ + +/* Define this if have stdlib.h */ +#undef HAVE_STDLIB_H + +/* Define this if you have unistd.h */ +#undef HAVE_UNISTD_H + +/* Set these to the appropriate values */ +#undef SIZEOF_SHORT +#undef SIZEOF_INT +#undef SIZEOF_LONG +#undef SIZEOF_FLOAT +#undef SIZEOF_DOUBLE + diff --git a/modules/cfitsio/src/fits.sl b/modules/cfitsio/src/fits.sl new file mode 100644 index 0000000..2c8269e --- /dev/null +++ b/modules/cfitsio/src/fits.sl @@ -0,0 +1,2031 @@ +% Copyright (C) 1998-2008 Massachusetts Institute of Technology +% +% Author: John E. Davis +% +% 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., 675 Mass Ave, Cambridge, MA 02139, USA. + +%if (current_namespace () != "") +% import ("cfitsio", current_namespace ()); +%else +import ("cfitsio"); + +variable _fits_sl_version = 404; +variable _fits_sl_version_string = "0.4.4-0"; + +private variable Verbose = 1; +% Forward declarations + +#ifexists new_exception +if (0 == is_defined ("FitsError")) + new_exception ("FitsError", RunTimeError, "Fits Error"); +#endif + +private variable Last_Error_Messages = String_Type[0]; + +private define reverse (a) +{ +#ifexists array_reverse + a = @a; + array_reverse (a); + return a; +#else + variable i = length (a); + if (i <= 1) + return a; + + i--; + __tmp(a)[[i:0:-1]]; +#endif +} + + +%!%+ +%\function{fits_read_errmsgs} +%\synopsis{Retrieve all error messages from the CFITSIO error stack} +%\usage{String_Type[] fits_read_errmsgs ()} +%\description +% This function returns all the error messages from the CFITSIO error +% message stack as an array of strings. +%\notes +% Using this function will cause the error message stack to be cleared. +%\seealso{_fits_read_errmsg, fits_set_verbose_errors} +%!%- +define fits_read_errmsgs () +{ + variable err; + variable errlist = String_Type[0]; + while (err = _fits_read_errmsg (), err != NULL) + { + errlist = [errlist, err]; + } + return errlist; +} + +define fits_get_errmsgs () +{ + return Last_Error_Messages; +} + + +%!%+ +%\function{fits_set_verbose_errors} +%\synopsis{Set the verbosity level of the cfitsio error messages} +%\usage{fits_set_verbose_errors (Int_Type level)} +%\description +% When a call to a function in the high-level interface fails, a error +% message will get generated. By default, all messages from the +% underlying cfitsio error stack are printed. This behavior may be +% turned off by calling this function with \exmp{level} equal to 0. +%\seealso{fits_read_errmsgs} +%!%- +define fits_set_verbose_errors () +{ + variable v = 1; + if (_NARGS) + v = (); + + Verbose = v; +} + +private define do_fits_error () +{ + variable status, file = ""; + + if (_NARGS == 2) + file = (); + status = (); + if (status == 0) + { + _fits_clear_errmsg (); + Last_Error_Messages = String_Type[0]; + return; + } + + if (strlen(file)) + file = strcat (": ", file); + variable errmsg = strcat (_fits_get_errstatus (status), file); + Last_Error_Messages = fits_read_errmsgs (); + if (Verbose) + errmsg = strjoin ([Last_Error_Messages, errmsg], "\n"); + +#ifexists new_exception + throw FitsError, errmsg, Last_Error_Messages; +#else + error (errmsg); +#endif +} + +%!%+ +%\function{fits_open_file} +%\synopsis{Open a fits file} +%\usage{Fits_File_Type fits_open_file (String_Type filename, String_Type mode)} +%\description +% The \var{fits_open_file} function can be used to open and existing fits +% file for reading or updating, or to create a new fits file, depending upon +% the value of the \var{mode} parameter. Specifically, if \var{mode} is +% \exmp{"r"}, the file will be opened for reading. If \var{mode} is \exmp{"w"}, +% the file will be opened for updating (both reading and writing). Otherwise, +% \var{mode} must be \var{"c"}, which indicates that a new file is to be created. +% In the latter case, if a file already exists with the specified name, it will +% get deleted and a new one created in its place. +% +% If the function fails, it will signal an error; otherwise an open file +% pointer will be returned. +%\seealso{fits_close_file, fits_create_binary_table} +%!%- +define fits_open_file () +{ + variable file, mode; + + if (_NARGS != 2) + usage ("fp = fits_open_file (file, \"r|w|c\")"); + + (file, mode) = (); + variable fp; + + variable status = _fits_open_file (&fp, file, mode); + if (status) + do_fits_error (status, file); + return fp; +} + + +%!%+ +%\function{fits_close_file} +%\synopsis{Close a fits file} +%\usage{fits_close_file (Fits_File_Type f)} +%\description +% The \var{fits_close_file} closes a previously opened fits file. The function +% will signal an error if the operation fails. +%\notes +% This function could fail if it fails to write out any buffered data because +% of filesystem errors (disk full, etc.). +%\seealso{fits_open_file} +%!%- +define fits_close_file (fp) +{ + do_fits_error (_fits_close_file (fp)); +} + +private define do_close_file (fp, needs_close) +{ + if (needs_close) + fits_close_file (fp); +} + +private define get_open_fp (fp, needs_close) +{ + @needs_close = 0; + if (typeof (fp) != Fits_File_Type) + { + variable file = fp; + do_fits_error (_fits_open_file (&fp, fp, "r"), file); + @needs_close = 1; + } + return fp; +} + + +private define find_interesting_hdu (f, hdu_type, check_naxis) +{ + variable type; + do + { + variable status; + + do_fits_error (_fits_get_hdu_type (f, &type)); + if (type == _FITS_ASCII_TBL) + type = _FITS_BINARY_TBL; + + if ((hdu_type == NULL) or (type == hdu_type)) + { + if (check_naxis == 0) + return 0; + + variable naxis; + do_fits_error (_fits_read_key (f, "NAXIS", &naxis, NULL)); + if (naxis != 0) + return 0; + } + + status = _fits_movrel_hdu (f, 1); + } + while (not status); + return -1; +} + + +private define get_open_hdu_of_type (f, hdu_type, needs_close, check_naxis) +{ + variable type; + variable type_str; + + switch (hdu_type) + { + case _FITS_BINARY_TBL: + type_str = "a binary table"; + } + { + case _FITS_IMAGE_HDU: + type_str = "an image"; + } + { + case _FITS_ASCII_TBL: + type_str = "an ascii table"; + } + { + % default + type_str = "an interesting hdu"; + } + + @needs_close = 0; + if (typeof (f) == Fits_File_Type) + { + do_fits_error (_fits_get_hdu_type (f, &type)); + if ((hdu_type == _FITS_BINARY_TBL) + and (type == _FITS_ASCII_TBL)) + hdu_type = type; + + if ((hdu_type != NULL) and (type != hdu_type)) + { + verror ("Extension is not %s", type_str); + } + return f; + } + + f = get_open_fp (f, needs_close); + + if (0 == find_interesting_hdu (f, hdu_type, check_naxis)) + return f; + + verror ("Unable to locate %s", type_str); +} + + +%!%+ +%\function{fits_move_to_interesting_hdu} +%\synopsis{Move to an extension that looks interesting} +%\usage{fits_move_to_interesting_hdu (fp [, hdu_type]} +%#v+ +% Fits_File_Type fp; +% Int_Type hdu_type; +%#v- +%\description +% The function move the fits file pointer \var{fp} forward to an HDU that looks +% interesting. By definition, an interesting HDU is one in which NAXIS is +% non-zero. The first parameter \var{fp} must be a pointer to an already open +% fits file. The second parameter, if present, may be used to specifiy the +% type of HDU, e.g., either an image (\exmp{hdu_type=_FITS_IMAGE_HDU}) or a +% binary table (\exmp{hdu_type=_FITS_BINARY_TBL}). +% +% If the function fails to find an interesting HDU of the appropriate type, +% an exception will be generated. +%\seealso{fits_open_file} +%!%- +define fits_move_to_interesting_hdu () +{ + variable f, hdu_type = NULL; + switch (_NARGS) + { + case 1: + f = (); + } + { + case 2: + (f, hdu_type) = (); + } + { + usage ("%s (f, hdu_type); % hdu_type = _FITS_IMAGE_HDU|_FITS_BINARY_TBL", + _function_name ()); + } + + if (-1 == find_interesting_hdu (f, hdu_type, 1)) + verror ("%s: Unable to find an interesting HDU", _function_name); +} + +private define get_open_binary_table (f, needs_close) +{ + return get_open_hdu_of_type (f, _FITS_BINARY_TBL, needs_close, 1); +} + +private define get_open_image_hdu (f, needs_close) +{ + return get_open_hdu_of_type (f, _FITS_IMAGE_HDU, needs_close, 1); +} + +private define get_open_interesting_hdu (fp, needs_close) +{ + if (needs_close == NULL) + { + variable nc; + needs_close = &nc; + } + + @needs_close = 0; + if (typeof (fp) == Fits_File_Type) + return fp; + + return get_open_hdu_of_type (fp, NULL, needs_close, 1); + %return get_open_binary_table (fp, needs_close); +} + + +%!%+ +%\function{fits_key_exists} +%\synopsis{Check for the existence of a keyword} +%\usage{Int_Type fits_key_exists (fd, key)} +%#v+ +% Fits_File_Type or String_Type fd; +% String_Type key; +%#v- +%\description +% The \var{fits_key_exists} function checks for the existence of a specified +% keyword in the file specified by the descriptor \var{fd}, which must specify +% the name of a file or an open file pointer. +% +% If the specified key exists, the function return \1, otherwise it returns \0. +%\seealso{fits_read_key, fits_read_header} +%!%- +define fits_key_exists () +{ + if (_NARGS != 2) + usage ("status = fits_key_exists (file, key)"); + + variable fp, key; + variable needs_close; + + (fp, key) = (); + fp = get_open_interesting_hdu (fp, &needs_close); + variable value; + variable status = _fits_read_key (fp, key, &value, NULL); + if (needs_close) fits_close_file (fp); + if (status == 0) + return 1; + + if (status == _FITS_KEY_NO_EXIST) + return 0; + + do_fits_error (status); +} + +private define get_fits_btable_info (fp) +{ + variable numrows, numcols, names, name, col; + + do_fits_error (_fits_get_num_rows (fp, &numrows)); + do_fits_error (_fits_get_num_cols (fp, &numcols)); + + names = String_Type [numcols]; + _for (1, numcols, 1) + { + col = (); + + do_fits_error (_fits_read_key_string (fp, "TTYPE"+string(col), &name, NULL)); + names [col-1] = name; + } + + return (numrows, names); +} + + +%!%+ +%\function{fits_get_colnum} +%\synopsis{Get the column numbers of specified columns} +%\usage{column_num = fits_get_colnum (fd, column_name)} +%#v+ +% Fits_File_Type or String_Type fd; +% String_Type column_name; +%#v- +%\description +% This function returns the column number of the column with the specified name. +% The file-descriptor \exmp{fd} must specify the name of a file, or an open +% fits file pointer. +%\seealso{fits_binary_table_column_exists} +%!%- +define fits_get_colnum () +{ + if (_NARGS != 2) + usage ("colnum = %s (file, column_name)", _function_name ()); + + variable f, column_names; (f, column_names) = (); + + variable needs_close; + f = get_open_binary_table (f, &needs_close); + + variable colnum; + do_fits_error (_fits_get_colnum (f, column_names, &colnum), column_names); + + do_close_file (f, needs_close); + return colnum; +} + + +%!%+ +%\function{fits_binary_table_column_exists} +%\synopsis{Check for the existence of a binary table column} +%\usage{Int_Type fits_binary_table_column_exists (fd, col)} +%#v+ +% Fits_File_Type or String_Type fd; +% String_Type col; +%#v- +%\description +% This function may be used to determine whether or not a named column +% exists in a binary table. The table is specified via the \var{fd} +% parameter which must either be the name of a file containing the binary +% table, or an file pointer. +% +% If the specified column exists, \1 will be returned; otherwise the function +% will return \0. +%\seealso{fits_key_exists, fits_open_file} +%!%- +define fits_binary_table_column_exists () +{ + if (_NARGS != 2) + usage ("status = %s (file, column_name)", _function_name ()); + + variable f, col; (f, col) = (); + + variable needs_close; + f = get_open_binary_table (f, &needs_close); + + variable names; + (,names) = get_fits_btable_info (f); + do_close_file (f, needs_close); + + col = strup (col); + names = array_map (String_Type, &strup, names); + return length (where (col == names)); +} + +private define get_tdim_string (fp, col) +{ + variable tdim = sprintf ("TDIM%d", col); + !if (fits_key_exists (fp, tdim)) + return NULL; + + do_fits_error (_fits_read_key (fp, tdim, &tdim, NULL), tdim); + return tdim; +} + +private define make_tdim_string (dims) +{ + variable i; + variable tdim = "("; + + dims = reverse (array_map (String_Type, &string, dims)); + return sprintf ("(%s)", strjoin (dims, ",")); +} + +private define convert_tdim_string (tdim, num_rows) +{ + tdim = strtrim (tdim, "()"); + tdim = reverse (strtok (tdim, " \t,")); + + tdim = array_map (Int_Type, &integer, tdim); + if (num_rows == -1) + return tdim; + + variable new_tdim = Int_Type[length(tdim)+1]; + new_tdim[0] = num_rows; + new_tdim[[1:]] = tdim; + return new_tdim; +} + + +private define check_vector_tdim (fp, first_row, col, data) +{ + variable tdim_col = sprintf ("TDIM%d", col); + + !if (fits_binary_table_column_exists (fp, tdim_col)) + return; + + do_fits_error (_fits_get_colnum (fp, tdim_col, &tdim_col)); + if (tdim_col == col) + return; + + variable len = length (data); + variable tdim; + + do_fits_error (_fits_read_col (fp, tdim_col, first_row, len, &tdim)); + if (_typeof (tdim) != String_Type) + return; + + _for (0, len-1, 1) + { + variable i = (); + reshape (data[i], convert_tdim_string (tdim[i], -1)); + } +} + +% FITS column and keyword names can begin with a number or have dashes. +% Bad Design. +private define normalize_names (names) +{ + names = @names; + _for (0, length (names)-1, 1) + { + variable i = (); + variable name = strlow (names[i]); +#iffalse + (name,) = strreplace (name, "-", "_", strlen (name)); +#else + name = strtrans (name, "^a-z0-9", "_"); +#endif + names[i] = name; + variable ch = name[0]; + if ((ch == '_') + or ((ch >= 'a') and (ch <= 'z'))) + continue; + names[i] = "_" + name; + } + return names; +} + +private define get_column_number (fp, col) +{ + if (typeof (col) == String_Type) + { + variable col_str = col; + do_fits_error (_fits_get_colnum (fp, col_str, &col), col_str); + return col; + } + return int (col); +} + +private define get_column_numbers (fp, args) +{ + variable column_nums = Int_Type[0]; + foreach (args) + { + variable arg = (); + variable col = arg.value; + if (typeof (col) == Array_Type) + col = array_map (Int_Type, &get_column_number, fp, col); + else + col = get_column_number (fp, col); + + column_nums = [column_nums, col]; + } + return column_nums; +} + +% This function assumes that fp is an open pointer, and that columns is +% an array of column numbers. The data are left on the stack. +private define read_cols (fp, columns, first_row, last_row) +{ + variable numrows; + do_fits_error (_fits_get_num_rows (fp, &numrows)); + + if (first_row < 0) + first_row += (1+numrows); + if (last_row < 0) + last_row += (1+numrows); + + variable want_num_rows = last_row - first_row + 1; + if ((first_row <= 0) or (last_row < 0) + or (want_num_rows > numrows) or (want_num_rows < 0)) + throw FitsError, "Invalid first or last row parameters"; + + variable numcols = length (columns); + variable data_arrays; + do_fits_error (_fits_read_cols (fp, columns, first_row, want_num_rows, &data_arrays)); + _for (0, numcols-1, 1) + { + variable i = (); + variable col = columns[i]; + variable data = data_arrays[i]; + variable tdim = get_tdim_string (fp, col); + if (tdim != NULL) + { + tdim = convert_tdim_string (tdim, numrows); + reshape (data, tdim); + } + else if (typeof (data) == Array_Type) + check_vector_tdim (fp, first_row, col, data); + + data; % leave it on stack + } +} + +%!%+ +%\function{fits_read_col} +%\synopsis{Read one or more columns from a FITS binary table} +%\usage{(x1, ...xN) = fits_read_col (file, c1, ... cN)} +%#v+ +% Fits_File_Type or String_Type file; +% Int_Type or String_Type c1, ...cN; +%#v- +%\description +% This function returns one or more vectors containing objects in the +% specified columns of the binary table indicated by \var{file}. If +% \var{file} is a string, then the file will be opened via the virtual +% file specification implied by \var{file}. Otherwise, \var{file} +% should represent an already opened FITS file. The column parameters +% may either be strings denoting the column names, or integers +% representing the column numbers. +%\seealso{fits_read_cell, fits_read_row, fits_read_table} +%!%- +define fits_read_col () +{ + if (_NARGS < 2) + usage ("(x1...xN) = fits_read_col (file, c1, ...cN)"); + + variable fp, col; + variable numrows; + variable columns = __pop_args (_NARGS-1); + fp = (); + + variable needs_close; + fp = get_open_binary_table (fp, &needs_close); + + columns = get_column_numbers (fp, columns); + + read_cols (fp, columns, 1, -1); % data on stack + + do_close_file (fp, needs_close); +} + +%!%+ +%\function{fits_read_col_struct} +%\synopsis{Read one or more columns from a FITS binary table} +%\usage{struct = fits_read_col_struct (file, col1, ...)} +%#v+ +% Fits_File_Type or String_Type file; +% String_Type col1, ...; +%#v- +%\description +% This function works exactly like \var{fits_read_col} except it returns the +% values in a structure. See the documentation on that function for more +% information. +% +%\seealso{fits_read_col, fits_read_key_struct, fits_read_row, fits_read_header} +%!%- +define fits_read_col_struct () +{ + !if (_NARGS) + usage ("struct = fits_read_col_struct(file, COL1, ...)"); + + variable cols = __pop_args (_NARGS - 1); + variable file = (); + variable fields = normalize_names ([__push_args(cols)]); + variable s = @Struct_Type (fields); + set_struct_fields (s, fits_read_col (file, __push_args (cols))); + return s; +} + +%!%+ +%\function{fits_read_cell} +%\synopsis{Read a cell from a FITS binary table} +%\usage{X = fits_read_cell (file, c, r)} +%#v+ +% Fits_File_Type or String_Type file; +% Int_Type r, c; +%#v- +%\description +% This function returns the object in the column \var{c} and row +% \var{r} of the binary table indicated by \var{file}. If \var{file} +% is a string, then the file will be opened via the virtual file +% specification implied by \var{file}. Otherwise, \var{file} should +% represent an already opened FITS file. +%\seealso{fits_read_col, fits_read_row} +%!%- +define fits_read_cell () +{ + variable fp, r, c; + variable needs_close; + + if (_NARGS != 3) + usage ("x = fits_read_cell (file, c, r)"); + + (fp, c, r) = (); + fp = get_open_binary_table (fp, &needs_close); + + variable a = read_cols (fp, get_column_number (fp, c), r, r); + variable dims, nd; (dims,nd,) = array_info (a); + if (nd == 1) + a = a[0]; + else + reshape (a, dims[[1:]]); + + do_close_file (fp, needs_close); + return a; +} + +define fits_read_cells () +{ + variable fp, r0, r1, columns; + variable needs_close; + + if (_NARGS < 4) + usage ("(x1,...xN) = %s (file, col1, ..., colN, r0, r1)", _function_name); + + (r0, r1) = (); + columns = __pop_args (_NARGS-3); + fp = (); + fp = get_open_binary_table (fp, &needs_close); + + columns = get_column_numbers (fp, columns); + read_cols (fp, columns, r0, r1); % on stack + do_close_file (fp, needs_close); +} + +%!%+ +%\function{fits_read_row} +%\synopsis{Read a row from a FITS binary table} +%\usage{Struct_Type fits_read_cell (file, r)} +%#v+ +% Fits_File_Type or String_Type file; +% Int_Type r; +%#v- +%\description +% This function returns a structure containing the data in the columns +% of the row \var{r} of the binary table indicated by \var{file}. If +% \var{file} is a string, then the file will be opened via the virtual +% file specification implied by \var{file}. Otherwise, \var{file} +% should represent an already opened FITS file. +%\seealso{fits_read_col, fits_read_cell} +%!%- +define fits_read_row () +{ + verror ("Not yet implemented"); +} + + +%!%+ +%\function{fits_read_header} +%\synopsis{Read a FITS header} +%\usage{Struct_Type fits_read_header (file)} +%#v+ +% Fits_File_Type or String_Type file; +%#v- +%\description +% This function reads the header of the fits file given by the +% \var{file} parameter and returns it as a structure. If \var{file} is +% a string, then the file will be opened via the virtual file +% specification implied by \var{file}. Otherwise, \var{file} should +% represent an already opened FITS file. +%\seealso{fits_read_table} +%!%- +define fits_read_header () +{ + !if (_NARGS) + usage ("Struct_Type fits_read_header (file)"); + + verror ("Not implemented"); + + variable fp = (); + variable needs_close; + fp = get_open_fp (fp, &needs_close); + do_close_file (fp, needs_close); +} + + +%!%+ +%\function{fits_read_table} +%\synopsis{Read a FITS table} +%\usage{Struct_Type fits_read_table (file [,columns...])} +%#v+ +% Fits_File_Type or String_Type file; +%#v- +%\description +% \var{fits_read_table} reads the data in a table of the FITS file +% specified by \var{file} and returns it as a structure. If the optional +% column name parameters are specified, then only those columns will be read. +% Otherwise, the entire table will be returned. +% +% If \var{file} is a string, then the file will be opened via the virtual file +% specification implied by \var{file}. Otherwise, \var{file} should +% represent an already opened FITS file. +%\seealso{fits_read_col, fits_read_cell, fits_read_row, fits_read_header} +%!%- +define fits_read_table () +{ + if (_NARGS == 0) + usage ("S = fits_read_table (FILE [,columns,...])"); + + variable f, names = NULL; + if (_NARGS > 1) + { + names = __pop_args (_NARGS-1); + names = [__push_args(names)]; + } + f = (); + variable needs_close; + f = get_open_binary_table (f, &needs_close); + + if (names == NULL) + (, names) = get_fits_btable_info (f); + + variable s = fits_read_col_struct (f, names); + do_close_file (f, needs_close); + return s; +} + +define fits_info () +{ + !if (_NARGS) + %usage ("(numrows, numcols, colnames[]) = fits_info (file);"); + usage ("fits_info (file);"); + variable file = (); + + variable fp; + variable numrows, numcols, names; + variable needs_close; + + %do_fits_error (_fits_open_file (&fp, file, "r")); + fp = get_open_interesting_hdu (file, &needs_close); + + (numrows, names) = get_fits_btable_info (fp); + numcols = length (names); + + () = fprintf (stdout, "%s contains %d rows and %d columns:\n", file, numrows, numcols); + _for (1, numcols, 1) + { + variable i = (); + variable tform, name; + + name = names[i-1]; + do_fits_error (_fits_read_key_string (fp, "TFORM" + string(i), &tform, NULL)); + variable tdim = get_tdim_string (fp, i); + if (tdim == NULL) tdim = ""; + else tdim = "TDIM=" + tdim; + () = fprintf (stdout, "[%2d] %s %s %s\n", i, name, tform, tdim); + } + do_close_file (fp, needs_close); + + %return (numrows, numcols, names); +} + + +%!%+ +%\function{fits_read_key} +%\synopsis{Read one or more keywords from a FITS file} +%\usage{(val1,...) = fits_read_key (file, key1, ...)} +%#v+ +% Fits_File_Type or String_Type file; +% String_Type key1, ...; +%#v- +%\description +% \var{fits_read_key} reads the values of one or more keywords in the fits +% file specified by \var{file} and returns them. If \var{file} +% is a string, then the file will be opened via the virtual file +% specification implied by \var{file}. Otherwise, \var{file} should +% represent an already opened FITS file. If any of the keywords do not exist, +% a value of \NULL will be returned for the corresponding keyword. +%\seealso{fits_read_key_struct, fits_read_col, fits_read_cell, fits_read_row, fits_read_header} +%!%- +define fits_read_key () +{ + !if (_NARGS) + usage ("(x,...) = fits_read_key (file, X_KEY, ...)"); + + variable fp, keys; + + keys = __pop_args (_NARGS - 1); + fp = (); + + variable needs_close; + fp = get_open_interesting_hdu (fp, &needs_close); + + foreach (keys) + { + variable key = ().value; + variable value, status; + status = _fits_read_key (fp, key, &value, NULL); + if (status == _FITS_KEY_NO_EXIST) + { + value = NULL; + _fits_clear_errmsg (); + } + else if (status) + do_fits_error (status, key); + + value; + } + do_close_file (fp, needs_close); +} + + +%!%+ +%\function{fits_read_key_struct} +%\synopsis{Read one or more keywords from a FITS file} +%\usage{struct = fits_read_key_struct (file, key1, ...)} +%#v+ +% Fits_File_Type or String_Type file; +% String_Type key1, ...; +%#v- +%\description +% This function works exactly like \var{fits_read_key} excepts returns the +% values in a structure. See the documentation on that function for more +% information. +%\seealso{fits_read_key, fits_read_col, fits_read_cell, fits_read_row, fits_read_header} +%!%- +define fits_read_key_struct () +{ + !if (_NARGS) + usage ("struct = fits_read_key_struct(file, X_KEY, ...)"); + + variable keys = __pop_args (_NARGS - 1); + variable file = (); + variable fields = normalize_names ([__push_args(keys)]); + variable s = @Struct_Type (fields); + set_struct_fields (s, fits_read_key (file, __push_args (keys))); + return s; +} + + + +private define get_open_write_fp (fp, mode, needs_close) +{ + @needs_close = 0; + if (typeof (fp) != Fits_File_Type) + { + @needs_close = 1; + do_fits_error (_fits_open_file (&fp, fp, mode)); + } + + return fp; +} + +%!%+ +%\function{fits_create_binary_table} +%\synopsis{Prepare a binary table} +%\usage{fits_create_binary_table (file, extname, nrows, ttype, tform, tunit)} +%#v+ +% Fits_File_Type or String_Type file; +% String_Type extname; +% Int_Type nrows; +% String_Type ttype[]; +% String_Type tform[]; +% String_Type tunit[]; +%#v- +%\description +% This creates a new binary table with the specified structure. The parameters +% \var{ttype}, \var{tform}, and \var{tunit} are string arrays that specify +% the column names, column data type, and column units, respectively. +% The binary table will be given the extension name \var{extname}. +%\seealso{fits_write_binary_table, fits_open_file} +%!%- +define fits_create_binary_table () +{ + if (_NARGS != 6) + usage ("fits_create_binary_table (file, extname, nrows, ttype[], tform[], tunit[])"); + + variable fp, nrows, ttype, tform, tunit, extnam; + + (fp, extnam, nrows, ttype, tform, tunit) = (); + + variable needs_close; + fp = get_open_write_fp (fp, "c", &needs_close); + + do_fits_error (_fits_create_binary_tbl (fp, nrows, ttype, tform, tunit, extnam)); + do_close_file (fp, needs_close); +} + +%!%+ +%\function{fits_write_binary_table} +%\synopsis{Write a binary table} +%\usage{fits_write_binary_table (file, extname, sdata, [skeys [,hist]])} +%#v+ +%Fits_File_Type or String_Type file; +%String_Type extname; +%Struct_Type sdata; +%Struct_Type skeys; +%Struct_Type hist; +%#v- +%\description +% The \var{fits_write_binary_table} function creates a new binary table in +% the specified file. The parameter \var{file} specifies either a filename or +% an open file pointer. The \var{extname} parameter specifies the extension +% name of the binary table. The data written to table are specified in the +% \var{sdata} structure, where the name of the structure field specifies the +% column name. If \var{skeys} is non-NULL, then it is a structure indicating +% additional keywords to be written to the header of the binary table. If the +% optional parameter \var{hist} is present and non-NULL, then it is a structure +% whose fields indicate either comment or history information to be written +% to the header. +%\example +% The following code +%#v+ +% variable data = struct { x, cosx, sinx }; +% data.x = [0:2*PI:0.01]; +% data.cosx = cos(data.x); +% data.sinx = sin(data.x); +% +% variable keys = struct { hduname, username}; +% keys.hduname = "COSXSINX"; +% keys.username = "John Doe"; +% +% variable hist = struct { history, comment}; +% hist.history = ["This is a history record", "This is another"]; +% hist.comment = ["This is a comment", "And this is another"]; +% +% fits_write_binary_table ("foo.fits", "COSXSINX", data, keys, hist); +%#v- +% produces a binary table with the header: +%#v+ +% XTENSION= 'BINTABLE' / binary table extension +% BITPIX = 8 / 8-bit bytes +% NAXIS = 2 / 2-dimensional binary table +% NAXIS1 = 24 / width of table in bytes +% NAXIS2 = 629 / number of rows in table +% PCOUNT = 0 / size of special data area +% GCOUNT = 1 / one data group (required keyword) +% TFIELDS = 3 / number of fields in each row +% TTYPE1 = 'x ' / label for field 1 +% TFORM1 = 'D ' / data format of field: 8-byte DOUBLE +% TTYPE2 = 'cosx ' / label for field 2 +% TFORM2 = 'D ' / data format of field: 8-byte DOUBLE +% TTYPE3 = 'sinx ' / label for field 3 +% TFORM3 = 'D ' / data format of field: 8-byte DOUBLE +% EXTNAME = 'COSXSINX' / name of this binary table extension +% HDUNAME = 'COSXSINX' +% USERNAME= 'John Doe' +% HISTORY This is a history record +% HISTORY This is another +% COMMENT This is a comment +% COMMENT And this is another +%#v- +%\notes +% This function provides no mechanism to mix comments and keyword records. As +% the example shows, this function places the comment and history records at +% the end of the table. +%\seealso{fits_create_binary_table, fits_open_file} +%!%- + +private define add_keys_and_history_func (fp, keys, history) +{ + variable val; + if (keys != NULL) + { + foreach (get_struct_field_names (keys)) + { + variable keyword = (); + val = get_struct_field (keys, keyword); + do_fits_error (_fits_update_key (fp, keyword, val, NULL), keyword); + } + } + + if (typeof (history) == String_Type) + { + history; + history = struct {history}; + history.history = (); + } + + if (history == NULL) + return; + + foreach (get_struct_field_names (history)) + { + keyword = (); + val = get_struct_field (history, keyword); + if (typeof (val) == String_Type) + val = [val]; + keyword = strlow (keyword); + foreach (val) + { + val = (); + if (keyword == "history") + { + do_fits_error (_fits_write_history (fp, val)); + continue; + } + if (keyword == "comment") + { + do_fits_error (_fits_write_comment (fp, val)); + continue; + } + vmessage ("*** WARNING: history/comment record name '%s' is not supported", + history); + } + } +} + +private define shape_columns_before_write (s, ncols, ttype) +{ + variable reshapes_to = Array_Type[ncols]; + variable ndims, dims; + + _for (0, ncols-1, 1) + { + variable i = (); + variable val = get_struct_field (s, ttype[i]); + (dims,ndims,) = array_info (val); + if (ndims > 1) + { + variable dim_0 = dims[0]; + if (dim_0 != 0) + { + reshape (val, [dim_0, length(val)/dim_0]); + reshapes_to[i] = dims; + } + } + } + return reshapes_to; +} + +private define unshape_columns_after_write (s, ncols, ttype, reshapes_to) +{ + _for (0, ncols-1, 1) + { + variable i = (); + if (reshapes_to[i] == NULL) + continue; + + reshape (get_struct_field (s, ttype[i]), reshapes_to[i]); + } +} + +define fits_write_binary_table () +{ + variable fp, extname, s, keys, history; + variable needs_close; + variable keyfunc, keyfunc_args; + + variable usage_str = "\n" + + "Form 1: fits_write_binary_table (file, extname, data_struct [,opt-keyword_struct [,opt-history]])\n" + + "Form 2: fits_write_binary_table (file, extname, data_struct, &keyfunc [,opt-args...])"; + + if (_NARGS < 3) + usage (usage_str); + + keyfunc = NULL; + if (_NARGS > 3) + { + _stk_reverse (_NARGS - 3); + keyfunc = (); + _stk_reverse (_NARGS - 4); + + if (typeof (keyfunc) != Ref_Type) + { + % keyfunc must be the keys struct + if (_NARGS == 4) + history = NULL; + else if (_NARGS == 5) + history = (); + else + { + _pop_n (_NARGS); + usage (usage_str); + } + (keyfunc, history); % put back on stack + keyfunc_args = __pop_args (2); + keyfunc = &add_keys_and_history_func; + } + else + keyfunc_args = __pop_args (_NARGS - 4); + } + + (fp, extname, s) = (); + + fp = get_open_write_fp (fp, "c", &needs_close); + + variable ttype; + if (s == NULL) + ttype = String_Type[0]; + else + ttype = get_struct_field_names (s); + variable ncols = length (ttype); + variable tform = String_Type [ncols]; + variable nrows = -1; + variable tdim = String_Type[ncols]; + + _for (0, ncols-1, 1) + { + variable i = (); + variable colname = ttype[i]; + variable val = get_struct_field (s, colname); + + if (colname[0] == '_') % unnormalize + colname = substr (colname, 2, -1); + + variable t = _typeof (val); + variable ndims; + + switch (t) + { + case Int32_Type: t = "J"; + } + { + case Float_Type: t = "E"; + } + { + case Double_Type: t = "D"; + } + { + case Int16_Type: t = "I"; + } + { + case UInt16_Type: t = "U"; + } + { + case UInt32_Type: t = "V"; + } + { + case String_Type: + (,ndims,) = array_info (val); + if (ndims > 1) + verror ("This function does not support %d-d strings", ndims); + + t = sprintf ("%dA", max (array_map (Int_Type, &strlen, val))); + if (t == "0A") t = "1A"; + } + { + case Char_Type or case UChar_Type: + t = "B"; + } + { + verror ("%s: %s column: %S type not supported", _function_name, colname, t); + } + + variable nrows_i = length (val); + if ((typeof (val) == Array_Type) + and nrows_i) + { + variable tdim_i; + (tdim_i,ndims,) = array_info (val); + + if (ndims > 1) + { + t = string (nrows_i/tdim_i[0]) + t; + tdim[i] = make_tdim_string (tdim_i[[1:]]); + nrows_i = tdim_i[0]; + } + } + + if (nrows != nrows_i) + { + if (nrows != -1) + verror ("Expecting field %s to have %d rows", ttype[i], nrows); + nrows = nrows_i; + } + + tform[i] = t; + ttype[i] = colname; + } + + if (nrows == -1) % ncols is 0 + nrows = 0; + fits_create_binary_table (fp, extname, nrows, ttype, tform, NULL); + + _for (0, ncols-1, 1) + { + i = (); + if (NULL != tdim[i]) + do_fits_error (_fits_update_key (fp, sprintf("TDIM%d", i+1), tdim[i], NULL)); + } + + if (keyfunc != NULL) + (@keyfunc)(fp, __push_args(keyfunc_args)); + +#iffalse + _for (0, ncols-1, 1) + { + i = (); + val = get_struct_field (s, ttype[i]); + do_fits_error (_fits_write_col (fp, i+1, 1, 1, val)); + } +#else + + variable reshapes_to = shape_columns_before_write (s, ncols, ttype); + +# ifeval (_slang_version >= 20000) + try + { +# else + ERROR_BLOCK + { + unshape_columns_after_write (s, ncols, ttype, reshapes_to); + } +# endif + variable r = 0; + variable drows = 10; + while (r < nrows) + { + variable r1 = r + nrows; + if (r1 > nrows) + r1 = nrows; + + variable k = [r:r1-1]; + + _for (0, ncols-1, 1) + { + i = (); + val = get_struct_field (s, ttype[i]); + if (reshapes_to[i] == NULL) + do_fits_error (_fits_write_col (fp, i+1, r+1, 1, val[k])); + else + do_fits_error (_fits_write_col (fp, i+1, r+1, 1, val[k,*])); + } + r = r1; + } +#ifeval (_slang_version >= 20000) + } + finally + { + unshape_columns_after_write (s, ncols, ttype, reshapes_to); + } +#endif + + do_close_file (fp, needs_close); +} + + +private define do_write_xxx (func, nargs) +{ + variable args = __pop_args (nargs-1); + variable fp = (); + + variable needs_close; + fp = get_open_write_fp (fp, "w", &needs_close); + + if (nargs > 1) + do_fits_error ((@func)(fp, __push_args(args))); + else + do_fits_error ((@func)(fp)); + + do_close_file (fp, needs_close); +} + +private define do_read_xxx (func, nargs) +{ + variable args = __pop_args (nargs-1); + variable fp = (); + + variable needs_close; + fp = get_open_fp (fp, &needs_close); + + if (nargs > 1) + do_fits_error ((@func)(fp, __push_args(args))); + else + do_fits_error ((@func)(fp)); + + do_close_file (fp, needs_close); +} + + +%!%+ +%\function{fits_update_key} +%\synopsis{Update the value of a keyword} +%\usage{fits_update_key (fd, key, val [,comment])} +%#v+ +% String_Type or Fits_File_Type fd; +% String_Type key; +% Any type val; +% String_Type comment; +%#v- +%\description +% The \var{fits_update_key} function updates the value and comment fields +% of an existing keyword with the specified name. If the keyword does not +% exist, a new keyword will be appended to the end of the header. +%\seealso{fits_update_logical, fits_read_key} +%!%- +define fits_update_key () +{ + variable nargs = _NARGS; + if (nargs < 3) + usage ("fits_update_key (fp, key, value, comment)"); + + if (nargs == 3) + { + NULL; % add comment + nargs++; + } + + do_write_xxx (&_fits_update_key, nargs); +} + +%!%+ +%\function{fits_update_logical} +%\synopsis{Update the value of a logical (boolean) keyword} +%\usage{fits_update_logical (fd, key, val, comment)} +%#v+ +% String_Type or Fits_File_Type fd; +% String_Type key; +% Any type val; +% String_Type comment; +%#v- +%\description +% The \var{fits_update_logical} function updates the value and comment fields +% of an existing keyword of the specified name with the specified boolean value. +% If the keyword does not exist, a new keyword will be appended to the end of +% the header. +%\seealso{fits_update_key} +%!%- +define fits_update_logical () +{ + if (_NARGS != 4) + usage ("fits_update_logical (fp, key, value, comment)"); + + do_write_xxx (&_fits_update_logical, _NARGS); +} + +%!%+ +%\function{fits_write_comment} +%\synopsis{Write a comment to the header} +%\usage{fits_write_comment (fd, comment)} +%#v+ +% Fits_File_Type or String_Type fd; +% String_Type comment; +%#v- +%\description +% As the name indicates, this function writes a comment record to the specified +% fits file. The file-descriptor \exmp{fd} must either be the name of a fits +% file or an open fits file pointer. +%\seealso{fits_update_key, fits_write_history} +%!%- +define fits_write_comment () +{ + if (_NARGS != 2) + usage ("fits_write_comment (fp, value)"); + + do_write_xxx (&_fits_write_comment, _NARGS); +} + +%!%+ +%\function{fits_write_history} +%\synopsis{Write a history record to the header} +%\usage{fits_write_history (fd, history)} +%#v+ +% Fits_File_Type or String_Type fd; +% String_Type history; +%#v- +%\description +% As the name indicates, this function writes a history record to the specified +% fits file. The file-descriptor \exmp{fd} must either be the name of a fits +% file or an open fits file pointer. +%\seealso{fits_update_key, fits_write_comment} +%!%- +define fits_write_history () +{ + if (_NARGS != 2) + usage ("fits_write_history (fp, value)"); + + do_write_xxx (&_fits_write_history, _NARGS); +} + +%!%+ +%\function{fits_write_date} +%\synopsis{Write the DATE keyword to the current HDU} +%\usage{fits_write_date (fd)} +%#v+ +% Fits_File_Type or String_Type fd; +%#v- +%\description +% The \sfun{fits_write_date} function calls \ifun{_fits_write_date} to write +% the DATE to the header of the specified file descriptor, which must either +% be the name of a fits file or an open fits file pointer. +%\seealso{fits_update_key} +%!%- +define fits_write_date () +{ + if (_NARGS != 1) + usage ("fits_write_date (fp)"); + do_write_xxx (&_fits_write_date, _NARGS); +} + +%!%+ +%\function{fits_write_chksum} +%\synopsis{Compute and write the DATASUM and CHECKSUM keywords} +%\usage{fits_write_chksum (fd)} +%#v+ +% Fits_File_Type or String_Type fd; +%#v- +%\description +% The \sfun{fits_write_chksum} function calls \ifun{_fits_write_comment} to +% compute and write the DATASUM and CHECKSUM keywords to the +% header of the specified file descriptor, which must either +% be the name of a fits file or an open fits file pointer. +%\seealso{fits_update_key, fits_verify_chksum} +%!%- +define fits_write_chksum () +{ + if (_NARGS != 1) + usage ("fits_write_chksum (fp)"); + do_write_xxx (&_fits_write_chksum, _NARGS); +} + +%!%+ +%\function{fits_verify_chksum} +%\synopsis{Verify the checksums for the current HDU} +%\usage{isok = fits_verify_chksum (fd [,dataok, hduok])} +%#v+ +% Fits_File_Type or String_Type fd; +% Ref_Type dataok, hduok; +%#v- +%\description +% The \sfun{fits_verify_chksum} function calls \ifun{_fits_verify_chksum} to +% verify the header and data checksums of the current HDU. A non-zero return value +% signifies that the checksums are ok, otherwise the function returns 0 to indicate +% that the checksums are invalid. The individual checksums of the HDU or data +% can be checked through the use of the optional parameters. +%\seealso{fits_write_chksum} +%!%- +define fits_verify_chksum () +{ + variable dataok_buf, hduok_buf; + variable dataok = &dataok_buf, hduok = &dataok_buf; + + if (_NARGS == 3) + (dataok, hduok) = (); + else if (_NARGS != 1) + usage ("ok = fits_verify_chksum (fp [,&dataok, &hduok])"); + + if (dataok == NULL) + dataok = &dataok_buf; + if (hduok == NULL) + hduok = &hduok_buf; + + &dataok, &hduok; % push + + do_read_xxx (&_fits_verify_chksum, 3); + + return min([@dataok, @hduok]); +} + +%!%+ +%\function{fits_read_records} +%\synopsis{Read all the records in a fits header} +%\usage{String_Type[] fits_read_records (Fits_File_Type or String_Type fp)} +%\description +% This function returns a list of all the header records associated with the +% fits file descriptor as an array of strings. +%\seealso{fits_write_records, fits_read_key} +%!%- +define fits_read_records () +{ + if (_NARGS != 1) + usage ("String_Type[] fits_read_records (fp)"); + + variable fp = (); + fp = get_open_interesting_hdu (fp, NULL); + + variable nkeys; + do_fits_error (_fits_get_num_keys (fp, &nkeys)); + + variable recs = String_Type [nkeys]; + _for (0, nkeys-1, 1) + { + variable i = (); + variable rec; + + do_fits_error (_fits_read_record (fp, i+1, &rec)); + recs[i] = rec; + } + return recs; +} + +%!%+ +%\function{fits_write_records} +%\synopsis{Write records to fits header} +%\usage{fits_write_records (fd, records)} +%#v+ +% Fits_File_Type or String_Type fd; +% Array_Type records; +%#v- +%\description +% This function uses the \ifun{_fits_write_record} function to write a series +% of records to the current HDU. +%\seealso{fits_read_records} +%!%- +define fits_write_records () +{ + if (_NARGS != 2) + usage ("fits_write_records (fp, records[])"); + + variable fp, records; + (fp, records) = (); + + variable needs_close; + fp = get_open_write_fp (fp, "w", &needs_close); + + if (String_Type == typeof (records)) + records = [records]; + + foreach (records) + { + variable rec = (); + do_fits_error (_fits_write_record (fp, rec)); + } + do_close_file (fp, needs_close); +} + + +%!%+ +%\function{fits_get_keyclass} +%\synopsis{Obtain the key classes for a set of cards} +%\usage{Int_Type[] = fits_get_keyclass (Array_Type cards)} +%\description +% This function uses the \ifun{_fits_get_keyclass} function to obtain the +% key-classes associated with one or more cards. The function returns an +% integer-valued array of the same length as the \exmp{cards} array. +%\example +% Obtain set of header cards to those that are not associated with the cards +% describing the structure of the HDU: +%#v+ +% variable cards = fits_read_records ("evt2.fits[EVENTS]"); +% variable classes = fits_get_keyclass (cards); +% cards = cards[where (classes != _FITS_TYP_STRUC_KEY)]; +%#v- +%\seealso{fits_read_records, fits_read_key} +%!%- +define fits_get_keyclass () +{ + if (_NARGS != 1) + usage ("Int_Type[] = fits_get_keyclass (records)"); + + variable records = (); + if (String_Type == typeof (records)) + return _fits_get_keyclass (records); + + return array_map (Int_Type, &_fits_get_keyclass, records); +} + +% Image routines + +%!%+ +%\function{fits_get_bitpix} +%\synopsis{Get the fits bitpix value for an array} +%\usage{Int_Type fits_get_bitpix (array)} +%\description +% This function may be used to obtain the bitpix value for a specified image +% array. The array must be an integer or floating point type, otherwise +% and error will be generated. The bitpix value is returned. +%\seealso{fits_write_image_hdu, fits_read_img} +%!%- +define fits_get_bitpix (image) +{ + variable types = [Char_Type, UChar_Type, Int16_Type, UInt16_Type, + Int32_Type, UInt32_Type, Float32_Type, Float64_Type]; + variable bitpix = [10, 8, 16, 20, 32, 40, -32, -64]; + + variable b; + + if (typeof (image) == DataType_Type) + b = image; + else + b = _typeof (image); + + variable i = where (types == b); + if (length (i) == 0) + verror ("fits_get_bitpix: %S is not supported", b); + + return bitpix[i[0]]; +} + + +%!%+ +%\function{fits_read_img} +%\synopsis{Read image data from a fits file} +%\usage{Array_Type fits_read_img (fd)} +%#v+ +% Fits_File_Type or String_Type fd; +%#v- +%\description +% This function reads an image from the specified file descriptor. +% The file descriptor must be either the name of an existing file, or an +% open file pointer. It returns the image upon sucess, or signals an error +% upon failure. +%\seealso{fits_read_table, fits_read_col, fits_open_file, fits_write_img} +%!%- +define fits_read_img () +{ + !if (_NARGS) + usage ("I=fits_read_img (file);"); + variable fp = (); + + variable needs_close; + fp = get_open_image_hdu (fp, &needs_close); + + variable a; + + do_fits_error (_fits_read_img (fp, &a)); + do_close_file (fp, needs_close); + + return a; +} + +%!%+ +%\function{fits_create_image_hdu} +%\synopsis{Create a primary array or image extension} +%\usage{fits_create_image_hdu (fd, extname, type, dims)} +%#v+ +% Fits_File_Type or String_Type fd; +% String_Type extname; +% Array_Type dims; +% DataType_Type type; +%#v- +%\description +% This function make use of the \ifun{_fits_create_img} function to create an +% image extension or primary array of the specified type and size. If the +% \exmp{extname} parameter is non-NULL, then an EXTNAME keyword will be +% written out with the value of the extname parameter. +% The \exmp{dims} parameter must be a 1-d integer array that corresponds +% to the dimensions of the array to be written. +% +% If \exmp{fd} is specified as a string, then a new file of that name will be +% created. If a file by that name already exists, it will be deleted and +% a new one created. If this behavior is undesired, then explicitly open the +% file and pass this routine the resulting file pointer. +%\seealso{fits_write_image_hdu} +%!%- +define fits_create_image_hdu () +{ + if (_NARGS != 4) + usage ("%s (file, extname, type, dims)", _function_name ()); + + variable fp, extname, type, dims; + + (fp, extname, type, dims) = (); + + variable needs_close; + fp = get_open_write_fp (fp, "c", &needs_close); + + do_fits_error (_fits_create_img (fp, fits_get_bitpix (type), dims)); + if (extname != NULL) + do_fits_error (_fits_update_key (fp, "EXTNAME", extname, NULL)); + + do_close_file (fp, needs_close); +} + +%!%+ +%\function{fits_write_image_hdu} +%\synopsis{Write an image extension} +%\usage{fits_write_image_hdu (file, extname, image [,skeys [,hist]])} +%#v+ +% Fits_File_Type or String_Type file; +% String_Type extname; +% Any_Type image +% Struct_Type skeys; +% Struct_Type hist; +%#v- +%\description +% The \var{fits_write_image_hdu} function creates a new image extension in +% the specified file. The parameter \var{file} specifies either a filename or +% an open file pointer. The \var{extname} parameter specifies the extension +% name of the image, or NULL for the primary image. The image data written +% to the file are specified by the \var{image} parameter. +% If the optional parameter \var{skeys} is non-NULL, then it is a +% structure indicating additional keywords to be written to the HDU. +% If the optional parameter \var{hist} is present and non-NULL, +% then it is a structure whose fields indicate either comment or history +% information to be written to the header. +%\example +% The following code +%#v+ +% variable img = [1:128*128]; reshape (img, [128,128]); +% variable keys = struct { hduname, username}; +% keys.hduname = "MY_IMAGE"; +% keys.username = "John Doe"; +% variable hist = struct { history, comment}; +% hist.history = ["This is a history record", "This is another"]; +% hist.comment = ["This is a comment", "And this is another"]; +% fits_write_image_hdu ("foo.fits", NULL, img, keys, hist); +%#v- +% produces an image HDU with the header: +%#v+ +% SIMPLE = T / file does conform to FITS standard +% BITPIX = 32 / number of bits per data pixel +% NAXIS = 2 / number of data axes +% NAXIS1 = 128 / length of data axis 1 +% NAXIS2 = 128 / length of data axis 2 +% EXTEND = T / FITS dataset may contain extensions +% COMMENT FITS (Flexible Image Transport System) format is defined in 'Astronomy +% COMMENT and Astrophysics', volume 376, page 359; bibcode: 2001A&A...376..359H +% HDUNAME = 'MY_IMAGE' +% USERNAME= 'John Doe' +% HISTORY This is a history record +% HISTORY This is another +% COMMENT This is a comment +% COMMENT And this is another +%#v- +%\notes +% This function provides no mechanism to mix comments and keyword records. As +% the example shows, this function places the comment and history records at +% the end of the table. +%\seealso{fits_create_binary_table, fits_open_file} +%!%- +define fits_write_image_hdu () +{ + variable fp, extname, image, keys = NULL, history = NULL; + variable needs_close; + + switch (_NARGS) + { + case 4: + keys = (); + } + { + case 5: + (keys, history) = (); + } + { + if (_NARGS != 3) + { + _pop_n (_NARGS); + usage ("%s (file, extname, image [, keyword_struct [, history]]", _function_name ()); + } + } + + (fp, extname, image) = (); + + fp = get_open_write_fp (fp, "c", &needs_close); + + variable dims; (dims,,) = array_info (image); + fits_create_image_hdu (fp, extname, _typeof (image), dims); + + if (keys != NULL) + { + foreach (get_struct_field_names (keys)) + { + variable keyword = (); + variable val = get_struct_field (keys, keyword); + do_fits_error (_fits_update_key (fp, keyword, val, NULL), keyword); + } + } + + if (typeof (history) == String_Type) + { + history; + history = struct {history}; + history.history = (); + } + + if (history != NULL) + { + foreach (get_struct_field_names (history)) + { + keyword = (); + val = get_struct_field (history, keyword); + if (typeof (val) == String_Type) + val = [val]; + keyword = strlow (keyword); + foreach (val) + { + val = (); + if (keyword == "history") + { + do_fits_error (_fits_write_history (fp, val)); + continue; + } + if (keyword == "comment") + { + do_fits_error (_fits_write_comment (fp, val)); + continue; + } + vmessage ("*** WARNING: history/comment record name '%s' is not supported", + history); + } + } + } + + do_fits_error (_fits_write_img (fp, image)); + do_close_file (fp, needs_close); +} + + +%!%+ +%\function{fits_write_img} +%\synopsis{Write the image data to an Image HDU} +%\usage{fits_write_img (Fits_File_Type fptr, Any_Type data)} +%\description +% This function writes the image data out to current HDU, assumed to be +% an Image HDU. +%\seealso{fits_write_image_hdu, fits_create_image_hdu} +%!%- +% FIXME: Allow only a portion of the image to be written +define fits_write_img () +{ + variable fp, data; + + switch (_NARGS) + { + case 2: + (fp, data) = (); + } + { + usage ("%s (fptr, img)", _function_name); + } + do_fits_error (_fits_write_img (fp, data)); +} + + +#iffalse +define fits_iterate (fp, delta_rows, func, client_data, column_names) +{ + variable numrows; + variable num_columns = length (column_names); + variable col_nums = Int_Type[num_columns]; + variable data = Struct_Type[num_columns]; + variable i; + + for (i = 0; i < num_columns; i++) + { + variable col; + do_fits_error (_fits_get_colnum (fp, column_names[i], &col)); + col_nums[i] = col; + data[i] = struct { value }; + } + + do_fits_error (_fits_get_num_rows (fp, &numrows)); + + variable current_row = 1; + while (numrows) + { + variable value; + + if (numrows < delta_rows) + delta_rows = numrows; + + for (i = 0; i < num_columns; i++) + { + do_fits_error (_fits_read_col (fp, col_nums[i], current_row, + delta_rows, &value)); + data[i].value = value; + } + @func (client_data, __push_args (data)); + + current_row += delta_rows; + numrows -= delta_rows; + } +} + +define test_func (info, x, y, ccdid, grade, status) +{ + variable i = where ((ccdid == info.ccdid) + and ((grade != 1) and (grade != 5) and (grade != 7)) + and (status == 0)); + info.sum_x += sum (x[i]); + info.sum_y += sum (y[i]); + info.num += length (x[i]); +} + + +define test_fits_iterate () +{ + variable file = "/tmp/test.fits[EVENTS]"; + + variable info = struct + { + sum_x, sum_y, ccdid, num + }; + variable fp = fits_open_file (file, "r"); + + variable delta = 1; + while (delta < 100000000) + { + info.sum_x = 0; + info.sum_y = 0; + info.ccdid = 7; + info.num = 0; + + tic (); + fits_iterate (fp, 10000, &test_func, info, + ["X", "Y", "CCD_ID", "GRADE", "STATUS"]); + + () = fprintf (stdout, "delta=%d, CPU=%g secs, mean([x,y]) is [%g,%g]\n", + delta, toc (), info.sum_x/info.num, info.sum_y/info.num); + () = fflush (stdout); + delta *= 10; + } + +} +#endif + +% Obsolete functions + +define fits_read_image () +{ + () = fprintf (stderr, "*** Warning: fits_read_image is deprecated.\n"); + variable args = __pop_args (_NARGS); + return fits_read_img (__push_args (args)); +} + +provide ("fits"); + +#ifexists add_doc_file +$1 = path_concat (path_concat (path_dirname (__FILE__), "help"), + "cfitsio.hlp"); +if (NULL != stat_file ($1)) + add_doc_file ($1); +#endif + +#iffalse +autoload ("fitswcs_get_img_wcs", "fitswcs.sl") +autoload ("fitswcs_get_column_wcs", "fitswcs.sl") +autoload ("fitswcs_write_img_wcs", "fitswcs.sl") +autoload ("fitswcs_slice", "fitswcs.sl") +#endif diff --git a/modules/cfitsio/src/fitswcs.sl b/modules/cfitsio/src/fitswcs.sl new file mode 100644 index 0000000..77bdb7c --- /dev/null +++ b/modules/cfitsio/src/fitswcs.sl @@ -0,0 +1,1087 @@ +% Copyright (C) 2004-2007 Massachusetts Institute of Technology +% +% Author: John E. Davis +% +% 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., 675 Mass Ave, Cambridge, MA 02139, USA. + +% TODO: +% +% * Add support for cross-references when dealing with vector columns. +% +% * Add support for writing binary table WCS info +% +% Notes: +% +% Some fits files do not use the WCSAXES keyword to specifiy the dimensionality +% of the WCS. Instead a common practice is to add so-called degenerate axes +% where one increases the NAXIS keyword to the WCS dimensionality and adds +% keywords NAXISj=1 for the new dimensions. To deal with this hack, the +% user will be required to reshape the image to its proper dimensionality. +% Then the projection routines defined here may be used on any subspace of +% the WCS by extracting that subspace via the fitswcs_slice routine. + +require ("fits"); +variable _fitswcs_version = 0*10000 + 2*100 + 0; +variable _fitswcs_version_string = "0.2.0-1"; + +% FITS WCS may be attached to images or pixel-lists. The images may be +% found in a standard image HDU, or as a cell of a binary table. +% Pixel lists are encoded as columns of a FITS binary table. Hence, there +% are three forms of keywords that describe the wcs. + +private variable CTYPE_INDX = 0; +private variable CUNIT_INDX = 1; +private variable CRVAL_INDX = 2; +private variable CDELT_INDX = 3; +private variable CRPIX_INDX = 4; +private variable PC_INDX = 5; +private variable CD_INDX = 6; +private variable PV_INDX = 7; +private variable PS_INDX = 8; +% private variable CNAME_INDX = 9; + +private variable Image_Formats = + ["CTYPE%d", "CUNIT%d", "CRVAL%d", "CDELT%d", "CRPIX%d", + "PC%d_%d", "CD%d_%d", "PV%d_%d", "PS%d_%d"]; %, "CNAME%d"]; +private variable Image_Formats_Alt = Image_Formats + "%c"; + +private variable Column_Formats = + ["TCTYP%d", "TCUNI%d", "TCRVL%d", "TCDLT%d", "TCRPX%d", + "TP%d_%d", "TC%d_%d", "TV%d_%d", "TS%d_%d"]; %, ""]; +private variable Column_Formats_Alt = + ["TCTY%d%c", "TCUN%d%c", "TCRV%d%c", "TCDE%d%c", "TCRP%d%c", + "TP%d_%d%c", "TC%d_%d%c", "TV%d_%d%c", "TS%d_%d%c"]; %, "TCNA%d"]; + +private variable Vector_Formats = + ["%dCTYP%d", "%dCUNI%d", "%dCRVL%d", "%dCDLT%d", "%dCRPX%d", + "%dP%d_%d", "%dC%d_%d", "%dV%d_%d", "%dS%d_%d"];%, "%dCNA%d"]; +private variable Vector_Formats_Alt = + ["%dCTY%d%c", "%dCUN%d%c", "%dCRV%d%c", "%dCDE%d%c", "%dCRP%d%c", + "%dP%d_%d%c", "%dC%d_%d%c", "%dV%d_%d%c", "%dS%d_%d%c"];% "%dCNA%d%c"]; + +% This structure defines a transformation of the following form: +% +% B_i = CDELT_i PC_ij (A_j - CRPIX_j) (no sum on i) +% {X} = PROJ_FUNC({CTYPE}, {PV}, {PS}, {B}) +% +% where {X} signifies the set of values. Using this notation, the first +% equation could have been written +% +% {B}_i = {CDELT}_i {PC}_ij ({A}_j - {CRPIX}_j) (no sum on i) +% +private variable WCS_Type = struct +{ + naxis, % number of axis to transform + ctype, % String_Type[naxis] + cunit, % String_Type[naxis] + crval, % Double_Type[naxis] + crpix, % Double_Type[naxis] + cdelt, % Double_Type[naxis] + pc, % Double_Type[naxis,naxis] or NULL + pv, % array of parameters + ps, % array of string parms + wcsname, % String_Type + radsys, + equinox +}; + +% Notes: For usage of the and default values for the radsys and +% equinox, see, e.g., +% + +%!%+ +%\function{fitswcs_new} +%\synopsis{Create a new-ndimensional linear WCS} +%\usage{wcs = fitswcs_new (Int_Type naxis)} +%\description +% This function returns a new WCS structure of the specified dimensionality +% that represents an identity (linear) transformation. +%\seealso{fitswcs_get_img_wcs, fitswcs_get_column_wcs, fitswcs_get_vector_wcs} +%!%- +define fitswcs_new (naxis) +{ + variable wcs = @WCS_Type; + wcs.naxis = naxis; + wcs.ctype = String_Type[naxis]; wcs.ctype[*] = "linear"; + wcs.cunit = String_Type[naxis]; + wcs.crval = Double_Type[naxis]; wcs.crval[*] = 0.0; + wcs.crpix = Double_Type[naxis]; wcs.crpix[*] = 0.0; + wcs.cdelt = Double_Type[naxis]; wcs.cdelt[*] = 1.0; + wcs.pc = NULL; + wcs.pv = NULL; + wcs.ps = NULL; + return wcs; +} + + +%!%+ +%\function{fitswcs_slice} +%\synopsis{Form a new wcs from one or more axes of another} +%\usage{new_wcs = fitswcs_slice (wcs, dims)} +%\description +% This function may be used to construct a new wcs from another by rearranging +% its axes or by using a subset of them. The \exmp{dims} argument specifies +% the dimensions to use. +%\example +% Suppose that \exmp{wcs} represents a 4 dimensional WCS. Then +%#v+ +% wcs2 = fitswcs_slice (wcs, [0,1]); +%#v- +% will result in a 2 dimensional WCS from the first 2 axis of the input WCS. +% Similarly, +%#v+ +% wcs2 = fitswcs_slice (wcs, [1,0]); +%#v- +% will produce a 2d WCS with the first two axes swapped. +%\seealso{fitswcs_get_img_wcs, fitswcs_get_column_wcs, fitswcs_get_vector_wcs} +%!%- +define fitswcs_slice () +{ + if (_NARGS < 2) + usage ("wcs1 = %s(wcs, dims-array)", _function_name ()); + + variable wcs, dims; + (wcs, dims) = (); + variable new_wcs = @wcs; + + new_wcs.naxis = length (dims); + new_wcs.ctype = wcs.ctype[dims]; + new_wcs.cunit = wcs.cunit[dims]; + new_wcs.crval = wcs.crval[dims]; + new_wcs.crpix = wcs.crpix[dims]; + new_wcs.cdelt = wcs.cdelt[dims]; + if (wcs.pc != NULL) + new_wcs.pc = wcs.pc[dims, dims]; + return new_wcs; +} + + +%--------------------------------------------------------------------------- +% Some simple utility functions +%--------------------------------------------------------------------------- + +private define make_diag_matrix (n, diag) +{ + variable d = Double_Type[n, n]; + d [[0:n*n-1:n+1]] = diag; + return d; +} + +private define det_2x2 (a) +{ + return a[0,0]*a[1,1] - a[0,1]*a[1,0]; +} + +private define inverse_2x2 (a) +{ + variable det = det_2x2 (a); + if (det == 0.0) + verror ("FITS wcs matrix has no inverse"); + variable a1 = Double_Type[2,2]; + a1[0,0] = a[1,1]; + a1[0,1] = -a[0,1]; + a1[1,0] = -a[1,0]; + a1[1,1] = a[0,0]; + return a1/det; +} + +private define dup_wcs (wcs) +{ + wcs = @wcs; + + foreach (get_struct_field_names (wcs)) + { + variable field = (); + variable value = get_struct_field (wcs, field); + if (typeof (value) == Array_Type) + set_struct_field (wcs, field, @value); + } + return wcs; +} + +% Convert to/from FORTRAN/C order +private define reverse_wcs (wcs) +{ + return fitswcs_slice (wcs, [wcs.naxis-1:0:-1]); +} + +private define read_simple_wcs_keywords () +{ + variable indices = __pop_args (_NARGS-2); + variable formats = (); + variable fp = (); + + variable ctype, cunit, crval, crpix, cdelt; + + (ctype, cunit, crval, crpix, cdelt) = + fits_read_key (fp, sprintf (formats[CTYPE_INDX], __push_args(indices)), + sprintf (formats[CUNIT_INDX], __push_args(indices)), + sprintf (formats[CRVAL_INDX], __push_args(indices)), + sprintf (formats[CRPIX_INDX], __push_args(indices)), + sprintf (formats[CDELT_INDX], __push_args(indices))); + + if (ctype == NULL) + ctype = "linear"; + if (crval == NULL) + crval = 0.0; + if (crpix == NULL) + crpix = 0.0; + if (cdelt == NULL) + cdelt = 1.0; + + return (ctype, cunit, crval, crpix, cdelt); +} + +private define read_matrix_wcs_keywords (fp, pc_fmt, is, js, a, diag) +{ + variable pc = NULL; + variable n = length (is); + foreach (is) + { + variable i = (); + variable i1 = i-1; + foreach (js) + { + variable j = (); + variable j1 = j-1; + variable pc_ij = sprintf (pc_fmt, i, j, a); + pc_ij = fits_read_key (fp, pc_ij); + if ((pc_ij == NULL) and (pc == NULL)) + continue; + if (pc == NULL) + pc = make_diag_matrix (n, diag); + if (pc_ij != NULL) + pc [i1,j1] = pc_ij; + } + } + return pc; +} + +private define get_wcs_naxis (fp) +{ + variable naxis = fits_read_key (fp, "WCSAXES"); + if (naxis == NULL) + naxis = fits_read_key (fp, "NAXIS"); + + return naxis; +} + +private define open_interesting_hdu (file, type) +{ + variable fp = fits_open_file (file, "r"); + fits_move_to_interesting_hdu (fp, type); + return fp; +} + + +private define check_for_crota_hack (fp, wcs) +{ + if (wcs.naxis < 2) + return NULL; + + variable rot = fits_read_key (fp, "CROTA2"); + if ((rot == NULL) or (rot == 0.0)) + { + rot = fits_read_key (fp, "CROTA1"); + if ((rot == NULL) or (rot == 0.0)) + return NULL; + } + rot *= PI/180.0; + + % Apparantly, this angle gets applied AFTER cdelts applied. Hence, we have + % + % B_i = R(rot)_ij CDELT_j (A_j - CRPIX_j) (no sum on i) + % + % instead of + % + % B_i = CDELT_i PC_ij (A_j - CRPIX_j) (no sum on i) + % + % Hence, + % + % PC_ij = R(rot)_ij CDELT_j/CDELT_i (no sum) + variable pc = make_diag_matrix (wcs.naxis); + variable cdelt0 = wcs.cdelts[0]; + variable cdelt1 = wcs.cdelts[0]; + variable c = cos(rot), s = sin(rot); + pc[0,0] = c; pc[0,1] = -s*cdelt1/cdelt0; + pc[1,0] = s*cdelt0/cdelt1; pc[1,1] = c; + + return pc; +} + +%!%+ +%\function{fitswcs_get_img_wcs} +%\synopsis{Read a WCS for a FITS image} +%\usage{wcs = fitswcs_get_img_wcs (fp [,alt])} +%\description +% The \sfun{fitswcs_get_img_wcs} returns a structure representing a WCS from +% the specified file descriptor \exmp{fp} corresponding to an image HDU. +% An optional parameter may be used to specified an alternate WCS. +%\example +%#v+ +% wcs = fitswcs_get_img_wcs ("img.fits[IMAGE]", 'P'); +%#v- +%\seealso{fitswcs_put_img_wcs, fitswcs_get_column_wcs, fitswcs_get_vector_wcs} +%!%- +define fitswcs_get_img_wcs () +{ + variable fp, a = 0; + + if (_NARGS == 1) + fp = (); + else if (_NARGS == 2) + (fp, a) = (); + else + usage ("wcs = %s(file [,alt_axis_char])", _function_name); + + if (typeof (fp) == String_Type) + fp = open_interesting_hdu (fp, _FITS_IMAGE_HDU); + + variable naxis = get_wcs_naxis (fp); + variable wcs = fitswcs_new (naxis); + variable ctype = wcs.ctype, cunit = wcs.cunit, crval = wcs.crval, + crpix = wcs.crpix, cdelt = wcs.cdelt; + + wcs.wcsname = fits_read_key (fp, sprintf ("WCSNAME%c", a)); + variable formats = Image_Formats; + if (a) + formats = Image_Formats_Alt; + _for (0, naxis-1 , 1) + { + variable i = (); + + (ctype[i], cunit[i], crval[i], crpix[i], cdelt[i]) + = read_simple_wcs_keywords (fp, formats, i+1, a); + } + + variable pc; + pc = read_matrix_wcs_keywords (fp, formats[PC_INDX], [1:naxis], [1:naxis], a, 1.0); + if (pc == NULL) + pc = read_matrix_wcs_keywords (fp, formats[CD_INDX], [1:naxis], [1:naxis], a, 0.0); + + if ((pc == NULL) and (a == 0)) + pc = check_for_crota_hack (fp, wcs); + + wcs.pc = pc; + + return reverse_wcs (wcs); +} + + +%!%+ +%\function{fitswcs_get_column_wcs} +%\synopsis{Get the WCS attached to one or more columns of a binary table} +%\usage{fitswcs_get_column_wcs (fp, columns-array [,alt]} +%\description +% This function may be used to obtain the WCS associated with one or more +% columns of a binary table. The file descriptor \exmp{fp} must specify +% a binary table. The \exmp{columns-array} parameter should be an array +% of columns names. The third parameter is optional and is used to specify +% an alternate WCS. +%\example +%#v+ +% wcs = fitswcs_get_column_wcs ("evt1.fits[EVENTS]", ["Y","X"]); +%#v- +%\notes +% If the intent is to bin the data in the binary table columns, then +% it is best to specify the columns as \exmp{["Y", "X"]} and not the +% other way around. This is because the slang routines that deal with +% images assumes that the slowest varying index corresponds to the +% first one, whereas FITS assumes the opposite. +%\seealso{fitswcs_put_column_wcs, fitswcs_get_img_wcs, fitswcs_get_vector_wcs} +%!%- +define fitswcs_get_column_wcs () +{ + variable fp, a = 0, column_names = NULL; + + if (_NARGS == 3) + (fp, column_names, a) = (); + else if (_NARGS == 2) + (fp, column_names) = (); + + if ((column_names == NULL) or (typeof(a) == String_Type)) + usage ("wcs = %s(file, array_of_column_names [,alt_axis_char]);\n%s", + _function_name, + sprintf ("Example: wcs = %s(\"evt1.fits\", [\"X\",\"Y\"],'A');\n", + _function_name)); + + if (typeof (fp) == String_Type) + fp = open_interesting_hdu (fp, _FITS_BINARY_TBL); + + variable naxis = length (column_names); + + variable wcs = fitswcs_new (naxis); + variable ctype = wcs.ctype, cunit = wcs.cunit, crval = wcs.crval, + crpix = wcs.crpix, cdelt = wcs.cdelt; + + % The wcsname is not supported. The specification of this is flawed for + % "pixel-lists". A wcsname applies to the WCS as a whole-- not just a + % column. + wcs.wcsname = NULL; + + variable formats = Column_Formats; + if (a) + formats = Column_Formats_Alt; + + variable column_nums = Int_Type[naxis]; + _for (0, naxis-1 , 1) + { + variable i = (); + variable col = fits_get_colnum (fp, column_names[i]); + column_nums[i] = col; + + (ctype[i], cunit[i], crval[i], crpix[i], cdelt[i]) + = read_simple_wcs_keywords (fp, formats, col, a); + } + + variable pc; + pc = read_matrix_wcs_keywords (fp, formats[PC_INDX], column_nums, column_nums, a, 1.0); + if (pc == NULL) + pc = read_matrix_wcs_keywords (fp, formats[CD_INDX], column_nums, column_nums, a, 0.0); + + wcs.pc = pc; + return wcs; +} + +private define read_key_or_col (fp, key, row) +{ + %vmessage ("Looking for %s in row %d", key, row); + variable val = fits_read_key (fp, key); + if (val != NULL) + return val; + + % Perhaps it is the name of a column. + if (fits_binary_table_column_exists (fp, key)) + val = fits_read_cell (fp, key, row); + + return val; +} + +private define read_vector_matrix_wcs_keywords (fp, pc_fmt, is, js, col, row, a, diag) +{ + variable pc = NULL; + variable n = length (is); + foreach (is) + { + variable i = (); + variable i1 = i-1; + foreach (js) + { + variable j = (); + variable j1 = j-1; + variable pc_ij = sprintf (pc_fmt, i, j, col, a); + pc_ij = read_key_or_col (fp, pc_ij, row); + if ((pc_ij == NULL) and (pc == NULL)) + continue; + if (pc == NULL) + pc = make_diag_matrix (n, diag); + if (pc_ij != NULL) + pc [i1,j1] = pc_ij; + } + } + return pc; +} + + +%!%+ +%\function{fitswcs_get_vector_wcs} +%\synopsis{Get the WCS of an image in a specified table cell} +%\usage{wcs = fitswcs_get_vector_wcs (fp, column_name, row [,alt])} +%\description +% This function reads the WCS of an image in a specified cell of a binary +% table given by \exmp{fp} parameter. The second and third parameters specify +% the column name and row number of the cell. An optional fourth parameter +% may be used to obtain the corresponding alternate WCS. +%\example +% This example reads the WCS associated with the image in the second row +% of the QEU column of the binary table with HDUNAME equal to AXAF_QEU1 +% in the file "HRCQEU.fits": +%#v+ +% wcs = fitswcs_get_vector_wcs ("HRCQEU.fits[AXAF_QEU1], "QEU", 2); +%#v- +%\notes +% The current implementation does not yet support references to the WCS +% of other cells. +%\seealso{fitswcs_get_column_wcs, fitswcs_get_img_wcs} +%!%- +define fitswcs_get_vector_wcs () +{ + variable fp, col, row, a = 0; + + switch (_NARGS) + { + case 3: + (fp, col, row) = (); + } + { + case 4: + (fp, col, row, a) = (); + } + { + usage ("wcs = %s(file, column, row [,alt])", _function_name); + } + + if (typeof (fp) == String_Type) + fp = open_interesting_hdu (fp, _FITS_BINARY_TBL); + + if (typeof (col) == String_Type) + col = fits_get_colnum (fp, col); + + % Get the number of axes for the WCS. This may be given explicitly by + % the + variable naxis = read_key_or_col (fp, sprintf ("WCAX%d%c", col, a), row); + if (naxis == NULL) + { + % Read the image and get its dimensions + variable img = fits_read_cell (fp, col, row); + variable dims; (dims,,) = array_info (__tmp(img)); + naxis = length (dims); + } + variable wcs = fitswcs_new (naxis); + variable ctype = wcs.ctype, cunit = wcs.cunit, crval = wcs.crval, + crpix = wcs.crpix, cdelt = wcs.cdelt; + + wcs.wcsname = read_key_or_col (fp, sprintf ("WCSN%d%c", col, a), row); + + variable formats = Vector_Formats; + if (a) + formats = Vector_Formats_Alt; + + _for (0, naxis-1 , 1) + { + variable i = (); + variable i1 = i+1; + variable val; + + val = read_key_or_col (fp, sprintf (formats[CTYPE_INDX], i1, col, a), row); + if (val != NULL) ctype[i] = val; + + val = read_key_or_col (fp, sprintf (formats[CUNIT_INDX], i1, col, a), row); + if (val != NULL) cunit[i] = val; + + val = read_key_or_col (fp, sprintf (formats[CRVAL_INDX], i1, col, a), row); + if (val != NULL) crval[i] = val; + + val = read_key_or_col (fp, sprintf (formats[CRPIX_INDX], i1, col, a), row); + if (val != NULL) crpix[i] = val; + + val = read_key_or_col (fp, sprintf (formats[CDELT_INDX], i1, col, a), row); + if (val != NULL) cdelt[i] = val; + } + + variable pc; + dims = [1:naxis]; + pc = read_vector_matrix_wcs_keywords (fp, formats[PC_INDX], dims, dims, col, row, a, 1.0); + if (pc == NULL) + pc = read_vector_matrix_wcs_keywords (fp, formats[CD_INDX], dims, dims, col, row, a, 0.0); + + wcs.pc = pc; + return reverse_wcs (wcs); +} + + +%!%+ +%\function{fitswcs_new_img_wcs} +%\synopsis{Create a linear WCS for an image} +%\usage{wcs = fitswcs_new_img_wcs (grid0,grid1,...)} +%\description +% This function may be used to construct a linear WCS for an image with the +% specified grids. The grids are assumed to be linear. +%\example +% Use the histogram module's hist2d function to create an image from the X +% and Y columns in a file, and the construct a corresponding WCS: +%#v+ +% (x,y) = fits_read_col ("table.fits", "X", "Y"); +% gridx = [min(x):max(x):0.5]; +% gridy = [min(y):max(y):0.5]; +% img = hist2d (y,x,gridy,gridx); +% wcs = fitswcs_new_img_wcs (gridy, gridx); +%#v- +%\seealso{fitswcs_new, fitswcs_get_img_wcs} +%!%- +define fitswcs_new_img_wcs () +{ + variable naxis = _NARGS; + if (naxis == 0) + usage ("wcs = %s(grid_dim0, grid_dim1, ..., grid_dimN)", _function_name()); + + variable wcs = fitswcs_new (naxis); + variable i = naxis; + loop (naxis) + { + i--; + variable grid = (); + variable x0 = grid[0]; + wcs.crpix[i] = 0.5; + wcs.crval[i] = x0; + wcs.cdelt[i] = grid[1]-x0; + } + return wcs; +} + +private define write_wcs_keyword (fp, format, index, axis, a, value, i) +{ + if (value == NULL) + return; + value = value[i]; + if (value == NULL) + return; + variable key = sprintf (format[index], axis, a); + fits_update_key (fp, key, value, ""); +} + + +%!%+ +%\function{fitswcs_put_img_wcs} +%\synopsis{Write a WCS out to an image header} +%\usage{fitswcs_put_img_wcs (fp, wcs [,alt])} +%\description +% The \sfun{fitswcs_put_img_wcs} may be used to write the specified wcs +% out to the image HDU specified by the \exmp{fp} parameter. An optional +% third parameter may be used to specify an alternate WCS. +%\example +%#v+ +% fp = fits_open_file ("img.fits", "w"); +% . +% . +% . +% fits_put_img_wcs (fp, wcs, 'P'); +% fits_close_file (fp); +%#v- +%\seealso{fitswcs_put_column_wcs} +%!%- +define fitswcs_put_img_wcs () +{ + variable fp, a = 0; + variable wcs; + + if (_NARGS == 2) + (fp, wcs) = (); + else if (_NARGS == 3) + (fp, wcs, a) = (); + else + usage ("%s(fp, wcs-struct [,alt_axis_char])", _function_name); + + if (typeof (fp) != Fits_File_Type) + fp = fits_open_file (fp, "w"); + + % Write the wcs out in FORTRAN order + wcs = reverse_wcs (wcs); + + variable ctype = wcs.ctype, cunit = wcs.cunit, crval = wcs.crval, + crpix = wcs.crpix, cdelt = wcs.cdelt, naxis = wcs.naxis; + + fits_update_key (fp, sprintf ("WCSAXES%c", a), naxis); + if (wcs.wcsname != NULL) + fits_update_key (fp, sprintf ("WCSNAME%c", a), wcs.wcsname); + + variable i, j; + variable formats = Image_Formats; + if (a) + formats = Image_Formats_Alt; + + variable axes = [1:naxis]; + _for (0, naxis-1 , 1) + { + i = (); + j = axes[i]; + write_wcs_keyword (fp, formats, CTYPE_INDX, j, a, ctype, i); + write_wcs_keyword (fp, formats, CUNIT_INDX, j, a, cunit, i); + write_wcs_keyword (fp, formats, CRVAL_INDX, j, a, crval, i); + write_wcs_keyword (fp, formats, CRPIX_INDX, j, a, crpix, i); + write_wcs_keyword (fp, formats, CDELT_INDX, j, a, cdelt, i); + } + + variable pc = wcs.pc; + if (pc != NULL) _for (0, naxis-1, 1) + { + i = (); + _for (0, naxis-1, 1) + { + j = (); + fits_update_key (fp, sprintf (formats[PC_INDX], axes[i], axes[j], a), + pc[i, j], NULL); + } + } + + % FIXME: Write the rest of the wcs structure +} + + +%!%+ +%\function{fitswcs_put_column_wcs} +%\synopsis{Write the WCS attached to one or more table columns} +%\usage{fitswcs_put_column_wcs (fp, wcs, columns-array [,alt])} +%\description +% This function may be used to attach a WCS to one or more columns of a binary +% table. The dimensionality of the specified WCS must match the length of the +% array specifying the column names. The first parameter, \exmp{fp} must specify +% a binary table extension. The fourth parameter is optional and may be used +% to specify an alternate WCS. +%\example +%#v+ +% fitswcs_put_column_wcs ("evt2.fits[EVENTS], wcs, ["X","Y"]); +%#v- +%\seealso{fitswcs_get_column_wcs, fitswcs_put_img_wcs, fitswcs_get_img_wcs} +%!%- +define fitswcs_put_column_wcs () +{ + variable fp, wcs, columns, a = 0; + + switch (_NARGS) + { + case 3: + (fp, wcs, columns) = (); + } + { + case 4: + (fp, wcs, columns, a) = (); + } + { + usage ("%s(fp, wcs-struct, columns-array [,alt])", _function_name()); + } + + variable ctype = wcs.ctype, cunit = wcs.cunit, crval = wcs.crval, + crpix = wcs.crpix, cdelt = wcs.cdelt, naxis = wcs.naxis; + + if (length (columns) != naxis) + verror ("The dimensionality of the specified WCS does not match the number of columns"); + + if (typeof (fp) != Fits_File_Type) + fp = fits_open_file (fp, "w"); + + variable i, cols = Int_Type[naxis]; + _for (0, naxis-1, 1) + { + i = (); + variable colname = columns[i]; + if (0 == fits_binary_table_column_exists (fp, colname)) + verror ("Binary table column %s does not exist", colname); + cols[i] = fits_get_colnum (fp, colname); + } + + variable formats = Column_Formats; + if (a) + formats = Column_Formats_Alt; + + _for (0, naxis-1 , 1) + { + i = (); + variable j = cols[i]; + write_wcs_keyword (fp, formats, CTYPE_INDX, j, a, ctype, i); + write_wcs_keyword (fp, formats, CUNIT_INDX, j, a, cunit, i); + write_wcs_keyword (fp, formats, CRVAL_INDX, j, a, crval, i); + write_wcs_keyword (fp, formats, CRPIX_INDX, j, a, crpix, i); + write_wcs_keyword (fp, formats, CDELT_INDX, j, a, cdelt, i); + } + + variable pc = wcs.pc; + if (pc != NULL) _for (0, naxis-1, 1) + { + i = (); + _for (0, naxis-1, 1) + { + j = (); + fits_update_key (fp, sprintf (formats[PC_INDX], cols[i], cols[j], a), + pc[i, j], NULL); + } + } + + % FIXME: Write the rest of the wcs structure +} + + + +% This function will be used later when applying the wcs +private define simplify_wcs (wcs) +{ + variable pc = wcs.pc; + variable n = wcs.naxis; + + if (pc != NULL) + { + % If pc is diagonal, then factor diagonal elements into the cdelts + variable d = @pc; + variable i = [0:n*n-1:n+1]*1; % *1 to force it from being a range. Huh?? + d[i] = 0.0; + if (0 == length (where (d != 0))) + { + wcs.cdelt *= pc[i]; + wcs.pc = NULL; + } + else + { + _for (0, n-1, 1) + { + i = (); +#iffalse + % Unfortunately ds9 is unable to grok files that contain + % a PC matrix and unequal CDELT values. So, we will not + % use this code. + d = max(abs(pc[i,*])); + if (d != 0.0) + { + pc[i,*] /= d; + wcs.cdelt[i] *= d; + } +#else + % part 1 of ds9 hack + d = abs (wcs.cdelt[i]); + if (d != 0.0) + { + pc[i,*] *= d; + wcs.cdelt[i] /= d; + } +#endif + } +#iftrue + % part 2 of ds9 hack + d = max (abs(pc)); + wcs.cdelt *= d; + pc /= d; +#endif + if (n == 2) + { + d = abs(det_2x2 (pc)); + if (d != 0.0) + { + pc /= d; + wcs.cdelt *= d; + } + } + wcs.pc = pc; + } + } + + return wcs; +} + +%!%+ +%\function{fitswcs_linear_transform_wcs} +%\synopsis{Apply a linear transformation to a WCS} +%\usage{wcs1 = fitswcs_linear_transform_wcs (wcs, U0, A, X0)} +%#v+ +% wcs: The specified WCS to transform +% U0,X0: 1-d arrays +% A: 2-d array (or 1-d array representing a diagonal matrix) +%#v- +%\description +% This function may be used to create a new WCS by applying a linear +% transformation to an existing one. This is useful when one +% has a WCS associated with physical coordinates \exmp{X}, and then +% applies the linear transformation +%#v+ +% U = U0 + A#(X-X0) +%#v- +% to the coordinates X. Then corresponding WCS for the resulting image is +% given by +%#v+ +% new_wcs = fitswcs_linear_transform_wcs (wcs, U0, A, X0); +%#v- +%\notes +% The dimensionality of the WCS is limited to 2 in the +% current implementation. +%\seealso{fitswcs_rebin_wcs, fitswcs_bin_wcs} +%!%- + +% The algorithm: +% +% The existing WCS maps X to the world coordinate W via +% W = CRVAL + CD#(X-CRPIX) +% Now, a linear transformation is applied to X: +% U = U0 + A#(X-X0) +% Then +% X = X0 + invA#(U-U0) +% So: +% W = CRVAL + CD#(X0 + invA#(U-U0) - CRPIX) +% = CRVAL + CD#invA#(U-CRPIX') +% = CRVAL + CD'#(U-CRPIX') +% where +% CRPIX' = U0+A#(CRPIX-X0) +% CD' = CD#invA +% +% Note: CD_ij = CDELT_i PC_ij (no sum on i) +% or CD = CDELT#PC +% ==> CD' = CDELT#PC#invA = CDELT#PC' +% In other words, CDELT is unaffected by this transformation. +define fitswcs_linear_transform_wcs () +{ + if (_NARGS != 4) + usage ("new_wcs = %s(old_wcs, U0, A, X0);\n%s\n%s", + _function_name, + "where U = U0 + A#(X-X0) is the relationship between the new coordinates U", + "and the old coordintes X"); + + variable wcs, u0, a, x0; + (wcs, u0, a, x0) = (); + + variable wcs_naxis = wcs.naxis; + if (wcs_naxis != 2) + verror ("%s: Currently this routine supports only 2d wcs systems", _function_name); + + variable dims, num_dims; + (dims, num_dims, ) = array_info (a); + variable naxis; + + if (num_dims == 1) + { + naxis = dims[0]; + variable tmp = Double_Type[naxis, naxis]; + tmp[[0:naxis*naxis-1:naxis+1]] = a; + a = tmp; + } + else if (num_dims == 2) + { + naxis = dims[0]; + if (naxis != dims[1]) + verror ("%s: The A matrix must be square", _function_name); + } + else verror ("%s: The A matrix must be square", _function_name); + + if (wcs_naxis != naxis) + verror ("%s: The wcs requires A to be [%d,%d]", _function_name, wcs_naxis, wcs_naxis); + + wcs = dup_wcs (wcs); + + % Compute this: CRPIX' = U0 + A#(CRPIX-X0) + wcs.crpix = u0 + a#(wcs.crpix-x0); + variable inv_a = inverse_2x2(a); + variable pc = wcs.pc; + if (pc != NULL) + { + pc = pc#inv_a; + } + else + pc = inv_a; + + wcs.pc = pc; + return simplify_wcs (wcs); +} + + +%!%+ +%\function{fitswcs_rebin_wcs} +%\synopsis{This function may be used to obtain the wcs for a rebinned image} +%\usage{wcs1 = fitswcs_rebin_wcs (wcs, old_dims, new_dims...)} +%\description +% This function may be used to construct the WCS for a rebinned image from +% the WCS of of the unbinned image. The grid parameters specify the linear +% grids the new image. +%\example +% new_img = hist2d_rebin (new_yrid, new_xgrid, +% old_ygrid, old_xgrid, old_img); +% new_wcs = fitswcs_rebin_wcs (old_wcs, +% array_shape(old_img), +% array_shape(new_img)); +%\seealso{fitswcs_bin_wcs, fitswcs_linear_transform_wcs, fitswcs_slice} +%!%- +define fitswcs_rebin_wcs () +{ + if (_NARGS < 2) + usage ("wcs = %s (wcs, grid_dim0, grid_dim1,...)", _function_name()); + + variable naxis = _NARGS-1; + variable X0 = Double_Type[naxis]; + variable dX = Double_Type[naxis]; + variable I0 = 0.5 + Double_Type[naxis]; + variable i = naxis; + loop (naxis) + { + i--; + variable grid = (); + X0[i] = grid[0]; + dX[i] = grid[1]-grid[0]; + } + variable wcs = (); + return fitswcs_linear_transform_wcs (wcs, X0, dX, I0); +} + +%!%+ +%\function{fitswcs_bin_wcs} +%\synopsis{This function may be used to obtain the wcs for a rebinned image} +%\usage{wcs1 = fitswcs_rebin_wcs (wcs, grid0, grid1, ...)} +%\description +% +% This function may be used to construct the WCS for an image created +% by binning a set of coordinates from, e.g., a pixel-list. The +% \exmp{wcs} parameter represents the wcs attached to the unbinnned +% coordinates. The grid parameters specify the linear grids that were +% used to create the image. +% +%\seealso{fitswcs_rebin_wcs, fitswcs_linear_transform_wcs, fitswcs_slice} +%!%- +% +% Denote the grid used for binning by +% X = [X0,X0+dX,...,X0+(N)dX] = X0+[0,1,..,N]*dX +% The associated image system will be +% I = [0.5,1.5,,...0.5+(N)] = 0.5+[0,1,..N] +% This defines a linear transformation from X to I: +% +% I = 0.5+(1/dX)*(X-X0) +define fitswcs_bin_wcs () +{ + if (_NARGS < 2) + usage ("wcs = %s (wcs, grid_dim0, grid_dim1,...)", _function_name()); + + variable naxis = _NARGS-1; + variable X0 = Double_Type[naxis]; + variable dX = Double_Type[naxis]; + variable I0 = 0.5 + Double_Type[naxis]; + variable i = naxis; + loop (naxis) + { + i--; + variable grid = (); + X0[i] = grid[0]; + dX[i] = grid[1]-grid[0]; + } + variable wcs = (); + return fitswcs_linear_transform_wcs (wcs, I0, 1.0/dX, X0); +} + +% Suppose an image I[M0,M1,...] is rebinnned to J[N0,N1,...] +% This is a mapping I to J: +% 0.5 <= I <= M+0.5 +% 0.5 <= J <= N+0.5 +% or +% (J-0.5)/(I-0.5) = N/M +% J = 0.5 + N/M(I-0.5) +% +define fitswcs_rebin_wcs () +{ + if (_NARGS != 3) + usage ("wcs = %s (wcs, old_dims, new_dims)", _function_name()); + + variable wcs, old_dims, new_dims; + (wcs, old_dims, new_dims) = (); + + variable n = length (old_dims); + if (n != length(new_dims)) + verror ("The old_dims and new_dims must have an equal number of dimensions"); + + variable u0 = 0.5 + Double_Type[n]; + variable x0 = @u0; + variable a = double (new_dims)/old_dims; + return fitswcs_linear_transform_wcs (wcs, u0, a, x0); +} + +define fitswcs_translate_wcs () +{ + if (_NARGS < 2) + usage ("wcs = %s (wcs, dX_array)", _function_name()); + verror ("Not Implemented"); +} + +provide("fitswcs"); diff --git a/modules/cfitsio/src/mkversion.sh b/modules/cfitsio/src/mkversion.sh new file mode 100755 index 0000000..bed2bb9 --- /dev/null +++ b/modules/cfitsio/src/mkversion.sh @@ -0,0 +1,4 @@ +#version 1.0 +# The initial echo is necessary because the solaris version of sed cannot +# grok input without a trailing newline. +echo `grep "^#define MODULE_[MP]" version.h | sed -e 's/[^0-9]*//' | tr '\012' .` | sed -e 's/.$//' diff --git a/modules/cfitsio/src/tests/test_fits.sl b/modules/cfitsio/src/tests/test_fits.sl new file mode 100644 index 0000000..4e4ed49 --- /dev/null +++ b/modules/cfitsio/src/tests/test_fits.sl @@ -0,0 +1,129 @@ +private variable MODULE_NAME = "cfitsio"; +prepend_to_slang_load_path ("."); +set_import_module_path (".:" + get_import_module_path ()); + +require ("fits"); + +private variable Failed = 0; + +private define warn () +{ + variable args = __pop_args (_NARGS); + () = fprintf (stderr, "**** Warning: %s\n", + sprintf (__push_args (args))); + Failed++; +} + +private define check_key_read_write (fptr, key, val) +{ + variable val1; + + fits_update_key (fptr, key, val, NULL); + val1 = fits_read_key (fptr, key); + if ((val != val1) or (typeof (val) != typeof (val1))) + warn ("failed to write and then read key %S (%S != %S)", key, + typeof (val), typeof (val1)); +} + +define is_identical (a, b) +{ + variable dims_a, dims_b; + (dims_a,,) = array_info (a); + (dims_b,,) = array_info (b); + if (length (dims_a) != length (dims_b)) + return 0; + if (length (where(dims_a != dims_b))) + return 0; + if (_typeof (a) != _typeof(b)) + return 0; + if (length (where (a != b))) + return 0; + return 1; +} + +define test_img (filename) +{ + variable fptr = fits_open_file (filename, "c"); + variable dims = [2,10]; + variable npixels = dims[0]*dims[1]; + + fits_create_image_hdu (fptr, NULL, UInt32_Type, dims); + variable card = + "key_prec= 'This keyword was written by fxprec' / comment goes here"; + + fits_write_records (fptr, [card]); + + variable val = "1234567890123456789012345678901234567890" + + "12345678901234567890123456789012345"; + check_key_read_write (fptr, "card1", val); + + + check_key_read_write (fptr, "keyint", 1); + check_key_read_write (fptr, "keydbl", 1.2); + check_key_read_write (fptr, "tstring", "a string"); + + fits_update_logical (fptr, "tlogical", 1, NULL); + if (1 != fits_read_key (fptr, "tlogical")) + warn ("failed to read and write logical"); + + + fits_write_comment (fptr, " This keyword was written by fxpcom."); + fits_write_history (fptr, " This keyword written by fxphis (w/ 2 leading spaces)."); + fits_write_date (fptr); + + % Write data + % define the null value (must do this before writing any data) % + fits_update_key (fptr, "BLANK", -99, "value to use for undefined pixels"); + + variable array = typecast ([1:npixels], UChar_Type); + fits_write_img (fptr, array); + fits_close_file (fptr); + + array = typecast (array, UInt32_Type); + reshape (array, dims); + + fptr = fits_open_file (filename, "w"); + variable img = fits_read_img (fptr); + if (0 == is_identical (img, array)) + { + warn ("Write then read image failed: %S vs %S", array, img); + } + fits_close_file (fptr); +} + + +private define test_bt (filename) +{ + variable uint16s = UInt16_Type[65]; uint16s[*] = [1:65]; + variable uint32s = UInt32_Type[65]; uint32s[*] = [1:65]; + variable data = struct {u16, u32}; + data.u16 = uint16s; + data.u32 = uint16s; + + fits_write_binary_table (filename, "FOO", data); + + variable delete = 0; + + variable table = fits_read_table (filename + "[FOO]"); + if (0 == is_identical (table.u16, data.u16)) + { + warn ("testbt: failed to read/write an unsigned 16 bit column"); + delete = 0; + } + if (0 == is_identical (table.u32, data.u32)) + { + warn ("testbt: failed to read/write an unsigned 32 bit column"); + delete = 0; + } + if (delete) + () = remove (filename); +} + +test_bt ("testbt.fit"); +test_img ("testimg.fit"); + +if (Failed == 0) + message ("Passed"); +else + message ("Failed"); + diff --git a/modules/cfitsio/src/tests/test_wcs.sl b/modules/cfitsio/src/tests/test_wcs.sl new file mode 100644 index 0000000..6a6a8e0 --- /dev/null +++ b/modules/cfitsio/src/tests/test_wcs.sl @@ -0,0 +1,70 @@ +private variable MODULE_NAME = "cfitsio"; +prepend_to_slang_load_path ("."); +set_import_module_path (".:" + get_import_module_path ()); + +require ("fitswcs"); + +private variable Failed = 0; +private define warn () +{ + variable args = __pop_args (_NARGS); + () = fprintf (stderr, "**** Warning: %s\n", + sprintf (__push_args (args))); + Failed++; +} + + +private define test_wcs () +{ + variable wcs = fitswcs_new (2); + variable xmin = 100.0; + variable ymin = 200.0; + variable crpix = [ymin+10.0, xmin+20.0]; + + wcs.cdelt = [1,1]; + wcs.crpix = crpix; + wcs.crval = [7,8]; + wcs.pc=NULL; + + % Suppose that (x,y) coordinates are binned into an image of size + % [M,M] using a grid [xmin, xmin+1, ..., xmin+(M-1)]; + variable M = 73; + variable dx = 0.1, dy = 0.3; + variable xgrid = xmin + dx*[0:M-1]; + variable ygrid = ymin + dy*[0:M-1]; + variable wcs_M = fitswcs_bin_wcs (wcs, ygrid, xgrid); + + % Now the reference pixel crpix will have the pixel coordinate i + % given by + % crpix[1] = xmin + dx*(i-0.5) + % or i = (crpix[1]-xmin)/dx + 0.5; + + variable ix = (crpix[1]-xmin)/dx + 0.5; + if (fneqs (ix,wcs_M.crpix[1])) + warn ("fitswcs_bin_wcs: CRPIX was improperly computed"); + if (fneqs (dx, wcs_M.cdelt[1])) + warn ("fitswcs_bin_wcs: CDELT was improperly computed"); + + % Now rebin the image to NxN + % The image currently runs from xmin to M*dx. We want it to go + % from xmin to N*(M/N*dx) + variable N = 93; + dx = (M*dx)/N; + dy = (M*dy)/N; + xgrid = xmin + dx*[0:N-1]; + ygrid = ymin + dy*[0:N-1]; + + variable wcs_N = fitswcs_rebin_wcs (wcs_M, [M,M], [N,N]); + variable iy = (crpix[0]-ymin)/dy + 0.5; + if (fneqs (iy,wcs_N.crpix[0])) + warn ("fitswcs_rebin_wcs: CRPIX was improperly computed"); + if (fneqs (dy, wcs_N.cdelt[0])) + warn ("fitswcs_rebin_wcs: CDELT was improperly computed"); +} + +test_wcs (); + +if (Failed == 0) + message ("Passed"); +else + message ("Failed"); diff --git a/modules/cfitsio/src/version.h b/modules/cfitsio/src/version.h new file mode 100644 index 0000000..35bfb8c --- /dev/null +++ b/modules/cfitsio/src/version.h @@ -0,0 +1,10 @@ +#define MODULE_MAJOR_VERSION 0 +#define MODULE_MINOR_VERSION 4 +#define MODULE_PATCH_LEVEL 4 +#define MKSTR1(x) #x +#define MKSTR(x) MKSTR1(x) +static char *Module_Version_String = MKSTR(MODULE_MAJOR_VERSION) "." \ + MKSTR(MODULE_MINOR_VERSION) "." MKSTR(MODULE_PATCH_LEVEL); + +#define MODULE_VERSION_NUMBER \ + (MODULE_MAJOR_VERSION*10000+MODULE_MINOR_VERSION*100+MODULE_PATCH_LEVEL) diff --git a/modules/maplib/COPYRIGHT b/modules/maplib/COPYRIGHT new file mode 100644 index 0000000..6218f4f --- /dev/null +++ b/modules/maplib/COPYRIGHT @@ -0,0 +1,24 @@ + Copyright (c) 2004-2008 Massachusetts Institute of Technology + + This software was developed by the MIT Center for Space Research + under contract SV1-61010 from the Smithsonian Institution. + + Permission to use, copy, modify, distribute, and sell this software + and its documentation for any purpose is hereby granted without fee, + provided that the above copyright notice appear in all copies and + that both that copyright notice and this permission notice appear in + the supporting documentation, and that the name of the Massachusetts + Institute of Technology not be used in advertising or publicity + pertaining to distribution of the software without specific, written + prior permission. The Massachusetts Institute of Technology makes + no representations about the suitability of this software for any + purpose. It is provided "as is" without express or implied warranty. + + THE MASSACHUSETTS INSTITUTE OF TECHNOLOGY DISCLAIMS ALL WARRANTIES + WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE MASSACHUSETTS + INSTITUTE OF TECHNOLOGY BE LIABLE FOR ANY SPECIAL, INDIRECT OR + CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS + OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, + NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION + WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. diff --git a/modules/maplib/INSTALL.txt b/modules/maplib/INSTALL.txt new file mode 100644 index 0000000..a2c8722 --- /dev/null +++ b/modules/maplib/INSTALL.txt @@ -0,0 +1,181 @@ +Basic Installation +================== + + These are generic installation instructions. + + 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, a file +`config.cache' that saves the results of its tests to speed up +reconfiguring, and a file `config.log' containing compiler output +(useful mainly for debugging `configure'). + + 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 at some point `config.cache' +contains results you don't want to keep, you may remove or edit it. + + The file `configure.in' is used to create `configure' by a program +called `autoconf'. You only need `configure.in' 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. If you're + using `csh' on an old version of System V, you might need to type + `sh ./configure' instead to prevent `csh' from trying to execute + `configure' itself. + + Running `configure' takes awhile. 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. + + 4. Type `make install' to install the programs and any data files and + documentation. + + 5. 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. + +Compilers and Options +===================== + + Some systems require unusual options for compilation or linking that +the `configure' script does not know about. You can give `configure' +initial values for variables by setting them in the environment. Using +a Bourne-compatible shell, you can do that on the command line like +this: + CC=c89 CFLAGS=-O2 LIBS=-lposix ./configure + +Or on systems that have the `env' program, you can do it like this: + env CPPFLAGS=-I/usr/local/include LDFLAGS=-s ./configure + +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 must use a version of `make' that +supports the `VPATH' variable, such as 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 `..'. + + If you have to use a `make' that does not supports the `VPATH' +variable, you have 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. + +Installation Names +================== + + By default, `make install' will install the package's files in +`/usr/local/bin', `/usr/local/man', etc. You can specify an +installation prefix other than `/usr/local' by giving `configure' the +option `--prefix=PATH'. + + You can specify separate installation prefixes for +architecture-specific files and architecture-independent files. If you +give `configure' the option `--exec-prefix=PATH', the package will use +PATH as the prefix for installing programs and libraries. +Documentation and other data files will still use the regular prefix. + + In addition, if you use an unusual directory layout you can give +options like `--bindir=PATH' 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. + + 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'. + +Optional Features +================= + + 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. + +Specifying the System Type +========================== + + There may be some features `configure' can not figure out +automatically, but needs to determine by the type of host the package +will run on. Usually `configure' can figure that out, but if it prints +a message saying it can not guess the host type, give it the +`--host=TYPE' option. TYPE can either be a short name for the system +type, such as `sun4', or a canonical name with three fields: + CPU-COMPANY-SYSTEM + +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 host type. + + If you are building compiler tools for cross-compiling, you can also +use the `--target=TYPE' option to select the type of system they will +produce code for and the `--build=TYPE' option to select the type of +system on which you are compiling the package. + +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. + +Operation Controls +================== + + `configure' recognizes the following options to control how it +operates. + +`--cache-file=FILE' + Use and save the results of the tests in FILE instead of + `./config.cache'. Set FILE to `/dev/null' to disable caching, for + debugging `configure'. + +`--help' + Print a summary of the options to `configure', and exit. + +`--quiet' +`--silent' +`-q' + Do not print messages saying which checks are being made. + +`--srcdir=DIR' + Look for the package's source code in directory DIR. Usually + `configure' can determine that directory automatically. + +`--version' + Print the version of Autoconf used to generate the `configure' + script, and exit. + +`configure' also accepts some other, not widely useful, options. + diff --git a/modules/maplib/README b/modules/maplib/README new file mode 100644 index 0000000..c581225 --- /dev/null +++ b/modules/maplib/README @@ -0,0 +1,58 @@ +This distribution contains code for the S-Lang Maplib module. This +module may be used to perform various mapping projections between the +unit sphere and a surface such as a plane or cylinder. For more +information, see doc/*. + +To build the code, you will need to ensure that you have the S-Lang +library installed. It may be obtained from +http://www.jedsoft.org/slang/. + +You must run the configure script before you can compile the module. +If the slang library is installed in a +non-standard locations, then you will need to specify the location of +the library as arguments to the configure script. For example, +suppose libslang.so is located in /home/bill/lib and its include file +slang.h is located in /home/bill/include. Then one would run the +configure script using: + + ./configure --with-slanglib=/home/bill/lib \ + --with-slanginc=/home/bill/include + +or, the shorter form which assumes a common pathname prefix for the +lib and include directories: + + ./configure --with-slang=/home/bill + +You should also specify a location for the modules (*.so) and any associated +script (*.sl) files created by this package. The default location for +the modules is in + + $prefix/lib/slang/modules/ + +Any .sl files will be installed in + + $exec_prefix/share/slsh/local-packages/ + +where the values of the variable $prefix defaults to /usr/local, and +that of $exec_prefix to the value of $prefix. These values may be +changed using the --prefix and --exec-prefix configure script +parameters. For example, to set the value of $prefix to /home/bill, +use + + ./configure --prefix=/home/bill ... + +For more help using the configure script, run it using + + ./configure --help + +It is also a good idea to read the INSTALL.txt file located in this +directory. + +Once the configure script has been run, you should inspect +the Makefile that it generated in the src directory. Then building +and installing the library should involve nothing more than: + + make + make install + +You may have to have root privileges to peform the last step. diff --git a/modules/maplib/autoconf/Makefile b/modules/maplib/autoconf/Makefile new file mode 100644 index 0000000..8112319 --- /dev/null +++ b/modules/maplib/autoconf/Makefile @@ -0,0 +1,8 @@ +../configure: aclocal.m4 configure.ac + /bin/rm -rf autom4te.cache + autoconf && mv ./configure .. +update: config.sub config.guess +config.guess: /usr/share/misc/config.guess + /bin/cp -f /usr/share/misc/config.guess config.guess +config.sub: /usr/share/misc/config.sub + /bin/cp -f /usr/share/misc/config.sub config.sub diff --git a/modules/maplib/autoconf/Makefile.in b/modules/maplib/autoconf/Makefile.in new file mode 100644 index 0000000..1a4f913 --- /dev/null +++ b/modules/maplib/autoconf/Makefile.in @@ -0,0 +1,18 @@ +# -*- sh -*- + +@SET_MAKE@ +SHELL = /bin/sh + +all: + cd src; $(MAKE) all +clean: + cd src; $(MAKE) clean + /bin/rm -f *~ \#* +distclean: clean + cd src; $(MAKE) distclean + /bin/rm -f config.log config.cache config.status Makefile +test: + cd src; $(MAKE) test +install: + cd src; $(MAKE) install + diff --git a/modules/maplib/autoconf/aclocal.m4 b/modules/maplib/autoconf/aclocal.m4 new file mode 100644 index 0000000..8ce6059 --- /dev/null +++ b/modules/maplib/autoconf/aclocal.m4 @@ -0,0 +1,1026 @@ +dnl# -*- mode: sh; mode: fold -*- +dnl# 0.2.3-1: AC_AIX needs to be called before running the compiler (Miroslav Lichvar) +dnl# 0.2.3: rewrote JD_CHECK_FOR_LIBRARY to loop over include/lib pairs +dnl# 0.2.2-1: JD_WITH_LIBRARY bug-fix +dnl# 0.2.2: Use ncurses5-config to search for terminfo dirs. +dnl# 0.2.1: Add .dll.a to list of extensions to when searching for libs (cygwin) +dnl# 0.2.0: Added install target name and more fixes for cygwin +dnl# 0.1.12: Improved support for cygwin +dnl# 0.1.11: Fixed elf linking on freebsd (Renato Botelho (garga at freebsd, org) +dnl# Version 0.1.10: rpath support for netbsd +dnl# Version 0.1.9: When searching for libs, use dylib on darwin +dnl# Version 0.1.8: Add rpath support for OpenBSD +dnl# Version 0.1.7: removed "-K pic" from IRIX compiler lines +dnl# Version 0.1.6: Added cygwin module support +dnl# Version 0.1.5: Added gcc version-script support. + +AC_DEFUN(JD_INIT, dnl#{{{ +[ +#These variable are initialized by JD init function +CONFIG_DIR=`pwd` +cd $srcdir +if test "`pwd`" != "$CONFIG_DIR" +then + AC_MSG_ERROR("This software does not support configuring from another directory. See the INSTALL file") +fi +dnl# if test "X$PWD" != "X" +dnl# then +dnl# CONFIG_DIR="$PWD" +dnl# fi +AC_SUBST(CONFIG_DIR)dnl +# Note: these will differ if one is a symbolic link +if test -f /usr/bin/dirname; then + JD_Above_Dir=`dirname $CONFIG_DIR` +else +# system is a loser + JD_Above_Dir=`cd ..;pwd` +fi +JD_Above_Dir2=`cd ..;pwd` +]) +dnl#}}} + +dnl# This function expand the "prefix variables. For example, it will expand +dnl# values such as ${exec_prefix}/foo when ${exec_prefix} itself has a +dnl# of ${prefix}. This function produces the shell variables: +dnl# jd_prefix_libdir, jd_prefix_incdir +AC_DEFUN(JD_EXPAND_PREFIX, dnl#{{{ +[ + if test "X$jd_prefix" = "X" + then + jd_prefix=$ac_default_prefix + if test "X$prefix" != "XNONE" + then + jd_prefix="$prefix" + fi + jd_exec_prefix="$jd_prefix" + if test "X$exec_prefix" != "XNONE" + then + jd_exec_prefix="$exec_prefix" + fi + + dnl#Unfortunately, exec_prefix may have a value like ${prefix}, etc. + dnl#Let the shell expand those. Yuk. + eval `sh <>)dnl +define(<<$2>>, translit($1, [a-z], [A-Z]))dnl +changequote([, ])dnl +]) +#}}} + +AC_DEFUN(JD_SIMPLE_LIB_DIR, dnl#{{{ +[ +JD_UPPERCASE($1,JD_UP_NAME) +JD_UP_NAME[]_LIB_DIR=$JD_Above_Dir/$1/libsrc/"$ARCH"objs +JD_UP_NAME[]_INCLUDE=$JD_Above_Dir/$1/libsrc + +if test ! -d "[$]JD_UP_NAME[]_INCLUDE" +then + JD_UP_NAME[]_LIB_DIR=$JD_Above_Dir/$1/src/"$ARCH"objs + JD_UP_NAME[]_INCLUDE=$JD_Above_Dir/$1/src + if test ! -d "[$]JD_UP_NAME[]_INCLUDE" + then + echo "" + echo WARNING------Unable to find the JD_UP_NAME directory + echo You may have to edit $CONFIG_DIR/src/Makefile. + echo "" + fi +fi + +AC_SUBST(JD_UP_NAME[]_LIB_DIR)dnl +AC_SUBST(JD_UP_NAME[]_INCLUDE)dnl +undefine([JD_UP_NAME])dnl +]) + + +dnl#}}} + +AC_DEFUN(JD_FIND_GENERIC, dnl#{{{ +[ + AC_REQUIRE([JD_EXPAND_PREFIX])dnl + + changequote(<<, >>)dnl + define(<>, translit($1, [a-z], [A-Z]))dnl + changequote([, ])dnl +# Look for the JD_UP_NAME package +#JD_UP_NAME[]_INCLUDE="" +#JD_UP_NAME[]_LIB_DIR="" + +# This list consists of "include,lib include,lib ..." +JD_Search_Dirs="$JD_Above_Dir2/$1/libsrc,$JD_Above_Dir2/$1/libsrc/"$ARCH"objs \ + $JD_Above_Dir/$1/libsrc,$JD_Above_Dir/$1/libsrc/"$ARCH"objs \ + $JD_Above_Dir2/$1/src,$JD_Above_Dir2/$1/src/"$ARCH"objs \ + $JD_Above_Dir/$1/src,$JD_Above_Dir/$1/src/"$ARCH"objs" + +JD_Search_Dirs="$JD_Search_Dirs \ + $jd_prefix_incdir,$jd_prefix_libdir \ + $HOME/include,$HOME/lib" + +if test -n "$ARCH" +then + JD_Search_Dirs="$JD_Search_Dirs $HOME/include,$HOME/$ARCH/lib" + JD_Search_Dirs="$JD_Search_Dirs $HOME/include,$HOME/sys/$ARCH/lib" +fi + +# Now add the standard system includes. The reason for doing this is that +# the other directories may have a better chance of containing a more recent +# version. + +JD_Search_Dirs="$JD_Search_Dirs \ + /usr/local/include,/usr/local/lib \ + /usr/include,/usr/lib \ + /usr/include/$1,/usr/lib \ + /usr/include/$1,/usr/lib/$1" + +echo looking for the JD_UP_NAME library + +for include_and_lib in $JD_Search_Dirs +do + # Yuk. Is there a better way to set these variables?? + generic_include=`echo $include_and_lib | tr ',' ' ' | awk '{print [$]1}'` + generic_lib=`echo $include_and_lib | tr ',' ' ' | awk '{print [$]2}'` + echo Looking for $1.h in $generic_include + echo and lib$1.a in $generic_lib + if test -r $generic_include/$1.h && test -r $generic_lib/lib$1.a + then + echo Found it. + JD_UP_NAME[]_LIB_DIR="$generic_lib" + JD_UP_NAME[]_INCLUDE="$generic_include" + break + else + if test -r $generic_include/$1.h && test -r $generic_lib/lib$1.so + then + echo Found it. + JD_UP_NAME[]_LIB_DIR="$generic_lib" + JD_UP_NAME[]_INCLUDE="$generic_include" + break + fi + fi +done + +if test -n "[$]JD_UP_NAME[]_LIB_DIR" +then + jd_have_$1="yes" +else + echo Unable to find the $JD_UP_NAME library. + echo You may have to edit $CONFIG_DIR/src/Makefile. + JD_UP_NAME[]_INCLUDE=$JD_Above_Dir/$1/src + JD_UP_NAME[]_LIB_DIR=$JD_Above_Dir/$1/src/"$ARCH"objs + jd_have_$1="no" +fi + +JD_UP_NAME[]_INC="-I[$]JD_UP_NAME[]_INCLUDE" +JD_UP_NAME[]_LIB="-L[$]JD_UP_NAME[]_LIB_DIR" +JD_SET_RPATH([$]JD_UP_NAME[]_LIB_DIR) +dnl if test "X$GCC" = Xyes +dnl then +dnl RPATH_[]JD_UP_NAME="-Wl,-R[$]JD_UP_NAME[]_LIB_DIR" +dnl else +dnl RPATH_[]JD_UP_NAME="-R[$]JD_UP_NAME[]_LIB_DIR" +dnl fi + +# gcc under solaris is often not installed correctly. Avoid specifying +# -I/usr/include. +if test "[$]JD_UP_NAME[]_INC" = "-I/usr/include" +then + JD_UP_NAME[]_INC="" +fi + +if test "[$]JD_UP_NAME[]_LIB" = "-L/usr/lib" +then + JD_UP_NAME[]_LIB="" + RPATH_[]JD_UP_NAME="" +fi + +AC_SUBST(JD_UP_NAME[]_LIB)dnl +AC_SUBST(JD_UP_NAME[]_INC)dnl +AC_SUBST(JD_UP_NAME[]_LIB_DIR)dnl +AC_SUBST(JD_UP_NAME[]_INCLUDE)dnl +dnl AC_SUBST(RPATH_[]JD_UP_NAME)dnl +undefine([JD_UP_NAME])dnl +]) + + +dnl#}}} + +AC_DEFUN(JD_FIND_SLANG, dnl#{{{ +[ +JD_FIND_GENERIC(slang) +]) + +dnl#}}} + +AC_DEFUN(JD_GCC_WARNINGS, dnl#{{{ +[ +AC_ARG_ENABLE(warnings, + [ --enable-warnings turn on GCC compiler warnings], + [gcc_warnings=$enableval]) +if test -n "$GCC" +then + #CFLAGS="$CFLAGS -fno-strength-reduce" + if test -n "$gcc_warnings" + then + CFLAGS="$CFLAGS -Wall -W -pedantic -Winline -Wmissing-prototypes \ + -Wnested-externs -Wpointer-arith -Wcast-align -Wshadow -Wstrict-prototypes" + # Now trim excess whitespace + CFLAGS=`echo $CFLAGS` + fi +fi +]) + + +dnl#}}} + +IEEE_CFLAGS="" +AC_DEFUN(JD_IEEE_CFLAGS, dnl#{{{ +[ +case "$host_cpu" in + *alpha* ) + if test "$GCC" = yes + then + IEEE_CFLAGS="-mieee" + else + IEEE_CFLAGS="-ieee_with_no_inexact" + fi + ;; + * ) + IEEE_CFLAGS="" +esac +]) + + +dnl#}}} + +AC_DEFUN(JD_CREATE_ORULE, dnl#{{{ +[ +PROGRAM_OBJECT_RULES="$PROGRAM_OBJECT_RULES +\$(OBJDIR)/$1.o : \$(SRCDIR)/$1.c \$(DOT_O_DEPS) \$("$1"_O_DEP) + cd \$(OBJDIR); \$(COMPILE_CMD) \$("$1"_C_FLAGS) \$(SRCDIR)/$1.c +" +]) + +dnl#}}} + +AC_DEFUN(JD_CREATE_ELFORULE, dnl#{{{ +[ +PROGRAM_ELF_ORULES="$PROGRAM_ELF_ORULES +\$(ELFDIR)/$1.o : \$(SRCDIR)/$1.c \$(DOT_O_DEPS) \$("$1"_O_DEP) + cd \$(ELFDIR); \$(ELFCOMPILE_CMD) \$("$1"_C_FLAGS) \$(SRCDIR)/$1.c +" +]) + + +dnl#}}} + +AC_DEFUN(JD_CREATE_EXEC_RULE, dnl#{{{ +[ +PROGRAM_OBJECT_RULES="$PROGRAM_OBJECT_RULES +$1 : \$(OBJDIR)/$1 + @echo $1 created in \$(OBJDIR) +\$(OBJDIR)/$1 : \$(OBJDIR)/$1.o \$("$1"_DEPS) \$(EXECDEPS) + \$(CC) -o \$(OBJDIR)/$1 \$(LDFLAGS) \$(OBJDIR)/$1.o \$("$1"_LIBS) \$(EXECLIBS) +\$(OBJDIR)/$1.o : \$(SRCDIR)/$1.c \$(DOT_O_DEPS) \$("$1"_O_DEP) + cd \$(OBJDIR); \$(COMPILE_CMD) \$("$1"_INC) \$(EXECINC) \$(SRCDIR)/$1.c +" +]) + + +dnl#}}} + +AC_DEFUN(JD_CREATE_MODULE_ORULES, dnl#{{{ +[ + for program_module in $Program_Modules; do + JD_CREATE_ORULE($program_module) + JD_CREATE_ELFORULE($program_module) + done +]) + +dnl#}}} + +AC_DEFUN(JD_GET_MODULES, dnl#{{{ +[ + PROGRAM_HFILES="" + PROGRAM_OFILES="" + PROGRAM_CFILES="" + PROGRAM_OBJECTS="" + PROGRAM_ELFOBJECTS="" + PROGRAM_OBJECT_RULES="" + PROGRAM_ELF_ORULES="" + if test -z "$1" + then + Program_Modules="" + else + comment_re="^#" + Program_Modules=`grep -v '$comment_re' $1 | awk '{print [$]1}'` + Program_H_Modules=`grep -v '$comment_re' $1 | awk '{print [$]2}'` + for program_module in $Program_H_Modules; do + PROGRAM_HFILES="$PROGRAM_HFILES $program_module" + done + fi + for program_module in $Program_Modules; do + PROGRAM_OFILES="$PROGRAM_OFILES $program_module.o" + PROGRAM_CFILES="$PROGRAM_CFILES $program_module.c" + PROGRAM_OBJECTS="$PROGRAM_OBJECTS \$(OBJDIR)/$program_module.o" + PROGRAM_ELFOBJECTS="$PROGRAM_ELFOBJECTS \$(ELFDIR)/$program_module.o" + done +dnl echo $PROGRAM_OFILES +dnl echo $PROGRAM_HFILES +AC_SUBST(PROGRAM_OFILES)dnl +AC_SUBST(PROGRAM_CFILES)dnl +AC_SUBST(PROGRAM_HFILES)dnl +AC_SUBST(PROGRAM_OBJECTS)dnl +AC_SUBST(PROGRAM_ELFOBJECTS)dnl +]) + + +dnl#}}} + +AC_DEFUN(JD_APPEND_RULES, dnl#{{{ +[ + echo "$PROGRAM_OBJECT_RULES" >> $1 +]) + + +dnl#}}} + +AC_DEFUN(JD_APPEND_ELFRULES, dnl#{{{ +[ + echo "$PROGRAM_ELF_ORULES" >> $1 +]) + +dnl#}}} + +AC_DEFUN(JD_CREATE_MODULE_EXEC_RULES, dnl#{{{ +[ + for program_module in $Program_Modules; do + JD_CREATE_EXEC_RULE($program_module) + done +]) + +dnl#}}} + +AC_DEFUN(JD_TERMCAP, dnl#{{{ +[ +AC_PATH_PROG(nc5config, ncurses5-config, no) +if test "$nc5config" = "no" +then + AC_PATH_PROG(nc5config, ncurses5w-config, no) +fi +AC_MSG_CHECKING(for terminfo) +if test "$nc5config" != "no" +then + MISC_TERMINFO_DIRS=`$nc5config --terminfo` +else + MISC_TERMINFO_DIRS="" +fi +JD_Terminfo_Dirs="$MISC_TERMINFO_DIRS \ + /usr/lib/terminfo \ + /usr/share/terminfo \ + /usr/share/lib/terminfo \ + /usr/local/lib/terminfo" +TERMCAP=-ltermcap + +for terminfo_dir in $JD_Terminfo_Dirs +do + if test -d $terminfo_dir + then + AC_MSG_RESULT(yes) + TERMCAP="" + break + fi +done +if test "$TERMCAP"; then + AC_MSG_RESULT(no) + AC_DEFINE(USE_TERMCAP) +fi +AC_SUBST(TERMCAP)dnl +AC_SUBST(MISC_TERMINFO_DIRS)dnl +]) + + +dnl#}}} + +AC_DEFUN(JD_ANSI_CC, dnl#{{{ +[ +AC_AIX +AC_PROG_CC +AC_PROG_CPP +AC_PROG_GCC_TRADITIONAL +AC_ISC_POSIX + +dnl #This stuff came from Yorick config script +dnl +dnl # HPUX needs special stuff +dnl +AC_EGREP_CPP(yes, +[#ifdef hpux + yes +#endif +], [ +AC_DEFINE(_HPUX_SOURCE) +if test "$CC" = cc; then CC="cc -Ae"; fi +])dnl +dnl +dnl #Be sure we've found compiler that understands prototypes +dnl +AC_MSG_CHECKING(C compiler that understands ANSI prototypes) +AC_TRY_COMPILE([ ],[ + extern int silly (int);], [ + AC_MSG_RESULT($CC looks ok. Good.)], [ + AC_MSG_RESULT($CC is not a good enough compiler) + AC_MSG_ERROR(Set env variable CC to your ANSI compiler and rerun configure.) + ])dnl +])dnl + +dnl#}}} + + +AC_DEFUN(JD_ELF_COMPILER, dnl#{{{ +[ +dnl #------------------------------------------------------------------------- +dnl # Check for dynamic linker +dnl #------------------------------------------------------------------------- +DYNAMIC_LINK_LIB="" +AC_CHECK_HEADER(dlfcn.h,[ + AC_DEFINE(HAVE_DLFCN_H) + AC_CHECK_LIB(dl,dlopen,[ + DYNAMIC_LINK_LIB="-ldl" + AC_DEFINE(HAVE_DLOPEN) + ],[ + AC_CHECK_FUNC(dlopen,AC_DEFINE(HAVE_DLOPEN)) + if test "$ac_cv_func_dlopen" != yes + then + AC_MSG_WARN(cannot perform dynamic linking) + fi + ])]) +AC_SUBST(DYNAMIC_LINK_LIB) + + +if test "$GCC" = yes +then + if test X"$CFLAGS" = X + then + CFLAGS="-O2" + fi +fi + +dnl #Some defaults +ELFLIB="lib\$(THIS_LIB).so" +ELFLIB_MAJOR="\$(ELFLIB).\$(ELF_MAJOR_VERSION)" +ELFLIB_MAJOR_MINOR="\$(ELFLIB_MAJOR).\$(ELF_MINOR_VERSION)" +ELFLIB_MAJOR_MINOR_MICRO="\$(ELFLIB_MAJOR_MINOR).\$(ELF_MICRO_VERSION)" + +dnl# This specifies the target to use in the makefile to install the shared library +INSTALL_ELFLIB_TARGET="install-elf-and-links" +ELFLIB_BUILD_NAME="\$(ELFLIB_MAJOR_MINOR_MICRO)" +INSTALL_MODULE="\$(INSTALL_DATA)" +SLANG_DLL_CFLAGS="" + +case "$host_os" in + *linux*|*gnu*|k*bsd*-gnu ) + DYNAMIC_LINK_FLAGS="-Wl,-export-dynamic" + ELF_CC="\$(CC)" + ELF_CFLAGS="\$(CFLAGS) -fPIC" + ELF_LINK="\$(CC) \$(LDFLAGS) -shared -Wl,-O1 -Wl,--version-script,\$(VERSION_SCRIPT) -Wl,-soname,\$(ELFLIB_MAJOR)" + ELF_DEP_LIBS="\$(DL_LIB) -lm -lc" + CC_SHARED="\$(CC) \$(CFLAGS) -shared -fPIC" + ;; + *solaris* ) + if test "$GCC" = yes + then + DYNAMIC_LINK_FLAGS="" + ELF_CC="\$(CC)" + ELF_CFLAGS="\$(CFLAGS) -fPIC" + ELF_LINK="\$(CC) \$(LDFLAGS) -shared -Wl,-ztext -Wl,-h,\$(ELFLIB_MAJOR)" + ELF_DEP_LIBS="\$(DL_LIB) -lm -lc" + CC_SHARED="\$(CC) \$(CFLAGS) -G -fPIC" + else + DYNAMIC_LINK_FLAGS="" + ELF_CC="\$(CC)" + ELF_CFLAGS="\$(CFLAGS) -K PIC" + ELF_LINK="\$(CC) \$(LDFLAGS) -G -h\$(ELFLIB_MAJOR)" + ELF_DEP_LIBS="\$(DL_LIB) -lm -lc" + CC_SHARED="\$(CC) \$(CFLAGS) -G -K PIC" + fi + ;; + # osr5 or unixware7 with current or late autoconf + *sco3.2v5* | *unixware-5* | *sco-sysv5uw7*) + if test "$GCC" = yes + then + DYNAMIC_LINK_FLAGS="" + ELF_CC="\$(CC)" + ELF_CFLAGS="\$(CFLAGS) -fPIC" + ELF_LINK="\$(CC) \$(LDFLAGS) -shared -Wl,-h,\$(ELFLIB_MAJOR)" + ELF_DEP_LIBS= + CC_SHARED="\$(CC) \$(CFLAGS) -G -fPIC" + else + DYNAMIC_LINK_FLAGS="" + ELF_CC="\$(CC)" + ELF_CFLAGS="\$(CFLAGS) -K pic" + # ELF_LINK="ld -G -z text -h#" + ELF_LINK="\$(CC) \$(LDFLAGS) -G -z text -h\$(ELFLIB_MAJOR)" + ELF_DEP_LIBS= + CC_SHARED="\$(CC) \$(CFLAGS) -G -K pic" + fi + ;; + *irix6.5* ) + echo "Note: ELF compiler for host_os=$host_os may not be correct" + echo "double-check: 'mode_t', 'pid_t' may be wrong!" + if test "$GCC" = yes + then + # not tested + DYNAMIC_LINK_FLAGS="" + ELF_CC="\$(CC)" + ELF_CFLAGS="\$(CFLAGS) -fPIC" + ELF_LINK="\$(CC) \$(LDFLAGS) -shared -Wl,-h,\$(ELFLIB_MAJOR)" + ELF_DEP_LIBS= + CC_SHARED="\$(CC) \$(CFLAGS) -shared -fPIC" + else + DYNAMIC_LINK_FLAGS="" + ELF_CC="\$(CC)" + ELF_CFLAGS="\$(CFLAGS)" # default anyhow + ELF_LINK="\$(CC) \$(LDFLAGS) -shared -o \$(ELFLIB_MAJOR)" + ELF_DEP_LIBS= + CC_SHARED="\$(CC) \$(CFLAGS) -shared" + fi + ;; + *darwin* ) + DYNAMIC_LINK_FLAGS="" + ELF_CC="\$(CC)" + ELF_CFLAGS="\$(CFLAGS) -fno-common" + ELF_LINK="\$(CC) \$(LDFLAGS) -dynamiclib -install_name \$(install_lib_dir)/\$(ELFLIB_MAJOR) -compatibility_version \$(ELF_MAJOR_VERSION) -current_version \$(ELF_MAJOR_VERSION).\$(ELF_MINOR_VERSION)" + ELF_DEP_LIBS="\$(LDFLAGS) \$(DL_LIB)" + CC_SHARED="\$(CC) -bundle -flat_namespace -undefined suppress \$(CFLAGS) -fno-common" + ELFLIB="lib\$(THIS_LIB).dylib" + ELFLIB_MAJOR="lib\$(THIS_LIB).\$(ELF_MAJOR_VERSION).dylib" + ELFLIB_MAJOR_MINOR="lib\$(THIS_LIB).\$(ELF_MAJOR_VERSION).\$(ELF_MINOR_VERSION).dylib" + ELFLIB_MAJOR_MINOR_MICRO="lib\$(THIS_LIB).\$(ELF_MAJOR_VERSION).\$(ELF_MINOR_VERSION).\$(ELF_MICRO_VERSION).dylib" + ;; + *freebsd* ) + ELF_CC="\$(CC)" + ELF_CFLAGS="\$(CFLAGS) -fPIC" + #if test "X$PORTOBJFORMAT" = "Xelf" ; then + # ELF_LINK="\$(CC) \$(LDFLAGS) -shared -Wl,-soname,\$(ELFLIB_MAJOR)" + #else + # ELF_LINK="ld -Bshareable -x" + #fi + ELF_LINK="\$(CC) \$(LDFLAGS) -shared -Wl,-soname,\$(ELFLIB_MAJOR)" + ELF_DEP_LIBS="\$(DL_LIB) -lm" + CC_SHARED="\$(CC) \$(CFLAGS) -shared -fPIC" + ;; + *cygwin* ) + DYNAMIC_LINK_FLAGS="" + ELF_CC="\$(CC)" + SLANG_DLL_CFLAGS="-DSLANG_DLL=1" + ELF_CFLAGS="\$(CFLAGS) -DBUILD_DLL=1" + DLL_IMPLIB_NAME="lib\$(THIS_LIB)\$(ELFLIB_MAJOR_VERSION).dll.a" + #ELF_LINK="\$(CC) \$(LDFLAGS) -shared -Wl,-O1 -Wl,--version-script,\$(VERSION_SCRIPT) -Wl,-soname,\$(ELFLIB_MAJOR) -Wl,--out-implib=\$(DLL_IMPLIB_NAME) -Wl,-export-all-symbols -Wl,-enable-auto-import" + ELF_LINK="\$(CC) \$(LDFLAGS) -shared -Wl,-O1 -Wl,--version-script,\$(VERSION_SCRIPT) -Wl,-soname,\$(ELFLIB_MAJOR) -Wl,--out-implib=\$(DLL_IMPLIB_NAME)" + ELF_DEP_LIBS="\$(DL_LIB) -lm" + CC_SHARED="\$(CC) \$(CFLAGS) -shared -DSLANG_DLL=1" + dnl# CYGWIN prohibits undefined symbols when linking shared libs + SLANG_LIB_FOR_MODULES="-L\$(ELFDIR) -lslang" + INSTALL_MODULE="\$(INSTALL)" + INSTALL_ELFLIB_TARGET="install-elf-cygwin" + ELFLIB="lib\$(THIS_LIB).dll" + ELFLIB_MAJOR="lib\$(THIS_LIB)\$(ELF_MAJOR_VERSION).dll" + ELFLIB_MAJOR_MINOR="lib\$(THIS_LIB)\$(ELF_MAJOR_VERSION)_\$(ELF_MINOR_VERSION).dll" + ELFLIB_MAJOR_MINOR_MICRO="lib\$(THIS_LIB)\$(ELF_MAJOR_VERSION)_\$(ELF_MINOR_VERSION)_\$(ELF_MICRO_VERSION).dll" + ELFLIB_BUILD_NAME="\$(ELFLIB_MAJOR)" + ;; + * ) + echo "Note: ELF compiler for host_os=$host_os may be wrong" + ELF_CC="\$(CC)" + ELF_CFLAGS="\$(CFLAGS) -fPIC" + ELF_LINK="\$(CC) \$(LDFLAGS) -shared" + ELF_DEP_LIBS="\$(DL_LIB) -lm -lc" + CC_SHARED="\$(CC) \$(CFLAGS) -shared -fPIC" +esac + +AC_SUBST(ELF_CC) +AC_SUBST(ELF_CFLAGS) +AC_SUBST(ELF_LINK) +AC_SUBST(ELF_LINK_CMD) +AC_SUBST(ELF_DEP_LIBS) +AC_SUBST(DYNAMIC_LINK_FLAGS) +AC_SUBST(CC_SHARED) +AC_SUBST(ELFLIB) +AC_SUBST(ELFLIB_MAJOR) +AC_SUBST(ELFLIB_MAJOR_MINOR) +AC_SUBST(ELFLIB_MAJOR_MINOR_MICRO) +AC_SUBST(SLANG_LIB_FOR_MODULES) +AC_SUBST(DLL_IMPLIB_NAME) +AC_SUBST(INSTALL_MODULE) +AC_SUBST(INSTALL_ELFLIB_TARGET) +AC_SUBST(ELFLIB_BUILD_NAME) +AC_SUBST(SLANG_DLL_CFLAGS) +]) + +dnl#}}} + +AC_DEFUN(JD_F77_COMPILER, dnl#{{{ +[ +case "$host_os" in + *linux* ) + F77="g77" + F77_LIBS="-lg2c" + ;; + *solaris*) + F77=f77 + #F77_LIBS="-lF77 -lM77 -L/opt/SUNWspro/SC4.0/lib -lsunmath" + F77_LIBS="-lF77 -lM77 -lsunmath" + ;; + *) + echo "" + echo "WARNING: Assuming f77 as your FORTRAN compiler" + echo "" + F77=f77 + F77_LIBS="" +esac +AC_SUBST(F77) +AC_SUBST(F77_LIBS) +]) + + + +dnl#}}} + +dnl# This macro process the --with-xxx, --with-xxxinc, and --with-xxxlib +dnl# command line arguments and returns the values as shell variables +dnl# jd_xxx_include_dir and jd_xxx_library_dir. It does not perform any +dnl# substitutions, nor check for the existence of the supplied values. +AC_DEFUN(JD_WITH_LIBRARY_PATHS, dnl#{{{ +[ + JD_UPPERCASE($1,JD_ARG1) + jd_$1_include_dir="" + jd_$1_library_dir="" + if test X"$jd_with_$1_library" = X + then + jd_with_$1_library="" + fi + + AC_ARG_WITH($1, + [ --with-$1=DIR Use DIR/lib and DIR/include for $1], + [jd_with_$1_arg=$withval], [jd_with_$1_arg=unspecified]) + + case "x$jd_with_$1_arg" in + xno) + jd_with_$1_library="no" + ;; + x) + dnl# AC_MSG_ERROR(--with-$1 requires a value-- try yes or no) + jd_with_$1_library="yes" + ;; + xunspecified) + ;; + xyes) + jd_with_$1_library="yes" + ;; + *) + jd_with_$1_library="yes" + jd_$1_include_dir="$jd_with_$1_arg"/include + jd_$1_library_dir="$jd_with_$1_arg"/lib + ;; + esac + + AC_ARG_WITH($1lib, + [ --with-$1lib=DIR $1 library in DIR], + [jd_with_$1lib_arg=$withval], [jd_with_$1lib_arg=unspecified]) + case "x$jd_with_$1lib_arg" in + xunspecified) + ;; + xno) + ;; + x) + AC_MSG_ERROR(--with-$1lib requres a value) + ;; + *) + jd_with_$1_library="yes" + jd_$1_library_dir="$jd_with_$1lib_arg" + ;; + esac + + AC_ARG_WITH($1inc, + [ --with-$1inc=DIR $1 include files in DIR], + [jd_with_$1inc_arg=$withval], [jd_with_$1inc_arg=unspecified]) + case "x$jd_with_$1inc_arg" in + x) + AC_MSG_ERROR(--with-$1inc requres a value) + ;; + xunspecified) + ;; + xno) + ;; + *) + jd_with_$1_library="yes" + jd_$1_include_dir="$jd_with_$1inc_arg" + ;; + esac +]) +dnl#}}} + +dnl# This function checks for the existence of the specified library $1 with +dnl# header file $2. If the library exists, then the shell variables will +dnl# be created: +dnl# jd_with_$1_library=yes/no, +dnl# jd_$1_inc_file +dnl# jd_$1_include_dir +dnl# jd_$1_library_dir +AC_DEFUN(JD_CHECK_FOR_LIBRARY, dnl#{{{ +[ + AC_REQUIRE([JD_EXPAND_PREFIX])dnl + dnl JD_UPPERCASE($1,JD_ARG1) + JD_WITH_LIBRARY_PATHS($1) + AC_MSG_CHECKING(for the $1 library and header files $2) + if test X"$jd_with_$1_library" != Xno + then + jd_$1_inc_file=$2 + dnl# jd_with_$1_library="yes" + + if test "X$jd_$1_inc_file" = "X" + then + jd_$1_inc_file=$1.h + fi + + if test X"$jd_$1_include_dir" = X + then + inc_and_lib_dirs="\ + $jd_prefix_incdir,$jd_prefix_libdir \ + /usr/local/$1/include,/usr/local/$1/lib \ + /usr/local/include/$1,/usr/local/lib \ + /usr/local/include,/usr/local/lib \ + /usr/include/$1,/usr/lib \ + /usr/$1/include,/usr/$1/lib \ + /usr/include,/usr/lib \ + /opt/include/$1,/opt/lib \ + /opt/$1/include,/opt/$1/lib \ + /opt/include,/opt/lib" + + case "$host_os" in + *darwin* ) + exts="dylib so a" + ;; + *cygwin* ) + exts="dll.a so a" + ;; + * ) + exts="so a" + esac + + xincfile="$jd_$1_inc_file" + xlibfile="lib$1" + jd_with_$1_library="no" + + for include_and_lib in $inc_and_lib_dirs + do + # Yuk. Is there a better way to set these variables?? + xincdir=`echo $include_and_lib | tr ',' ' ' | awk '{print [$]1}'` + xlibdir=`echo $include_and_lib | tr ',' ' ' | awk '{print [$]2}'` + found=0 + if test -r $xincdir/$xincfile + then + for E in $exts + do + if test -r "$xlibdir/$xlibfile.$E" + then + jd_$1_include_dir="$xincdir" + jd_$1_library_dir="$xlibdir" + jd_with_$1_library="yes" + found=1 + break + fi + done + fi + if test $found -eq 1 + then + break + fi + done + fi + fi + + if test X"$jd_$1_include_dir" != X -a "$jd_$1_library_dir" != X + then + AC_MSG_RESULT(yes: $jd_$1_library_dir and $jd_$1_include_dir) + jd_with_$1_library="yes" + dnl# Avoid using /usr/lib and /usr/include because of problems with + dnl# gcc on some solaris systems. + JD_ARG1[]_LIB=-L$jd_$1_library_dir + if test "X$jd_$1_library_dir" = "X/usr/lib" + then + JD_ARG1[]_LIB="" + else + JD_SET_RPATH($jd_$1_library_dir) + fi + + JD_ARG1[]_INC=-I$jd_$1_include_dir + if test "X$jd_$1_include_dir" = "X/usr/include" + then + JD_ARG1[]_INC="" + fi + else + AC_MSG_RESULT(no) + jd_with_$1_library="no" + JD_ARG1[]_INC="" + JD_ARG1[]_LIB="" + fi + AC_SUBST(JD_ARG1[]_LIB) + AC_SUBST(JD_ARG1[]_INC) +]) +dnl#}}} + +AC_DEFUN(JD_WITH_LIBRARY, dnl#{{{ +[ + JD_CHECK_FOR_LIBRARY($1, $2) + if test "$jd_with_$1_library" = "no" + then + AC_MSG_ERROR(unable to find the $1 library and header file $jd_$1_inc_file) + fi +]) +dnl#}}} + +AC_DEFUN(JD_SLANG_VERSION, dnl#{{{ +[ + slang_h=$jd_slang_include_dir/slang.h + AC_MSG_CHECKING(SLANG_VERSION in $slang_h) +slang_version=`grep "^#define *SLANG_VERSION " $slang_h | + awk '{ print [$]3 }'` +slang_major_version=`echo $slang_version | + awk '{ print int([$]1/10000) }'` +slang_minor_version=`echo $slang_version $slang_major_version | + awk '{ print int(([$]1 - [$]2*10000)/100) }'` +slang_patchlevel_version=`echo $slang_version $slang_major_version $slang_minor_version | + awk '{ print ([$]1 - [$]2*10000 - [$]3*100) }'` + +AC_MSG_RESULT($slang_major_version.$slang_minor_version.$slang_patchlevel_version) +AC_SUBST(slang_version) +AC_SUBST(slang_major_version) +AC_SUBST(slang_minor_version) +AC_SUBST(slang_patchlevel_version) +]) +#}}} + +AC_DEFUN(JD_SLANG_MODULE_INSTALL_DIR, dnl#{{{ +[ + AC_REQUIRE([JD_SLANG_VERSION]) + if test "X$slang_major_version" = "X1" + then + MODULE_INSTALL_DIR="$libdir/slang/modules" + else + MODULE_INSTALL_DIR="$libdir/slang/v$slang_major_version/modules" + fi + SL_FILES_INSTALL_DIR=$datadir/slsh/local-packages + AC_SUBST(MODULE_INSTALL_DIR) + AC_SUBST(SL_FILES_INSTALL_DIR) +]) +#}}} + +AC_DEFUN(JD_CHECK_LONG_LONG, dnl#{{{ +[ + AC_CHECK_TYPES(long long) + AC_CHECK_SIZEOF(long long) +]) +dnl#}}} + +AC_DEFUN(JD_LARGE_FILE_SUPPORTXXX, dnl#{{{ +[ + AC_REQUIRE([JD_CHECK_LONG_LONG]) + AC_MSG_CHECKING(whether to explicitly activate long file support) + AC_DEFINE(_LARGEFILE_SOURCE, 1) + AC_DEFINE(_FILE_OFFSET_BITS, 64) + jd_large_file_support=no + if test X$ac_cv_type_long_long = Xyes + then + if test $ac_cv_sizeof_long_long -ge 8 + then + jd_large_file_support=yes + fi + fi + + if test $jd_large_file_support = yes + then + AC_DEFINE(HAVE_LARGEFILE_SUPPORT, 1) + AC_MSG_RESULT(yes) + else + AC_MSG_RESULT(no) + fi +]) +dnl#}}} + +AC_DEFUN(JD_LARGE_FILE_SUPPORT, dnl#{{{ +[ + AC_SYS_LARGEFILE + AC_FUNC_FSEEKO + AC_TYPE_OFF_T + AC_CHECK_SIZEOF(off_t) +]) +#}}} + +AC_DEFUN(JD_HAVE_ISINF, dnl#{{{ +[ + AC_MSG_CHECKING([for isinf]) + AC_LINK_IFELSE([AC_LANG_PROGRAM( [[#include ]], [[isinf (0.0);]])], + [AC_MSG_RESULT([yes]) + AC_DEFINE(HAVE_ISINF, 1)]) +]) +#}}} diff --git a/modules/maplib/autoconf/config.guess b/modules/maplib/autoconf/config.guess new file mode 100755 index 0000000..396482d --- /dev/null +++ b/modules/maplib/autoconf/config.guess @@ -0,0 +1,1500 @@ +#! /bin/sh +# Attempt to guess a canonical system name. +# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, +# 2000, 2001, 2002, 2003, 2004, 2005, 2006 Free Software Foundation, +# Inc. + +timestamp='2006-07-02' + +# This file is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA +# 02110-1301, USA. +# +# As a special exception to the GNU General Public License, if you +# distribute this file as part of a program that contains a +# configuration script generated by Autoconf, you may include it under +# the same distribution terms that you use for the rest of that program. + + +# Originally written by Per Bothner . +# Please send patches to . Submit a context +# diff and a properly formatted ChangeLog entry. +# +# This script attempts to guess a canonical system name similar to +# config.sub. If it succeeds, it prints the system name on stdout, and +# exits with 0. Otherwise, it exits with 1. +# +# The plan is that this can be called by configure scripts if you +# don't specify an explicit build system type. + +me=`echo "$0" | sed -e 's,.*/,,'` + +usage="\ +Usage: $0 [OPTION] + +Output the configuration name of the system \`$me' is run on. + +Operation modes: + -h, --help print this help, then exit + -t, --time-stamp print date of last modification, then exit + -v, --version print version number, then exit + +Report bugs and patches to ." + +version="\ +GNU config.guess ($timestamp) + +Originally written by Per Bothner. +Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005 +Free Software Foundation, Inc. + +This is free software; see the source for copying conditions. There is NO +warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." + +help=" +Try \`$me --help' for more information." + +# Parse command line +while test $# -gt 0 ; do + case $1 in + --time-stamp | --time* | -t ) + echo "$timestamp" ; exit ;; + --version | -v ) + echo "$version" ; exit ;; + --help | --h* | -h ) + echo "$usage"; exit ;; + -- ) # Stop option processing + shift; break ;; + - ) # Use stdin as input. + break ;; + -* ) + echo "$me: invalid option $1$help" >&2 + exit 1 ;; + * ) + break ;; + esac +done + +if test $# != 0; then + echo "$me: too many arguments$help" >&2 + exit 1 +fi + +trap 'exit 1' 1 2 15 + +# CC_FOR_BUILD -- compiler used by this script. Note that the use of a +# compiler to aid in system detection is discouraged as it requires +# temporary files to be created and, as you can see below, it is a +# headache to deal with in a portable fashion. + +# Historically, `CC_FOR_BUILD' used to be named `HOST_CC'. We still +# use `HOST_CC' if defined, but it is deprecated. + +# Portable tmp directory creation inspired by the Autoconf team. + +set_cc_for_build=' +trap "exitcode=\$?; (rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null) && exit \$exitcode" 0 ; +trap "rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null; exit 1" 1 2 13 15 ; +: ${TMPDIR=/tmp} ; + { tmp=`(umask 077 && mktemp -d "$TMPDIR/cgXXXXXX") 2>/dev/null` && test -n "$tmp" && test -d "$tmp" ; } || + { test -n "$RANDOM" && tmp=$TMPDIR/cg$$-$RANDOM && (umask 077 && mkdir $tmp) ; } || + { tmp=$TMPDIR/cg-$$ && (umask 077 && mkdir $tmp) && echo "Warning: creating insecure temp directory" >&2 ; } || + { echo "$me: cannot create a temporary directory in $TMPDIR" >&2 ; exit 1 ; } ; +dummy=$tmp/dummy ; +tmpfiles="$dummy.c $dummy.o $dummy.rel $dummy" ; +case $CC_FOR_BUILD,$HOST_CC,$CC in + ,,) echo "int x;" > $dummy.c ; + for c in cc gcc c89 c99 ; do + if ($c -c -o $dummy.o $dummy.c) >/dev/null 2>&1 ; then + CC_FOR_BUILD="$c"; break ; + fi ; + done ; + if test x"$CC_FOR_BUILD" = x ; then + CC_FOR_BUILD=no_compiler_found ; + fi + ;; + ,,*) CC_FOR_BUILD=$CC ;; + ,*,*) CC_FOR_BUILD=$HOST_CC ;; +esac ; set_cc_for_build= ;' + +# This is needed to find uname on a Pyramid OSx when run in the BSD universe. +# (ghazi@noc.rutgers.edu 1994-08-24) +if (test -f /.attbin/uname) >/dev/null 2>&1 ; then + PATH=$PATH:/.attbin ; export PATH +fi + +UNAME_MACHINE=`(uname -m) 2>/dev/null` || UNAME_MACHINE=unknown +UNAME_RELEASE=`(uname -r) 2>/dev/null` || UNAME_RELEASE=unknown +UNAME_SYSTEM=`(uname -s) 2>/dev/null` || UNAME_SYSTEM=unknown +UNAME_VERSION=`(uname -v) 2>/dev/null` || UNAME_VERSION=unknown + +# Note: order is significant - the case branches are not exclusive. + +case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in + *:NetBSD:*:*) + # NetBSD (nbsd) targets should (where applicable) match one or + # more of the tupples: *-*-netbsdelf*, *-*-netbsdaout*, + # *-*-netbsdecoff* and *-*-netbsd*. For targets that recently + # switched to ELF, *-*-netbsd* would select the old + # object file format. This provides both forward + # compatibility and a consistent mechanism for selecting the + # object file format. + # + # Note: NetBSD doesn't particularly care about the vendor + # portion of the name. We always set it to "unknown". + sysctl="sysctl -n hw.machine_arch" + UNAME_MACHINE_ARCH=`(/sbin/$sysctl 2>/dev/null || \ + /usr/sbin/$sysctl 2>/dev/null || echo unknown)` + case "${UNAME_MACHINE_ARCH}" in + armeb) machine=armeb-unknown ;; + arm*) machine=arm-unknown ;; + sh3el) machine=shl-unknown ;; + sh3eb) machine=sh-unknown ;; + *) machine=${UNAME_MACHINE_ARCH}-unknown ;; + esac + # The Operating System including object format, if it has switched + # to ELF recently, or will in the future. + case "${UNAME_MACHINE_ARCH}" in + arm*|i386|m68k|ns32k|sh3*|sparc|vax) + eval $set_cc_for_build + if echo __ELF__ | $CC_FOR_BUILD -E - 2>/dev/null \ + | grep __ELF__ >/dev/null + then + # Once all utilities can be ECOFF (netbsdecoff) or a.out (netbsdaout). + # Return netbsd for either. FIX? + os=netbsd + else + os=netbsdelf + fi + ;; + *) + os=netbsd + ;; + esac + # The OS release + # Debian GNU/NetBSD machines have a different userland, and + # thus, need a distinct triplet. However, they do not need + # kernel version information, so it can be replaced with a + # suitable tag, in the style of linux-gnu. + case "${UNAME_VERSION}" in + Debian*) + release='-gnu' + ;; + *) + release=`echo ${UNAME_RELEASE}|sed -e 's/[-_].*/\./'` + ;; + esac + # Since CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM: + # contains redundant information, the shorter form: + # CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM is used. + echo "${machine}-${os}${release}" + exit ;; + *:OpenBSD:*:*) + UNAME_MACHINE_ARCH=`arch | sed 's/OpenBSD.//'` + echo ${UNAME_MACHINE_ARCH}-unknown-openbsd${UNAME_RELEASE} + exit ;; + *:ekkoBSD:*:*) + echo ${UNAME_MACHINE}-unknown-ekkobsd${UNAME_RELEASE} + exit ;; + *:SolidBSD:*:*) + echo ${UNAME_MACHINE}-unknown-solidbsd${UNAME_RELEASE} + exit ;; + macppc:MirBSD:*:*) + echo powerpc-unknown-mirbsd${UNAME_RELEASE} + exit ;; + *:MirBSD:*:*) + echo ${UNAME_MACHINE}-unknown-mirbsd${UNAME_RELEASE} + exit ;; + alpha:OSF1:*:*) + case $UNAME_RELEASE in + *4.0) + UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $3}'` + ;; + *5.*) + UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $4}'` + ;; + esac + # According to Compaq, /usr/sbin/psrinfo has been available on + # OSF/1 and Tru64 systems produced since 1995. I hope that + # covers most systems running today. This code pipes the CPU + # types through head -n 1, so we only detect the type of CPU 0. + ALPHA_CPU_TYPE=`/usr/sbin/psrinfo -v | sed -n -e 's/^ The alpha \(.*\) processor.*$/\1/p' | head -n 1` + case "$ALPHA_CPU_TYPE" in + "EV4 (21064)") + UNAME_MACHINE="alpha" ;; + "EV4.5 (21064)") + UNAME_MACHINE="alpha" ;; + "LCA4 (21066/21068)") + UNAME_MACHINE="alpha" ;; + "EV5 (21164)") + UNAME_MACHINE="alphaev5" ;; + "EV5.6 (21164A)") + UNAME_MACHINE="alphaev56" ;; + "EV5.6 (21164PC)") + UNAME_MACHINE="alphapca56" ;; + "EV5.7 (21164PC)") + UNAME_MACHINE="alphapca57" ;; + "EV6 (21264)") + UNAME_MACHINE="alphaev6" ;; + "EV6.7 (21264A)") + UNAME_MACHINE="alphaev67" ;; + "EV6.8CB (21264C)") + UNAME_MACHINE="alphaev68" ;; + "EV6.8AL (21264B)") + UNAME_MACHINE="alphaev68" ;; + "EV6.8CX (21264D)") + UNAME_MACHINE="alphaev68" ;; + "EV6.9A (21264/EV69A)") + UNAME_MACHINE="alphaev69" ;; + "EV7 (21364)") + UNAME_MACHINE="alphaev7" ;; + "EV7.9 (21364A)") + UNAME_MACHINE="alphaev79" ;; + esac + # A Pn.n version is a patched version. + # A Vn.n version is a released version. + # A Tn.n version is a released field test version. + # A Xn.n version is an unreleased experimental baselevel. + # 1.2 uses "1.2" for uname -r. + echo ${UNAME_MACHINE}-dec-osf`echo ${UNAME_RELEASE} | sed -e 's/^[PVTX]//' | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'` + exit ;; + Alpha\ *:Windows_NT*:*) + # How do we know it's Interix rather than the generic POSIX subsystem? + # Should we change UNAME_MACHINE based on the output of uname instead + # of the specific Alpha model? + echo alpha-pc-interix + exit ;; + 21064:Windows_NT:50:3) + echo alpha-dec-winnt3.5 + exit ;; + Amiga*:UNIX_System_V:4.0:*) + echo m68k-unknown-sysv4 + exit ;; + *:[Aa]miga[Oo][Ss]:*:*) + echo ${UNAME_MACHINE}-unknown-amigaos + exit ;; + *:[Mm]orph[Oo][Ss]:*:*) + echo ${UNAME_MACHINE}-unknown-morphos + exit ;; + *:OS/390:*:*) + echo i370-ibm-openedition + exit ;; + *:z/VM:*:*) + echo s390-ibm-zvmoe + exit ;; + *:OS400:*:*) + echo powerpc-ibm-os400 + exit ;; + arm:RISC*:1.[012]*:*|arm:riscix:1.[012]*:*) + echo arm-acorn-riscix${UNAME_RELEASE} + exit ;; + arm:riscos:*:*|arm:RISCOS:*:*) + echo arm-unknown-riscos + exit ;; + SR2?01:HI-UX/MPP:*:* | SR8000:HI-UX/MPP:*:*) + echo hppa1.1-hitachi-hiuxmpp + exit ;; + Pyramid*:OSx*:*:* | MIS*:OSx*:*:* | MIS*:SMP_DC-OSx*:*:*) + # akee@wpdis03.wpafb.af.mil (Earle F. Ake) contributed MIS and NILE. + if test "`(/bin/universe) 2>/dev/null`" = att ; then + echo pyramid-pyramid-sysv3 + else + echo pyramid-pyramid-bsd + fi + exit ;; + NILE*:*:*:dcosx) + echo pyramid-pyramid-svr4 + exit ;; + DRS?6000:unix:4.0:6*) + echo sparc-icl-nx6 + exit ;; + DRS?6000:UNIX_SV:4.2*:7* | DRS?6000:isis:4.2*:7*) + case `/usr/bin/uname -p` in + sparc) echo sparc-icl-nx7; exit ;; + esac ;; + sun4H:SunOS:5.*:*) + echo sparc-hal-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit ;; + sun4*:SunOS:5.*:* | tadpole*:SunOS:5.*:*) + echo sparc-sun-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit ;; + i86pc:SunOS:5.*:*) + echo i386-pc-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit ;; + sun4*:SunOS:6*:*) + # According to config.sub, this is the proper way to canonicalize + # SunOS6. Hard to guess exactly what SunOS6 will be like, but + # it's likely to be more like Solaris than SunOS4. + echo sparc-sun-solaris3`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit ;; + sun4*:SunOS:*:*) + case "`/usr/bin/arch -k`" in + Series*|S4*) + UNAME_RELEASE=`uname -v` + ;; + esac + # Japanese Language versions have a version number like `4.1.3-JL'. + echo sparc-sun-sunos`echo ${UNAME_RELEASE}|sed -e 's/-/_/'` + exit ;; + sun3*:SunOS:*:*) + echo m68k-sun-sunos${UNAME_RELEASE} + exit ;; + sun*:*:4.2BSD:*) + UNAME_RELEASE=`(sed 1q /etc/motd | awk '{print substr($5,1,3)}') 2>/dev/null` + test "x${UNAME_RELEASE}" = "x" && UNAME_RELEASE=3 + case "`/bin/arch`" in + sun3) + echo m68k-sun-sunos${UNAME_RELEASE} + ;; + sun4) + echo sparc-sun-sunos${UNAME_RELEASE} + ;; + esac + exit ;; + aushp:SunOS:*:*) + echo sparc-auspex-sunos${UNAME_RELEASE} + exit ;; + # The situation for MiNT is a little confusing. The machine name + # can be virtually everything (everything which is not + # "atarist" or "atariste" at least should have a processor + # > m68000). The system name ranges from "MiNT" over "FreeMiNT" + # to the lowercase version "mint" (or "freemint"). Finally + # the system name "TOS" denotes a system which is actually not + # MiNT. But MiNT is downward compatible to TOS, so this should + # be no problem. + atarist[e]:*MiNT:*:* | atarist[e]:*mint:*:* | atarist[e]:*TOS:*:*) + echo m68k-atari-mint${UNAME_RELEASE} + exit ;; + atari*:*MiNT:*:* | atari*:*mint:*:* | atarist[e]:*TOS:*:*) + echo m68k-atari-mint${UNAME_RELEASE} + exit ;; + *falcon*:*MiNT:*:* | *falcon*:*mint:*:* | *falcon*:*TOS:*:*) + echo m68k-atari-mint${UNAME_RELEASE} + exit ;; + milan*:*MiNT:*:* | milan*:*mint:*:* | *milan*:*TOS:*:*) + echo m68k-milan-mint${UNAME_RELEASE} + exit ;; + hades*:*MiNT:*:* | hades*:*mint:*:* | *hades*:*TOS:*:*) + echo m68k-hades-mint${UNAME_RELEASE} + exit ;; + *:*MiNT:*:* | *:*mint:*:* | *:*TOS:*:*) + echo m68k-unknown-mint${UNAME_RELEASE} + exit ;; + m68k:machten:*:*) + echo m68k-apple-machten${UNAME_RELEASE} + exit ;; + powerpc:machten:*:*) + echo powerpc-apple-machten${UNAME_RELEASE} + exit ;; + RISC*:Mach:*:*) + echo mips-dec-mach_bsd4.3 + exit ;; + RISC*:ULTRIX:*:*) + echo mips-dec-ultrix${UNAME_RELEASE} + exit ;; + VAX*:ULTRIX*:*:*) + echo vax-dec-ultrix${UNAME_RELEASE} + exit ;; + 2020:CLIX:*:* | 2430:CLIX:*:*) + echo clipper-intergraph-clix${UNAME_RELEASE} + exit ;; + mips:*:*:UMIPS | mips:*:*:RISCos) + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c +#ifdef __cplusplus +#include /* for printf() prototype */ + int main (int argc, char *argv[]) { +#else + int main (argc, argv) int argc; char *argv[]; { +#endif + #if defined (host_mips) && defined (MIPSEB) + #if defined (SYSTYPE_SYSV) + printf ("mips-mips-riscos%ssysv\n", argv[1]); exit (0); + #endif + #if defined (SYSTYPE_SVR4) + printf ("mips-mips-riscos%ssvr4\n", argv[1]); exit (0); + #endif + #if defined (SYSTYPE_BSD43) || defined(SYSTYPE_BSD) + printf ("mips-mips-riscos%sbsd\n", argv[1]); exit (0); + #endif + #endif + exit (-1); + } +EOF + $CC_FOR_BUILD -o $dummy $dummy.c && + dummyarg=`echo "${UNAME_RELEASE}" | sed -n 's/\([0-9]*\).*/\1/p'` && + SYSTEM_NAME=`$dummy $dummyarg` && + { echo "$SYSTEM_NAME"; exit; } + echo mips-mips-riscos${UNAME_RELEASE} + exit ;; + Motorola:PowerMAX_OS:*:*) + echo powerpc-motorola-powermax + exit ;; + Motorola:*:4.3:PL8-*) + echo powerpc-harris-powermax + exit ;; + Night_Hawk:*:*:PowerMAX_OS | Synergy:PowerMAX_OS:*:*) + echo powerpc-harris-powermax + exit ;; + Night_Hawk:Power_UNIX:*:*) + echo powerpc-harris-powerunix + exit ;; + m88k:CX/UX:7*:*) + echo m88k-harris-cxux7 + exit ;; + m88k:*:4*:R4*) + echo m88k-motorola-sysv4 + exit ;; + m88k:*:3*:R3*) + echo m88k-motorola-sysv3 + exit ;; + AViiON:dgux:*:*) + # DG/UX returns AViiON for all architectures + UNAME_PROCESSOR=`/usr/bin/uname -p` + if [ $UNAME_PROCESSOR = mc88100 ] || [ $UNAME_PROCESSOR = mc88110 ] + then + if [ ${TARGET_BINARY_INTERFACE}x = m88kdguxelfx ] || \ + [ ${TARGET_BINARY_INTERFACE}x = x ] + then + echo m88k-dg-dgux${UNAME_RELEASE} + else + echo m88k-dg-dguxbcs${UNAME_RELEASE} + fi + else + echo i586-dg-dgux${UNAME_RELEASE} + fi + exit ;; + M88*:DolphinOS:*:*) # DolphinOS (SVR3) + echo m88k-dolphin-sysv3 + exit ;; + M88*:*:R3*:*) + # Delta 88k system running SVR3 + echo m88k-motorola-sysv3 + exit ;; + XD88*:*:*:*) # Tektronix XD88 system running UTekV (SVR3) + echo m88k-tektronix-sysv3 + exit ;; + Tek43[0-9][0-9]:UTek:*:*) # Tektronix 4300 system running UTek (BSD) + echo m68k-tektronix-bsd + exit ;; + *:IRIX*:*:*) + echo mips-sgi-irix`echo ${UNAME_RELEASE}|sed -e 's/-/_/g'` + exit ;; + ????????:AIX?:[12].1:2) # AIX 2.2.1 or AIX 2.1.1 is RT/PC AIX. + echo romp-ibm-aix # uname -m gives an 8 hex-code CPU id + exit ;; # Note that: echo "'`uname -s`'" gives 'AIX ' + i*86:AIX:*:*) + echo i386-ibm-aix + exit ;; + ia64:AIX:*:*) + if [ -x /usr/bin/oslevel ] ; then + IBM_REV=`/usr/bin/oslevel` + else + IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE} + fi + echo ${UNAME_MACHINE}-ibm-aix${IBM_REV} + exit ;; + *:AIX:2:3) + if grep bos325 /usr/include/stdio.h >/dev/null 2>&1; then + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c + #include + + main() + { + if (!__power_pc()) + exit(1); + puts("powerpc-ibm-aix3.2.5"); + exit(0); + } +EOF + if $CC_FOR_BUILD -o $dummy $dummy.c && SYSTEM_NAME=`$dummy` + then + echo "$SYSTEM_NAME" + else + echo rs6000-ibm-aix3.2.5 + fi + elif grep bos324 /usr/include/stdio.h >/dev/null 2>&1; then + echo rs6000-ibm-aix3.2.4 + else + echo rs6000-ibm-aix3.2 + fi + exit ;; + *:AIX:*:[45]) + IBM_CPU_ID=`/usr/sbin/lsdev -C -c processor -S available | sed 1q | awk '{ print $1 }'` + if /usr/sbin/lsattr -El ${IBM_CPU_ID} | grep ' POWER' >/dev/null 2>&1; then + IBM_ARCH=rs6000 + else + IBM_ARCH=powerpc + fi + if [ -x /usr/bin/oslevel ] ; then + IBM_REV=`/usr/bin/oslevel` + else + IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE} + fi + echo ${IBM_ARCH}-ibm-aix${IBM_REV} + exit ;; + *:AIX:*:*) + echo rs6000-ibm-aix + exit ;; + ibmrt:4.4BSD:*|romp-ibm:BSD:*) + echo romp-ibm-bsd4.4 + exit ;; + ibmrt:*BSD:*|romp-ibm:BSD:*) # covers RT/PC BSD and + echo romp-ibm-bsd${UNAME_RELEASE} # 4.3 with uname added to + exit ;; # report: romp-ibm BSD 4.3 + *:BOSX:*:*) + echo rs6000-bull-bosx + exit ;; + DPX/2?00:B.O.S.:*:*) + echo m68k-bull-sysv3 + exit ;; + 9000/[34]??:4.3bsd:1.*:*) + echo m68k-hp-bsd + exit ;; + hp300:4.4BSD:*:* | 9000/[34]??:4.3bsd:2.*:*) + echo m68k-hp-bsd4.4 + exit ;; + 9000/[34678]??:HP-UX:*:*) + HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'` + case "${UNAME_MACHINE}" in + 9000/31? ) HP_ARCH=m68000 ;; + 9000/[34]?? ) HP_ARCH=m68k ;; + 9000/[678][0-9][0-9]) + if [ -x /usr/bin/getconf ]; then + sc_cpu_version=`/usr/bin/getconf SC_CPU_VERSION 2>/dev/null` + sc_kernel_bits=`/usr/bin/getconf SC_KERNEL_BITS 2>/dev/null` + case "${sc_cpu_version}" in + 523) HP_ARCH="hppa1.0" ;; # CPU_PA_RISC1_0 + 528) HP_ARCH="hppa1.1" ;; # CPU_PA_RISC1_1 + 532) # CPU_PA_RISC2_0 + case "${sc_kernel_bits}" in + 32) HP_ARCH="hppa2.0n" ;; + 64) HP_ARCH="hppa2.0w" ;; + '') HP_ARCH="hppa2.0" ;; # HP-UX 10.20 + esac ;; + esac + fi + if [ "${HP_ARCH}" = "" ]; then + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c + + #define _HPUX_SOURCE + #include + #include + + int main () + { + #if defined(_SC_KERNEL_BITS) + long bits = sysconf(_SC_KERNEL_BITS); + #endif + long cpu = sysconf (_SC_CPU_VERSION); + + switch (cpu) + { + case CPU_PA_RISC1_0: puts ("hppa1.0"); break; + case CPU_PA_RISC1_1: puts ("hppa1.1"); break; + case CPU_PA_RISC2_0: + #if defined(_SC_KERNEL_BITS) + switch (bits) + { + case 64: puts ("hppa2.0w"); break; + case 32: puts ("hppa2.0n"); break; + default: puts ("hppa2.0"); break; + } break; + #else /* !defined(_SC_KERNEL_BITS) */ + puts ("hppa2.0"); break; + #endif + default: puts ("hppa1.0"); break; + } + exit (0); + } +EOF + (CCOPTS= $CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null) && HP_ARCH=`$dummy` + test -z "$HP_ARCH" && HP_ARCH=hppa + fi ;; + esac + if [ ${HP_ARCH} = "hppa2.0w" ] + then + eval $set_cc_for_build + + # hppa2.0w-hp-hpux* has a 64-bit kernel and a compiler generating + # 32-bit code. hppa64-hp-hpux* has the same kernel and a compiler + # generating 64-bit code. GNU and HP use different nomenclature: + # + # $ CC_FOR_BUILD=cc ./config.guess + # => hppa2.0w-hp-hpux11.23 + # $ CC_FOR_BUILD="cc +DA2.0w" ./config.guess + # => hppa64-hp-hpux11.23 + + if echo __LP64__ | (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) | + grep __LP64__ >/dev/null + then + HP_ARCH="hppa2.0w" + else + HP_ARCH="hppa64" + fi + fi + echo ${HP_ARCH}-hp-hpux${HPUX_REV} + exit ;; + ia64:HP-UX:*:*) + HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'` + echo ia64-hp-hpux${HPUX_REV} + exit ;; + 3050*:HI-UX:*:*) + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c + #include + int + main () + { + long cpu = sysconf (_SC_CPU_VERSION); + /* The order matters, because CPU_IS_HP_MC68K erroneously returns + true for CPU_PA_RISC1_0. CPU_IS_PA_RISC returns correct + results, however. */ + if (CPU_IS_PA_RISC (cpu)) + { + switch (cpu) + { + case CPU_PA_RISC1_0: puts ("hppa1.0-hitachi-hiuxwe2"); break; + case CPU_PA_RISC1_1: puts ("hppa1.1-hitachi-hiuxwe2"); break; + case CPU_PA_RISC2_0: puts ("hppa2.0-hitachi-hiuxwe2"); break; + default: puts ("hppa-hitachi-hiuxwe2"); break; + } + } + else if (CPU_IS_HP_MC68K (cpu)) + puts ("m68k-hitachi-hiuxwe2"); + else puts ("unknown-hitachi-hiuxwe2"); + exit (0); + } +EOF + $CC_FOR_BUILD -o $dummy $dummy.c && SYSTEM_NAME=`$dummy` && + { echo "$SYSTEM_NAME"; exit; } + echo unknown-hitachi-hiuxwe2 + exit ;; + 9000/7??:4.3bsd:*:* | 9000/8?[79]:4.3bsd:*:* ) + echo hppa1.1-hp-bsd + exit ;; + 9000/8??:4.3bsd:*:*) + echo hppa1.0-hp-bsd + exit ;; + *9??*:MPE/iX:*:* | *3000*:MPE/iX:*:*) + echo hppa1.0-hp-mpeix + exit ;; + hp7??:OSF1:*:* | hp8?[79]:OSF1:*:* ) + echo hppa1.1-hp-osf + exit ;; + hp8??:OSF1:*:*) + echo hppa1.0-hp-osf + exit ;; + i*86:OSF1:*:*) + if [ -x /usr/sbin/sysversion ] ; then + echo ${UNAME_MACHINE}-unknown-osf1mk + else + echo ${UNAME_MACHINE}-unknown-osf1 + fi + exit ;; + parisc*:Lites*:*:*) + echo hppa1.1-hp-lites + exit ;; + C1*:ConvexOS:*:* | convex:ConvexOS:C1*:*) + echo c1-convex-bsd + exit ;; + C2*:ConvexOS:*:* | convex:ConvexOS:C2*:*) + if getsysinfo -f scalar_acc + then echo c32-convex-bsd + else echo c2-convex-bsd + fi + exit ;; + C34*:ConvexOS:*:* | convex:ConvexOS:C34*:*) + echo c34-convex-bsd + exit ;; + C38*:ConvexOS:*:* | convex:ConvexOS:C38*:*) + echo c38-convex-bsd + exit ;; + C4*:ConvexOS:*:* | convex:ConvexOS:C4*:*) + echo c4-convex-bsd + exit ;; + CRAY*Y-MP:*:*:*) + echo ymp-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + exit ;; + CRAY*[A-Z]90:*:*:*) + echo ${UNAME_MACHINE}-cray-unicos${UNAME_RELEASE} \ + | sed -e 's/CRAY.*\([A-Z]90\)/\1/' \ + -e y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/ \ + -e 's/\.[^.]*$/.X/' + exit ;; + CRAY*TS:*:*:*) + echo t90-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + exit ;; + CRAY*T3E:*:*:*) + echo alphaev5-cray-unicosmk${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + exit ;; + CRAY*SV1:*:*:*) + echo sv1-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + exit ;; + *:UNICOS/mp:*:*) + echo craynv-cray-unicosmp${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + exit ;; + F30[01]:UNIX_System_V:*:* | F700:UNIX_System_V:*:*) + FUJITSU_PROC=`uname -m | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'` + FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'` + FUJITSU_REL=`echo ${UNAME_RELEASE} | sed -e 's/ /_/'` + echo "${FUJITSU_PROC}-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}" + exit ;; + 5000:UNIX_System_V:4.*:*) + FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'` + FUJITSU_REL=`echo ${UNAME_RELEASE} | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/ /_/'` + echo "sparc-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}" + exit ;; + i*86:BSD/386:*:* | i*86:BSD/OS:*:* | *:Ascend\ Embedded/OS:*:*) + echo ${UNAME_MACHINE}-pc-bsdi${UNAME_RELEASE} + exit ;; + sparc*:BSD/OS:*:*) + echo sparc-unknown-bsdi${UNAME_RELEASE} + exit ;; + *:BSD/OS:*:*) + echo ${UNAME_MACHINE}-unknown-bsdi${UNAME_RELEASE} + exit ;; + *:FreeBSD:*:*) + case ${UNAME_MACHINE} in + pc98) + echo i386-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;; + amd64) + echo x86_64-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;; + *) + echo ${UNAME_MACHINE}-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;; + esac + exit ;; + i*:CYGWIN*:*) + echo ${UNAME_MACHINE}-pc-cygwin + exit ;; + i*:MINGW*:*) + echo ${UNAME_MACHINE}-pc-mingw32 + exit ;; + i*:windows32*:*) + # uname -m includes "-pc" on this system. + echo ${UNAME_MACHINE}-mingw32 + exit ;; + i*:PW*:*) + echo ${UNAME_MACHINE}-pc-pw32 + exit ;; + x86:Interix*:[3456]*) + echo i586-pc-interix${UNAME_RELEASE} + exit ;; + EM64T:Interix*:[3456]*) + echo x86_64-unknown-interix${UNAME_RELEASE} + exit ;; + [345]86:Windows_95:* | [345]86:Windows_98:* | [345]86:Windows_NT:*) + echo i${UNAME_MACHINE}-pc-mks + exit ;; + i*:Windows_NT*:* | Pentium*:Windows_NT*:*) + # How do we know it's Interix rather than the generic POSIX subsystem? + # It also conflicts with pre-2.0 versions of AT&T UWIN. Should we + # UNAME_MACHINE based on the output of uname instead of i386? + echo i586-pc-interix + exit ;; + i*:UWIN*:*) + echo ${UNAME_MACHINE}-pc-uwin + exit ;; + amd64:CYGWIN*:*:* | x86_64:CYGWIN*:*:*) + echo x86_64-unknown-cygwin + exit ;; + p*:CYGWIN*:*) + echo powerpcle-unknown-cygwin + exit ;; + prep*:SunOS:5.*:*) + echo powerpcle-unknown-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit ;; + *:GNU:*:*) + # the GNU system + echo `echo ${UNAME_MACHINE}|sed -e 's,[-/].*$,,'`-unknown-gnu`echo ${UNAME_RELEASE}|sed -e 's,/.*$,,'` + exit ;; + *:GNU/*:*:*) + # other systems with GNU libc and userland + echo ${UNAME_MACHINE}-unknown-`echo ${UNAME_SYSTEM} | sed 's,^[^/]*/,,' | tr '[A-Z]' '[a-z]'``echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`-gnu + exit ;; + i*86:Minix:*:*) + echo ${UNAME_MACHINE}-pc-minix + exit ;; + arm*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; + avr32*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; + cris:Linux:*:*) + echo cris-axis-linux-gnu + exit ;; + crisv32:Linux:*:*) + echo crisv32-axis-linux-gnu + exit ;; + frv:Linux:*:*) + echo frv-unknown-linux-gnu + exit ;; + ia64:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; + m32r*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; + m68*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; + mips:Linux:*:*) + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c + #undef CPU + #undef mips + #undef mipsel + #if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL) || defined(MIPSEL) + CPU=mipsel + #else + #if defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB) || defined(MIPSEB) + CPU=mips + #else + CPU= + #endif + #endif +EOF + eval "`$CC_FOR_BUILD -E $dummy.c 2>/dev/null | sed -n ' + /^CPU/{ + s: ::g + p + }'`" + test x"${CPU}" != x && { echo "${CPU}-unknown-linux-gnu"; exit; } + ;; + mips64:Linux:*:*) + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c + #undef CPU + #undef mips64 + #undef mips64el + #if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL) || defined(MIPSEL) + CPU=mips64el + #else + #if defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB) || defined(MIPSEB) + CPU=mips64 + #else + CPU= + #endif + #endif +EOF + eval "`$CC_FOR_BUILD -E $dummy.c 2>/dev/null | sed -n ' + /^CPU/{ + s: ::g + p + }'`" + test x"${CPU}" != x && { echo "${CPU}-unknown-linux-gnu"; exit; } + ;; + or32:Linux:*:*) + echo or32-unknown-linux-gnu + exit ;; + ppc:Linux:*:*) + echo powerpc-unknown-linux-gnu + exit ;; + ppc64:Linux:*:*) + echo powerpc64-unknown-linux-gnu + exit ;; + alpha:Linux:*:*) + case `sed -n '/^cpu model/s/^.*: \(.*\)/\1/p' < /proc/cpuinfo` in + EV5) UNAME_MACHINE=alphaev5 ;; + EV56) UNAME_MACHINE=alphaev56 ;; + PCA56) UNAME_MACHINE=alphapca56 ;; + PCA57) UNAME_MACHINE=alphapca56 ;; + EV6) UNAME_MACHINE=alphaev6 ;; + EV67) UNAME_MACHINE=alphaev67 ;; + EV68*) UNAME_MACHINE=alphaev68 ;; + esac + objdump --private-headers /bin/sh | grep ld.so.1 >/dev/null + if test "$?" = 0 ; then LIBC="libc1" ; else LIBC="" ; fi + echo ${UNAME_MACHINE}-unknown-linux-gnu${LIBC} + exit ;; + parisc:Linux:*:* | hppa:Linux:*:*) + # Look for CPU level + case `grep '^cpu[^a-z]*:' /proc/cpuinfo 2>/dev/null | cut -d' ' -f2` in + PA7*) echo hppa1.1-unknown-linux-gnu ;; + PA8*) echo hppa2.0-unknown-linux-gnu ;; + *) echo hppa-unknown-linux-gnu ;; + esac + exit ;; + parisc64:Linux:*:* | hppa64:Linux:*:*) + echo hppa64-unknown-linux-gnu + exit ;; + s390:Linux:*:* | s390x:Linux:*:*) + echo ${UNAME_MACHINE}-ibm-linux + exit ;; + sh64*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; + sh*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; + sparc:Linux:*:* | sparc64:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; + vax:Linux:*:*) + echo ${UNAME_MACHINE}-dec-linux-gnu + exit ;; + x86_64:Linux:*:*) + echo x86_64-unknown-linux-gnu + exit ;; + i*86:Linux:*:*) + # The BFD linker knows what the default object file format is, so + # first see if it will tell us. cd to the root directory to prevent + # problems with other programs or directories called `ld' in the path. + # Set LC_ALL=C to ensure ld outputs messages in English. + ld_supported_targets=`cd /; LC_ALL=C ld --help 2>&1 \ + | sed -ne '/supported targets:/!d + s/[ ][ ]*/ /g + s/.*supported targets: *// + s/ .*// + p'` + case "$ld_supported_targets" in + elf32-i386) + TENTATIVE="${UNAME_MACHINE}-pc-linux-gnu" + ;; + a.out-i386-linux) + echo "${UNAME_MACHINE}-pc-linux-gnuaout" + exit ;; + coff-i386) + echo "${UNAME_MACHINE}-pc-linux-gnucoff" + exit ;; + "") + # Either a pre-BFD a.out linker (linux-gnuoldld) or + # one that does not give us useful --help. + echo "${UNAME_MACHINE}-pc-linux-gnuoldld" + exit ;; + esac + # Determine whether the default compiler is a.out or elf + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c + #include + #ifdef __ELF__ + # ifdef __GLIBC__ + # if __GLIBC__ >= 2 + LIBC=gnu + # else + LIBC=gnulibc1 + # endif + # else + LIBC=gnulibc1 + # endif + #else + #if defined(__INTEL_COMPILER) || defined(__PGI) || defined(__SUNPRO_C) || defined(__SUNPRO_CC) + LIBC=gnu + #else + LIBC=gnuaout + #endif + #endif + #ifdef __dietlibc__ + LIBC=dietlibc + #endif +EOF + eval "`$CC_FOR_BUILD -E $dummy.c 2>/dev/null | sed -n ' + /^LIBC/{ + s: ::g + p + }'`" + test x"${LIBC}" != x && { + echo "${UNAME_MACHINE}-pc-linux-${LIBC}" + exit + } + test x"${TENTATIVE}" != x && { echo "${TENTATIVE}"; exit; } + ;; + i*86:DYNIX/ptx:4*:*) + # ptx 4.0 does uname -s correctly, with DYNIX/ptx in there. + # earlier versions are messed up and put the nodename in both + # sysname and nodename. + echo i386-sequent-sysv4 + exit ;; + i*86:UNIX_SV:4.2MP:2.*) + # Unixware is an offshoot of SVR4, but it has its own version + # number series starting with 2... + # I am not positive that other SVR4 systems won't match this, + # I just have to hope. -- rms. + # Use sysv4.2uw... so that sysv4* matches it. + echo ${UNAME_MACHINE}-pc-sysv4.2uw${UNAME_VERSION} + exit ;; + i*86:OS/2:*:*) + # If we were able to find `uname', then EMX Unix compatibility + # is probably installed. + echo ${UNAME_MACHINE}-pc-os2-emx + exit ;; + i*86:XTS-300:*:STOP) + echo ${UNAME_MACHINE}-unknown-stop + exit ;; + i*86:atheos:*:*) + echo ${UNAME_MACHINE}-unknown-atheos + exit ;; + i*86:syllable:*:*) + echo ${UNAME_MACHINE}-pc-syllable + exit ;; + i*86:LynxOS:2.*:* | i*86:LynxOS:3.[01]*:* | i*86:LynxOS:4.0*:*) + echo i386-unknown-lynxos${UNAME_RELEASE} + exit ;; + i*86:*DOS:*:*) + echo ${UNAME_MACHINE}-pc-msdosdjgpp + exit ;; + i*86:*:4.*:* | i*86:SYSTEM_V:4.*:*) + UNAME_REL=`echo ${UNAME_RELEASE} | sed 's/\/MP$//'` + if grep Novell /usr/include/link.h >/dev/null 2>/dev/null; then + echo ${UNAME_MACHINE}-univel-sysv${UNAME_REL} + else + echo ${UNAME_MACHINE}-pc-sysv${UNAME_REL} + fi + exit ;; + i*86:*:5:[678]*) + # UnixWare 7.x, OpenUNIX and OpenServer 6. + case `/bin/uname -X | grep "^Machine"` in + *486*) UNAME_MACHINE=i486 ;; + *Pentium) UNAME_MACHINE=i586 ;; + *Pent*|*Celeron) UNAME_MACHINE=i686 ;; + esac + echo ${UNAME_MACHINE}-unknown-sysv${UNAME_RELEASE}${UNAME_SYSTEM}${UNAME_VERSION} + exit ;; + i*86:*:3.2:*) + if test -f /usr/options/cb.name; then + UNAME_REL=`sed -n 's/.*Version //p' /dev/null >/dev/null ; then + UNAME_REL=`(/bin/uname -X|grep Release|sed -e 's/.*= //')` + (/bin/uname -X|grep i80486 >/dev/null) && UNAME_MACHINE=i486 + (/bin/uname -X|grep '^Machine.*Pentium' >/dev/null) \ + && UNAME_MACHINE=i586 + (/bin/uname -X|grep '^Machine.*Pent *II' >/dev/null) \ + && UNAME_MACHINE=i686 + (/bin/uname -X|grep '^Machine.*Pentium Pro' >/dev/null) \ + && UNAME_MACHINE=i686 + echo ${UNAME_MACHINE}-pc-sco$UNAME_REL + else + echo ${UNAME_MACHINE}-pc-sysv32 + fi + exit ;; + pc:*:*:*) + # Left here for compatibility: + # uname -m prints for DJGPP always 'pc', but it prints nothing about + # the processor, so we play safe by assuming i386. + echo i386-pc-msdosdjgpp + exit ;; + Intel:Mach:3*:*) + echo i386-pc-mach3 + exit ;; + paragon:*:*:*) + echo i860-intel-osf1 + exit ;; + i860:*:4.*:*) # i860-SVR4 + if grep Stardent /usr/include/sys/uadmin.h >/dev/null 2>&1 ; then + echo i860-stardent-sysv${UNAME_RELEASE} # Stardent Vistra i860-SVR4 + else # Add other i860-SVR4 vendors below as they are discovered. + echo i860-unknown-sysv${UNAME_RELEASE} # Unknown i860-SVR4 + fi + exit ;; + mini*:CTIX:SYS*5:*) + # "miniframe" + echo m68010-convergent-sysv + exit ;; + mc68k:UNIX:SYSTEM5:3.51m) + echo m68k-convergent-sysv + exit ;; + M680?0:D-NIX:5.3:*) + echo m68k-diab-dnix + exit ;; + M68*:*:R3V[5678]*:*) + test -r /sysV68 && { echo 'm68k-motorola-sysv'; exit; } ;; + 3[345]??:*:4.0:3.0 | 3[34]??A:*:4.0:3.0 | 3[34]??,*:*:4.0:3.0 | 3[34]??/*:*:4.0:3.0 | 4400:*:4.0:3.0 | 4850:*:4.0:3.0 | SKA40:*:4.0:3.0 | SDS2:*:4.0:3.0 | SHG2:*:4.0:3.0 | S7501*:*:4.0:3.0) + OS_REL='' + test -r /etc/.relid \ + && OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid` + /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ + && { echo i486-ncr-sysv4.3${OS_REL}; exit; } + /bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \ + && { echo i586-ncr-sysv4.3${OS_REL}; exit; } ;; + 3[34]??:*:4.0:* | 3[34]??,*:*:4.0:*) + /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ + && { echo i486-ncr-sysv4; exit; } ;; + m68*:LynxOS:2.*:* | m68*:LynxOS:3.0*:*) + echo m68k-unknown-lynxos${UNAME_RELEASE} + exit ;; + mc68030:UNIX_System_V:4.*:*) + echo m68k-atari-sysv4 + exit ;; + TSUNAMI:LynxOS:2.*:*) + echo sparc-unknown-lynxos${UNAME_RELEASE} + exit ;; + rs6000:LynxOS:2.*:*) + echo rs6000-unknown-lynxos${UNAME_RELEASE} + exit ;; + PowerPC:LynxOS:2.*:* | PowerPC:LynxOS:3.[01]*:* | PowerPC:LynxOS:4.0*:*) + echo powerpc-unknown-lynxos${UNAME_RELEASE} + exit ;; + SM[BE]S:UNIX_SV:*:*) + echo mips-dde-sysv${UNAME_RELEASE} + exit ;; + RM*:ReliantUNIX-*:*:*) + echo mips-sni-sysv4 + exit ;; + RM*:SINIX-*:*:*) + echo mips-sni-sysv4 + exit ;; + *:SINIX-*:*:*) + if uname -p 2>/dev/null >/dev/null ; then + UNAME_MACHINE=`(uname -p) 2>/dev/null` + echo ${UNAME_MACHINE}-sni-sysv4 + else + echo ns32k-sni-sysv + fi + exit ;; + PENTIUM:*:4.0*:*) # Unisys `ClearPath HMP IX 4000' SVR4/MP effort + # says + echo i586-unisys-sysv4 + exit ;; + *:UNIX_System_V:4*:FTX*) + # From Gerald Hewes . + # How about differentiating between stratus architectures? -djm + echo hppa1.1-stratus-sysv4 + exit ;; + *:*:*:FTX*) + # From seanf@swdc.stratus.com. + echo i860-stratus-sysv4 + exit ;; + i*86:VOS:*:*) + # From Paul.Green@stratus.com. + echo ${UNAME_MACHINE}-stratus-vos + exit ;; + *:VOS:*:*) + # From Paul.Green@stratus.com. + echo hppa1.1-stratus-vos + exit ;; + mc68*:A/UX:*:*) + echo m68k-apple-aux${UNAME_RELEASE} + exit ;; + news*:NEWS-OS:6*:*) + echo mips-sony-newsos6 + exit ;; + R[34]000:*System_V*:*:* | R4000:UNIX_SYSV:*:* | R*000:UNIX_SV:*:*) + if [ -d /usr/nec ]; then + echo mips-nec-sysv${UNAME_RELEASE} + else + echo mips-unknown-sysv${UNAME_RELEASE} + fi + exit ;; + BeBox:BeOS:*:*) # BeOS running on hardware made by Be, PPC only. + echo powerpc-be-beos + exit ;; + BeMac:BeOS:*:*) # BeOS running on Mac or Mac clone, PPC only. + echo powerpc-apple-beos + exit ;; + BePC:BeOS:*:*) # BeOS running on Intel PC compatible. + echo i586-pc-beos + exit ;; + SX-4:SUPER-UX:*:*) + echo sx4-nec-superux${UNAME_RELEASE} + exit ;; + SX-5:SUPER-UX:*:*) + echo sx5-nec-superux${UNAME_RELEASE} + exit ;; + SX-6:SUPER-UX:*:*) + echo sx6-nec-superux${UNAME_RELEASE} + exit ;; + Power*:Rhapsody:*:*) + echo powerpc-apple-rhapsody${UNAME_RELEASE} + exit ;; + *:Rhapsody:*:*) + echo ${UNAME_MACHINE}-apple-rhapsody${UNAME_RELEASE} + exit ;; + *:Darwin:*:*) + UNAME_PROCESSOR=`uname -p` || UNAME_PROCESSOR=unknown + case $UNAME_PROCESSOR in + unknown) UNAME_PROCESSOR=powerpc ;; + esac + echo ${UNAME_PROCESSOR}-apple-darwin${UNAME_RELEASE} + exit ;; + *:procnto*:*:* | *:QNX:[0123456789]*:*) + UNAME_PROCESSOR=`uname -p` + if test "$UNAME_PROCESSOR" = "x86"; then + UNAME_PROCESSOR=i386 + UNAME_MACHINE=pc + fi + echo ${UNAME_PROCESSOR}-${UNAME_MACHINE}-nto-qnx${UNAME_RELEASE} + exit ;; + *:QNX:*:4*) + echo i386-pc-qnx + exit ;; + NSE-?:NONSTOP_KERNEL:*:*) + echo nse-tandem-nsk${UNAME_RELEASE} + exit ;; + NSR-?:NONSTOP_KERNEL:*:*) + echo nsr-tandem-nsk${UNAME_RELEASE} + exit ;; + *:NonStop-UX:*:*) + echo mips-compaq-nonstopux + exit ;; + BS2000:POSIX*:*:*) + echo bs2000-siemens-sysv + exit ;; + DS/*:UNIX_System_V:*:*) + echo ${UNAME_MACHINE}-${UNAME_SYSTEM}-${UNAME_RELEASE} + exit ;; + *:Plan9:*:*) + # "uname -m" is not consistent, so use $cputype instead. 386 + # is converted to i386 for consistency with other x86 + # operating systems. + if test "$cputype" = "386"; then + UNAME_MACHINE=i386 + else + UNAME_MACHINE="$cputype" + fi + echo ${UNAME_MACHINE}-unknown-plan9 + exit ;; + *:TOPS-10:*:*) + echo pdp10-unknown-tops10 + exit ;; + *:TENEX:*:*) + echo pdp10-unknown-tenex + exit ;; + KS10:TOPS-20:*:* | KL10:TOPS-20:*:* | TYPE4:TOPS-20:*:*) + echo pdp10-dec-tops20 + exit ;; + XKL-1:TOPS-20:*:* | TYPE5:TOPS-20:*:*) + echo pdp10-xkl-tops20 + exit ;; + *:TOPS-20:*:*) + echo pdp10-unknown-tops20 + exit ;; + *:ITS:*:*) + echo pdp10-unknown-its + exit ;; + SEI:*:*:SEIUX) + echo mips-sei-seiux${UNAME_RELEASE} + exit ;; + *:DragonFly:*:*) + echo ${UNAME_MACHINE}-unknown-dragonfly`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` + exit ;; + *:*VMS:*:*) + UNAME_MACHINE=`(uname -p) 2>/dev/null` + case "${UNAME_MACHINE}" in + A*) echo alpha-dec-vms ; exit ;; + I*) echo ia64-dec-vms ; exit ;; + V*) echo vax-dec-vms ; exit ;; + esac ;; + *:XENIX:*:SysV) + echo i386-pc-xenix + exit ;; + i*86:skyos:*:*) + echo ${UNAME_MACHINE}-pc-skyos`echo ${UNAME_RELEASE}` | sed -e 's/ .*$//' + exit ;; + i*86:rdos:*:*) + echo ${UNAME_MACHINE}-pc-rdos + exit ;; +esac + +#echo '(No uname command or uname output not recognized.)' 1>&2 +#echo "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" 1>&2 + +eval $set_cc_for_build +cat >$dummy.c < +# include +#endif +main () +{ +#if defined (sony) +#if defined (MIPSEB) + /* BFD wants "bsd" instead of "newsos". Perhaps BFD should be changed, + I don't know.... */ + printf ("mips-sony-bsd\n"); exit (0); +#else +#include + printf ("m68k-sony-newsos%s\n", +#ifdef NEWSOS4 + "4" +#else + "" +#endif + ); exit (0); +#endif +#endif + +#if defined (__arm) && defined (__acorn) && defined (__unix) + printf ("arm-acorn-riscix\n"); exit (0); +#endif + +#if defined (hp300) && !defined (hpux) + printf ("m68k-hp-bsd\n"); exit (0); +#endif + +#if defined (NeXT) +#if !defined (__ARCHITECTURE__) +#define __ARCHITECTURE__ "m68k" +#endif + int version; + version=`(hostinfo | sed -n 's/.*NeXT Mach \([0-9]*\).*/\1/p') 2>/dev/null`; + if (version < 4) + printf ("%s-next-nextstep%d\n", __ARCHITECTURE__, version); + else + printf ("%s-next-openstep%d\n", __ARCHITECTURE__, version); + exit (0); +#endif + +#if defined (MULTIMAX) || defined (n16) +#if defined (UMAXV) + printf ("ns32k-encore-sysv\n"); exit (0); +#else +#if defined (CMU) + printf ("ns32k-encore-mach\n"); exit (0); +#else + printf ("ns32k-encore-bsd\n"); exit (0); +#endif +#endif +#endif + +#if defined (__386BSD__) + printf ("i386-pc-bsd\n"); exit (0); +#endif + +#if defined (sequent) +#if defined (i386) + printf ("i386-sequent-dynix\n"); exit (0); +#endif +#if defined (ns32000) + printf ("ns32k-sequent-dynix\n"); exit (0); +#endif +#endif + +#if defined (_SEQUENT_) + struct utsname un; + + uname(&un); + + if (strncmp(un.version, "V2", 2) == 0) { + printf ("i386-sequent-ptx2\n"); exit (0); + } + if (strncmp(un.version, "V1", 2) == 0) { /* XXX is V1 correct? */ + printf ("i386-sequent-ptx1\n"); exit (0); + } + printf ("i386-sequent-ptx\n"); exit (0); + +#endif + +#if defined (vax) +# if !defined (ultrix) +# include +# if defined (BSD) +# if BSD == 43 + printf ("vax-dec-bsd4.3\n"); exit (0); +# else +# if BSD == 199006 + printf ("vax-dec-bsd4.3reno\n"); exit (0); +# else + printf ("vax-dec-bsd\n"); exit (0); +# endif +# endif +# else + printf ("vax-dec-bsd\n"); exit (0); +# endif +# else + printf ("vax-dec-ultrix\n"); exit (0); +# endif +#endif + +#if defined (alliant) && defined (i860) + printf ("i860-alliant-bsd\n"); exit (0); +#endif + + exit (1); +} +EOF + +$CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null && SYSTEM_NAME=`$dummy` && + { echo "$SYSTEM_NAME"; exit; } + +# Apollos put the system type in the environment. + +test -d /usr/apollo && { echo ${ISP}-apollo-${SYSTYPE}; exit; } + +# Convex versions that predate uname can use getsysinfo(1) + +if [ -x /usr/convex/getsysinfo ] +then + case `getsysinfo -f cpu_type` in + c1*) + echo c1-convex-bsd + exit ;; + c2*) + if getsysinfo -f scalar_acc + then echo c32-convex-bsd + else echo c2-convex-bsd + fi + exit ;; + c34*) + echo c34-convex-bsd + exit ;; + c38*) + echo c38-convex-bsd + exit ;; + c4*) + echo c4-convex-bsd + exit ;; + esac +fi + +cat >&2 < in order to provide the needed +information to handle your system. + +config.guess timestamp = $timestamp + +uname -m = `(uname -m) 2>/dev/null || echo unknown` +uname -r = `(uname -r) 2>/dev/null || echo unknown` +uname -s = `(uname -s) 2>/dev/null || echo unknown` +uname -v = `(uname -v) 2>/dev/null || echo unknown` + +/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null` +/bin/uname -X = `(/bin/uname -X) 2>/dev/null` + +hostinfo = `(hostinfo) 2>/dev/null` +/bin/universe = `(/bin/universe) 2>/dev/null` +/usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null` +/bin/arch = `(/bin/arch) 2>/dev/null` +/usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null` +/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null` + +UNAME_MACHINE = ${UNAME_MACHINE} +UNAME_RELEASE = ${UNAME_RELEASE} +UNAME_SYSTEM = ${UNAME_SYSTEM} +UNAME_VERSION = ${UNAME_VERSION} +EOF + +exit 1 + +# Local variables: +# eval: (add-hook 'write-file-hooks 'time-stamp) +# time-stamp-start: "timestamp='" +# time-stamp-format: "%:y-%02m-%02d" +# time-stamp-end: "'" +# End: diff --git a/modules/maplib/autoconf/config.sub b/modules/maplib/autoconf/config.sub new file mode 100755 index 0000000..387c18d --- /dev/null +++ b/modules/maplib/autoconf/config.sub @@ -0,0 +1,1608 @@ +#! /bin/sh +# Configuration validation subroutine script. +# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, +# 2000, 2001, 2002, 2003, 2004, 2005, 2006 Free Software Foundation, +# Inc. + +timestamp='2006-07-02' + +# This file is (in principle) common to ALL GNU software. +# The presence of a machine in this file suggests that SOME GNU software +# can handle that machine. It does not imply ALL GNU software can. +# +# This file is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA +# 02110-1301, USA. +# +# As a special exception to the GNU General Public License, if you +# distribute this file as part of a program that contains a +# configuration script generated by Autoconf, you may include it under +# the same distribution terms that you use for the rest of that program. + + +# Please send patches to . Submit a context +# diff and a properly formatted ChangeLog entry. +# +# Configuration subroutine to validate and canonicalize a configuration type. +# Supply the specified configuration type as an argument. +# If it is invalid, we print an error message on stderr and exit with code 1. +# Otherwise, we print the canonical config type on stdout and succeed. + +# This file is supposed to be the same for all GNU packages +# and recognize all the CPU types, system types and aliases +# that are meaningful with *any* GNU software. +# Each package is responsible for reporting which valid configurations +# it does not support. The user should be able to distinguish +# a failure to support a valid configuration from a meaningless +# configuration. + +# The goal of this file is to map all the various variations of a given +# machine specification into a single specification in the form: +# CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM +# or in some cases, the newer four-part form: +# CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM +# It is wrong to echo any other type of specification. + +me=`echo "$0" | sed -e 's,.*/,,'` + +usage="\ +Usage: $0 [OPTION] CPU-MFR-OPSYS + $0 [OPTION] ALIAS + +Canonicalize a configuration name. + +Operation modes: + -h, --help print this help, then exit + -t, --time-stamp print date of last modification, then exit + -v, --version print version number, then exit + +Report bugs and patches to ." + +version="\ +GNU config.sub ($timestamp) + +Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005 +Free Software Foundation, Inc. + +This is free software; see the source for copying conditions. There is NO +warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." + +help=" +Try \`$me --help' for more information." + +# Parse command line +while test $# -gt 0 ; do + case $1 in + --time-stamp | --time* | -t ) + echo "$timestamp" ; exit ;; + --version | -v ) + echo "$version" ; exit ;; + --help | --h* | -h ) + echo "$usage"; exit ;; + -- ) # Stop option processing + shift; break ;; + - ) # Use stdin as input. + break ;; + -* ) + echo "$me: invalid option $1$help" + exit 1 ;; + + *local*) + # First pass through any local machine types. + echo $1 + exit ;; + + * ) + break ;; + esac +done + +case $# in + 0) echo "$me: missing argument$help" >&2 + exit 1;; + 1) ;; + *) echo "$me: too many arguments$help" >&2 + exit 1;; +esac + +# Separate what the user gave into CPU-COMPANY and OS or KERNEL-OS (if any). +# Here we must recognize all the valid KERNEL-OS combinations. +maybe_os=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\2/'` +case $maybe_os in + nto-qnx* | linux-gnu* | linux-dietlibc | linux-newlib* | linux-uclibc* | \ + uclinux-uclibc* | uclinux-gnu* | kfreebsd*-gnu* | knetbsd*-gnu* | netbsd*-gnu* | \ + storm-chaos* | os2-emx* | rtmk-nova*) + os=-$maybe_os + basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'` + ;; + *) + basic_machine=`echo $1 | sed 's/-[^-]*$//'` + if [ $basic_machine != $1 ] + then os=`echo $1 | sed 's/.*-/-/'` + else os=; fi + ;; +esac + +### Let's recognize common machines as not being operating systems so +### that things like config.sub decstation-3100 work. We also +### recognize some manufacturers as not being operating systems, so we +### can provide default operating systems below. +case $os in + -sun*os*) + # Prevent following clause from handling this invalid input. + ;; + -dec* | -mips* | -sequent* | -encore* | -pc532* | -sgi* | -sony* | \ + -att* | -7300* | -3300* | -delta* | -motorola* | -sun[234]* | \ + -unicom* | -ibm* | -next | -hp | -isi* | -apollo | -altos* | \ + -convergent* | -ncr* | -news | -32* | -3600* | -3100* | -hitachi* |\ + -c[123]* | -convex* | -sun | -crds | -omron* | -dg | -ultra | -tti* | \ + -harris | -dolphin | -highlevel | -gould | -cbm | -ns | -masscomp | \ + -apple | -axis | -knuth | -cray) + os= + basic_machine=$1 + ;; + -sim | -cisco | -oki | -wec | -winbond) + os= + basic_machine=$1 + ;; + -scout) + ;; + -wrs) + os=-vxworks + basic_machine=$1 + ;; + -chorusos*) + os=-chorusos + basic_machine=$1 + ;; + -chorusrdb) + os=-chorusrdb + basic_machine=$1 + ;; + -hiux*) + os=-hiuxwe2 + ;; + -sco6) + os=-sco5v6 + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -sco5) + os=-sco3.2v5 + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -sco4) + os=-sco3.2v4 + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -sco3.2.[4-9]*) + os=`echo $os | sed -e 's/sco3.2./sco3.2v/'` + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -sco3.2v[4-9]*) + # Don't forget version if it is 3.2v4 or newer. + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -sco5v6*) + # Don't forget version if it is 3.2v4 or newer. + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -sco*) + os=-sco3.2v2 + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -udk*) + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -isc) + os=-isc2.2 + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -clix*) + basic_machine=clipper-intergraph + ;; + -isc*) + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -lynx*) + os=-lynxos + ;; + -ptx*) + basic_machine=`echo $1 | sed -e 's/86-.*/86-sequent/'` + ;; + -windowsnt*) + os=`echo $os | sed -e 's/windowsnt/winnt/'` + ;; + -psos*) + os=-psos + ;; + -mint | -mint[0-9]*) + basic_machine=m68k-atari + os=-mint + ;; +esac + +# Decode aliases for certain CPU-COMPANY combinations. +case $basic_machine in + # Recognize the basic CPU types without company name. + # Some are omitted here because they have special meanings below. + 1750a | 580 \ + | a29k \ + | alpha | alphaev[4-8] | alphaev56 | alphaev6[78] | alphapca5[67] \ + | alpha64 | alpha64ev[4-8] | alpha64ev56 | alpha64ev6[78] | alpha64pca5[67] \ + | am33_2.0 \ + | arc | arm | arm[bl]e | arme[lb] | armv[2345] | armv[345][lb] | avr | avr32 \ + | bfin \ + | c4x | clipper \ + | d10v | d30v | dlx | dsp16xx \ + | fr30 | frv \ + | h8300 | h8500 | hppa | hppa1.[01] | hppa2.0 | hppa2.0[nw] | hppa64 \ + | i370 | i860 | i960 | ia64 \ + | ip2k | iq2000 \ + | m32c | m32r | m32rle | m68000 | m68k | m88k \ + | maxq | mb | microblaze | mcore \ + | mips | mipsbe | mipseb | mipsel | mipsle \ + | mips16 \ + | mips64 | mips64el \ + | mips64vr | mips64vrel \ + | mips64orion | mips64orionel \ + | mips64vr4100 | mips64vr4100el \ + | mips64vr4300 | mips64vr4300el \ + | mips64vr5000 | mips64vr5000el \ + | mips64vr5900 | mips64vr5900el \ + | mipsisa32 | mipsisa32el \ + | mipsisa32r2 | mipsisa32r2el \ + | mipsisa64 | mipsisa64el \ + | mipsisa64r2 | mipsisa64r2el \ + | mipsisa64sb1 | mipsisa64sb1el \ + | mipsisa64sr71k | mipsisa64sr71kel \ + | mipstx39 | mipstx39el \ + | mn10200 | mn10300 \ + | mt \ + | msp430 \ + | nios | nios2 \ + | ns16k | ns32k \ + | or32 \ + | pdp10 | pdp11 | pj | pjl \ + | powerpc | powerpc64 | powerpc64le | powerpcle | ppcbe \ + | pyramid \ + | sh | sh[1234] | sh[24]a | sh[23]e | sh[34]eb | sheb | shbe | shle | sh[1234]le | sh3ele \ + | sh64 | sh64le \ + | sparc | sparc64 | sparc64b | sparc64v | sparc86x | sparclet | sparclite \ + | sparcv8 | sparcv9 | sparcv9b | sparcv9v \ + | spu | strongarm \ + | tahoe | thumb | tic4x | tic80 | tron \ + | v850 | v850e \ + | we32k \ + | x86 | xscale | xscalee[bl] | xstormy16 | xtensa \ + | z8k) + basic_machine=$basic_machine-unknown + ;; + m6811 | m68hc11 | m6812 | m68hc12) + # Motorola 68HC11/12. + basic_machine=$basic_machine-unknown + os=-none + ;; + m88110 | m680[12346]0 | m683?2 | m68360 | m5200 | v70 | w65 | z8k) + ;; + ms1) + basic_machine=mt-unknown + ;; + + # We use `pc' rather than `unknown' + # because (1) that's what they normally are, and + # (2) the word "unknown" tends to confuse beginning users. + i*86 | x86_64) + basic_machine=$basic_machine-pc + ;; + # Object if more than one company name word. + *-*-*) + echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2 + exit 1 + ;; + # Recognize the basic CPU types with company name. + 580-* \ + | a29k-* \ + | alpha-* | alphaev[4-8]-* | alphaev56-* | alphaev6[78]-* \ + | alpha64-* | alpha64ev[4-8]-* | alpha64ev56-* | alpha64ev6[78]-* \ + | alphapca5[67]-* | alpha64pca5[67]-* | arc-* \ + | arm-* | armbe-* | armle-* | armeb-* | armv*-* \ + | avr-* | avr32-* \ + | bfin-* | bs2000-* \ + | c[123]* | c30-* | [cjt]90-* | c4x-* | c54x-* | c55x-* | c6x-* \ + | clipper-* | craynv-* | cydra-* \ + | d10v-* | d30v-* | dlx-* \ + | elxsi-* \ + | f30[01]-* | f700-* | fr30-* | frv-* | fx80-* \ + | h8300-* | h8500-* \ + | hppa-* | hppa1.[01]-* | hppa2.0-* | hppa2.0[nw]-* | hppa64-* \ + | i*86-* | i860-* | i960-* | ia64-* \ + | ip2k-* | iq2000-* \ + | m32c-* | m32r-* | m32rle-* \ + | m68000-* | m680[012346]0-* | m68360-* | m683?2-* | m68k-* \ + | m88110-* | m88k-* | maxq-* | mcore-* \ + | mips-* | mipsbe-* | mipseb-* | mipsel-* | mipsle-* \ + | mips16-* \ + | mips64-* | mips64el-* \ + | mips64vr-* | mips64vrel-* \ + | mips64orion-* | mips64orionel-* \ + | mips64vr4100-* | mips64vr4100el-* \ + | mips64vr4300-* | mips64vr4300el-* \ + | mips64vr5000-* | mips64vr5000el-* \ + | mips64vr5900-* | mips64vr5900el-* \ + | mipsisa32-* | mipsisa32el-* \ + | mipsisa32r2-* | mipsisa32r2el-* \ + | mipsisa64-* | mipsisa64el-* \ + | mipsisa64r2-* | mipsisa64r2el-* \ + | mipsisa64sb1-* | mipsisa64sb1el-* \ + | mipsisa64sr71k-* | mipsisa64sr71kel-* \ + | mipstx39-* | mipstx39el-* \ + | mmix-* \ + | mt-* \ + | msp430-* \ + | nios-* | nios2-* \ + | none-* | np1-* | ns16k-* | ns32k-* \ + | orion-* \ + | pdp10-* | pdp11-* | pj-* | pjl-* | pn-* | power-* \ + | powerpc-* | powerpc64-* | powerpc64le-* | powerpcle-* | ppcbe-* \ + | pyramid-* \ + | romp-* | rs6000-* \ + | sh-* | sh[1234]-* | sh[24]a-* | sh[23]e-* | sh[34]eb-* | sheb-* | shbe-* \ + | shle-* | sh[1234]le-* | sh3ele-* | sh64-* | sh64le-* \ + | sparc-* | sparc64-* | sparc64b-* | sparc64v-* | sparc86x-* | sparclet-* \ + | sparclite-* \ + | sparcv8-* | sparcv9-* | sparcv9b-* | sparcv9v-* | strongarm-* | sv1-* | sx?-* \ + | tahoe-* | thumb-* \ + | tic30-* | tic4x-* | tic54x-* | tic55x-* | tic6x-* | tic80-* \ + | tron-* \ + | v850-* | v850e-* | vax-* \ + | we32k-* \ + | x86-* | x86_64-* | xps100-* | xscale-* | xscalee[bl]-* \ + | xstormy16-* | xtensa-* \ + | ymp-* \ + | z8k-*) + ;; + # Recognize the various machine names and aliases which stand + # for a CPU type and a company and sometimes even an OS. + 386bsd) + basic_machine=i386-unknown + os=-bsd + ;; + 3b1 | 7300 | 7300-att | att-7300 | pc7300 | safari | unixpc) + basic_machine=m68000-att + ;; + 3b*) + basic_machine=we32k-att + ;; + a29khif) + basic_machine=a29k-amd + os=-udi + ;; + abacus) + basic_machine=abacus-unknown + ;; + adobe68k) + basic_machine=m68010-adobe + os=-scout + ;; + alliant | fx80) + basic_machine=fx80-alliant + ;; + altos | altos3068) + basic_machine=m68k-altos + ;; + am29k) + basic_machine=a29k-none + os=-bsd + ;; + amd64) + basic_machine=x86_64-pc + ;; + amd64-*) + basic_machine=x86_64-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + amdahl) + basic_machine=580-amdahl + os=-sysv + ;; + amiga | amiga-*) + basic_machine=m68k-unknown + ;; + amigaos | amigados) + basic_machine=m68k-unknown + os=-amigaos + ;; + amigaunix | amix) + basic_machine=m68k-unknown + os=-sysv4 + ;; + apollo68) + basic_machine=m68k-apollo + os=-sysv + ;; + apollo68bsd) + basic_machine=m68k-apollo + os=-bsd + ;; + aux) + basic_machine=m68k-apple + os=-aux + ;; + balance) + basic_machine=ns32k-sequent + os=-dynix + ;; + c90) + basic_machine=c90-cray + os=-unicos + ;; + convex-c1) + basic_machine=c1-convex + os=-bsd + ;; + convex-c2) + basic_machine=c2-convex + os=-bsd + ;; + convex-c32) + basic_machine=c32-convex + os=-bsd + ;; + convex-c34) + basic_machine=c34-convex + os=-bsd + ;; + convex-c38) + basic_machine=c38-convex + os=-bsd + ;; + cray | j90) + basic_machine=j90-cray + os=-unicos + ;; + craynv) + basic_machine=craynv-cray + os=-unicosmp + ;; + cr16c) + basic_machine=cr16c-unknown + os=-elf + ;; + crds | unos) + basic_machine=m68k-crds + ;; + crisv32 | crisv32-* | etraxfs*) + basic_machine=crisv32-axis + ;; + cris | cris-* | etrax*) + basic_machine=cris-axis + ;; + crx) + basic_machine=crx-unknown + os=-elf + ;; + da30 | da30-*) + basic_machine=m68k-da30 + ;; + decstation | decstation-3100 | pmax | pmax-* | pmin | dec3100 | decstatn) + basic_machine=mips-dec + ;; + decsystem10* | dec10*) + basic_machine=pdp10-dec + os=-tops10 + ;; + decsystem20* | dec20*) + basic_machine=pdp10-dec + os=-tops20 + ;; + delta | 3300 | motorola-3300 | motorola-delta \ + | 3300-motorola | delta-motorola) + basic_machine=m68k-motorola + ;; + delta88) + basic_machine=m88k-motorola + os=-sysv3 + ;; + djgpp) + basic_machine=i586-pc + os=-msdosdjgpp + ;; + dpx20 | dpx20-*) + basic_machine=rs6000-bull + os=-bosx + ;; + dpx2* | dpx2*-bull) + basic_machine=m68k-bull + os=-sysv3 + ;; + ebmon29k) + basic_machine=a29k-amd + os=-ebmon + ;; + elxsi) + basic_machine=elxsi-elxsi + os=-bsd + ;; + encore | umax | mmax) + basic_machine=ns32k-encore + ;; + es1800 | OSE68k | ose68k | ose | OSE) + basic_machine=m68k-ericsson + os=-ose + ;; + fx2800) + basic_machine=i860-alliant + ;; + genix) + basic_machine=ns32k-ns + ;; + gmicro) + basic_machine=tron-gmicro + os=-sysv + ;; + go32) + basic_machine=i386-pc + os=-go32 + ;; + h3050r* | hiux*) + basic_machine=hppa1.1-hitachi + os=-hiuxwe2 + ;; + h8300hms) + basic_machine=h8300-hitachi + os=-hms + ;; + h8300xray) + basic_machine=h8300-hitachi + os=-xray + ;; + h8500hms) + basic_machine=h8500-hitachi + os=-hms + ;; + harris) + basic_machine=m88k-harris + os=-sysv3 + ;; + hp300-*) + basic_machine=m68k-hp + ;; + hp300bsd) + basic_machine=m68k-hp + os=-bsd + ;; + hp300hpux) + basic_machine=m68k-hp + os=-hpux + ;; + hp3k9[0-9][0-9] | hp9[0-9][0-9]) + basic_machine=hppa1.0-hp + ;; + hp9k2[0-9][0-9] | hp9k31[0-9]) + basic_machine=m68000-hp + ;; + hp9k3[2-9][0-9]) + basic_machine=m68k-hp + ;; + hp9k6[0-9][0-9] | hp6[0-9][0-9]) + basic_machine=hppa1.0-hp + ;; + hp9k7[0-79][0-9] | hp7[0-79][0-9]) + basic_machine=hppa1.1-hp + ;; + hp9k78[0-9] | hp78[0-9]) + # FIXME: really hppa2.0-hp + basic_machine=hppa1.1-hp + ;; + hp9k8[67]1 | hp8[67]1 | hp9k80[24] | hp80[24] | hp9k8[78]9 | hp8[78]9 | hp9k893 | hp893) + # FIXME: really hppa2.0-hp + basic_machine=hppa1.1-hp + ;; + hp9k8[0-9][13679] | hp8[0-9][13679]) + basic_machine=hppa1.1-hp + ;; + hp9k8[0-9][0-9] | hp8[0-9][0-9]) + basic_machine=hppa1.0-hp + ;; + hppa-next) + os=-nextstep3 + ;; + hppaosf) + basic_machine=hppa1.1-hp + os=-osf + ;; + hppro) + basic_machine=hppa1.1-hp + os=-proelf + ;; + i370-ibm* | ibm*) + basic_machine=i370-ibm + ;; +# I'm not sure what "Sysv32" means. Should this be sysv3.2? + i*86v32) + basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` + os=-sysv32 + ;; + i*86v4*) + basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` + os=-sysv4 + ;; + i*86v) + basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` + os=-sysv + ;; + i*86sol2) + basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` + os=-solaris2 + ;; + i386mach) + basic_machine=i386-mach + os=-mach + ;; + i386-vsta | vsta) + basic_machine=i386-unknown + os=-vsta + ;; + iris | iris4d) + basic_machine=mips-sgi + case $os in + -irix*) + ;; + *) + os=-irix4 + ;; + esac + ;; + isi68 | isi) + basic_machine=m68k-isi + os=-sysv + ;; + m88k-omron*) + basic_machine=m88k-omron + ;; + magnum | m3230) + basic_machine=mips-mips + os=-sysv + ;; + merlin) + basic_machine=ns32k-utek + os=-sysv + ;; + mingw32) + basic_machine=i386-pc + os=-mingw32 + ;; + miniframe) + basic_machine=m68000-convergent + ;; + *mint | -mint[0-9]* | *MiNT | *MiNT[0-9]*) + basic_machine=m68k-atari + os=-mint + ;; + mips3*-*) + basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'` + ;; + mips3*) + basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'`-unknown + ;; + monitor) + basic_machine=m68k-rom68k + os=-coff + ;; + morphos) + basic_machine=powerpc-unknown + os=-morphos + ;; + msdos) + basic_machine=i386-pc + os=-msdos + ;; + ms1-*) + basic_machine=`echo $basic_machine | sed -e 's/ms1-/mt-/'` + ;; + mvs) + basic_machine=i370-ibm + os=-mvs + ;; + ncr3000) + basic_machine=i486-ncr + os=-sysv4 + ;; + netbsd386) + basic_machine=i386-unknown + os=-netbsd + ;; + netwinder) + basic_machine=armv4l-rebel + os=-linux + ;; + news | news700 | news800 | news900) + basic_machine=m68k-sony + os=-newsos + ;; + news1000) + basic_machine=m68030-sony + os=-newsos + ;; + news-3600 | risc-news) + basic_machine=mips-sony + os=-newsos + ;; + necv70) + basic_machine=v70-nec + os=-sysv + ;; + next | m*-next ) + basic_machine=m68k-next + case $os in + -nextstep* ) + ;; + -ns2*) + os=-nextstep2 + ;; + *) + os=-nextstep3 + ;; + esac + ;; + nh3000) + basic_machine=m68k-harris + os=-cxux + ;; + nh[45]000) + basic_machine=m88k-harris + os=-cxux + ;; + nindy960) + basic_machine=i960-intel + os=-nindy + ;; + mon960) + basic_machine=i960-intel + os=-mon960 + ;; + nonstopux) + basic_machine=mips-compaq + os=-nonstopux + ;; + np1) + basic_machine=np1-gould + ;; + nsr-tandem) + basic_machine=nsr-tandem + ;; + op50n-* | op60c-*) + basic_machine=hppa1.1-oki + os=-proelf + ;; + openrisc | openrisc-*) + basic_machine=or32-unknown + ;; + os400) + basic_machine=powerpc-ibm + os=-os400 + ;; + OSE68000 | ose68000) + basic_machine=m68000-ericsson + os=-ose + ;; + os68k) + basic_machine=m68k-none + os=-os68k + ;; + pa-hitachi) + basic_machine=hppa1.1-hitachi + os=-hiuxwe2 + ;; + paragon) + basic_machine=i860-intel + os=-osf + ;; + pbd) + basic_machine=sparc-tti + ;; + pbb) + basic_machine=m68k-tti + ;; + pc532 | pc532-*) + basic_machine=ns32k-pc532 + ;; + pc98) + basic_machine=i386-pc + ;; + pc98-*) + basic_machine=i386-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + pentium | p5 | k5 | k6 | nexgen | viac3) + basic_machine=i586-pc + ;; + pentiumpro | p6 | 6x86 | athlon | athlon_*) + basic_machine=i686-pc + ;; + pentiumii | pentium2 | pentiumiii | pentium3) + basic_machine=i686-pc + ;; + pentium4) + basic_machine=i786-pc + ;; + pentium-* | p5-* | k5-* | k6-* | nexgen-* | viac3-*) + basic_machine=i586-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + pentiumpro-* | p6-* | 6x86-* | athlon-*) + basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + pentiumii-* | pentium2-* | pentiumiii-* | pentium3-*) + basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + pentium4-*) + basic_machine=i786-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + pn) + basic_machine=pn-gould + ;; + power) basic_machine=power-ibm + ;; + ppc) basic_machine=powerpc-unknown + ;; + ppc-*) basic_machine=powerpc-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + ppcle | powerpclittle | ppc-le | powerpc-little) + basic_machine=powerpcle-unknown + ;; + ppcle-* | powerpclittle-*) + basic_machine=powerpcle-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + ppc64) basic_machine=powerpc64-unknown + ;; + ppc64-*) basic_machine=powerpc64-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + ppc64le | powerpc64little | ppc64-le | powerpc64-little) + basic_machine=powerpc64le-unknown + ;; + ppc64le-* | powerpc64little-*) + basic_machine=powerpc64le-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + ps2) + basic_machine=i386-ibm + ;; + pw32) + basic_machine=i586-unknown + os=-pw32 + ;; + rdos) + basic_machine=i386-pc + os=-rdos + ;; + rom68k) + basic_machine=m68k-rom68k + os=-coff + ;; + rm[46]00) + basic_machine=mips-siemens + ;; + rtpc | rtpc-*) + basic_machine=romp-ibm + ;; + s390 | s390-*) + basic_machine=s390-ibm + ;; + s390x | s390x-*) + basic_machine=s390x-ibm + ;; + sa29200) + basic_machine=a29k-amd + os=-udi + ;; + sb1) + basic_machine=mipsisa64sb1-unknown + ;; + sb1el) + basic_machine=mipsisa64sb1el-unknown + ;; + sei) + basic_machine=mips-sei + os=-seiux + ;; + sequent) + basic_machine=i386-sequent + ;; + sh) + basic_machine=sh-hitachi + os=-hms + ;; + sh64) + basic_machine=sh64-unknown + ;; + sparclite-wrs | simso-wrs) + basic_machine=sparclite-wrs + os=-vxworks + ;; + sps7) + basic_machine=m68k-bull + os=-sysv2 + ;; + spur) + basic_machine=spur-unknown + ;; + st2000) + basic_machine=m68k-tandem + ;; + stratus) + basic_machine=i860-stratus + os=-sysv4 + ;; + sun2) + basic_machine=m68000-sun + ;; + sun2os3) + basic_machine=m68000-sun + os=-sunos3 + ;; + sun2os4) + basic_machine=m68000-sun + os=-sunos4 + ;; + sun3os3) + basic_machine=m68k-sun + os=-sunos3 + ;; + sun3os4) + basic_machine=m68k-sun + os=-sunos4 + ;; + sun4os3) + basic_machine=sparc-sun + os=-sunos3 + ;; + sun4os4) + basic_machine=sparc-sun + os=-sunos4 + ;; + sun4sol2) + basic_machine=sparc-sun + os=-solaris2 + ;; + sun3 | sun3-*) + basic_machine=m68k-sun + ;; + sun4) + basic_machine=sparc-sun + ;; + sun386 | sun386i | roadrunner) + basic_machine=i386-sun + ;; + sv1) + basic_machine=sv1-cray + os=-unicos + ;; + symmetry) + basic_machine=i386-sequent + os=-dynix + ;; + t3e) + basic_machine=alphaev5-cray + os=-unicos + ;; + t90) + basic_machine=t90-cray + os=-unicos + ;; + tic54x | c54x*) + basic_machine=tic54x-unknown + os=-coff + ;; + tic55x | c55x*) + basic_machine=tic55x-unknown + os=-coff + ;; + tic6x | c6x*) + basic_machine=tic6x-unknown + os=-coff + ;; + tx39) + basic_machine=mipstx39-unknown + ;; + tx39el) + basic_machine=mipstx39el-unknown + ;; + toad1) + basic_machine=pdp10-xkl + os=-tops20 + ;; + tower | tower-32) + basic_machine=m68k-ncr + ;; + tpf) + basic_machine=s390x-ibm + os=-tpf + ;; + udi29k) + basic_machine=a29k-amd + os=-udi + ;; + ultra3) + basic_machine=a29k-nyu + os=-sym1 + ;; + v810 | necv810) + basic_machine=v810-nec + os=-none + ;; + vaxv) + basic_machine=vax-dec + os=-sysv + ;; + vms) + basic_machine=vax-dec + os=-vms + ;; + vpp*|vx|vx-*) + basic_machine=f301-fujitsu + ;; + vxworks960) + basic_machine=i960-wrs + os=-vxworks + ;; + vxworks68) + basic_machine=m68k-wrs + os=-vxworks + ;; + vxworks29k) + basic_machine=a29k-wrs + os=-vxworks + ;; + w65*) + basic_machine=w65-wdc + os=-none + ;; + w89k-*) + basic_machine=hppa1.1-winbond + os=-proelf + ;; + xbox) + basic_machine=i686-pc + os=-mingw32 + ;; + xps | xps100) + basic_machine=xps100-honeywell + ;; + ymp) + basic_machine=ymp-cray + os=-unicos + ;; + z8k-*-coff) + basic_machine=z8k-unknown + os=-sim + ;; + none) + basic_machine=none-none + os=-none + ;; + +# Here we handle the default manufacturer of certain CPU types. It is in +# some cases the only manufacturer, in others, it is the most popular. + w89k) + basic_machine=hppa1.1-winbond + ;; + op50n) + basic_machine=hppa1.1-oki + ;; + op60c) + basic_machine=hppa1.1-oki + ;; + romp) + basic_machine=romp-ibm + ;; + mmix) + basic_machine=mmix-knuth + ;; + rs6000) + basic_machine=rs6000-ibm + ;; + vax) + basic_machine=vax-dec + ;; + pdp10) + # there are many clones, so DEC is not a safe bet + basic_machine=pdp10-unknown + ;; + pdp11) + basic_machine=pdp11-dec + ;; + we32k) + basic_machine=we32k-att + ;; + sh[1234] | sh[24]a | sh[34]eb | sh[1234]le | sh[23]ele) + basic_machine=sh-unknown + ;; + sparc | sparcv8 | sparcv9 | sparcv9b | sparcv9v) + basic_machine=sparc-sun + ;; + cydra) + basic_machine=cydra-cydrome + ;; + orion) + basic_machine=orion-highlevel + ;; + orion105) + basic_machine=clipper-highlevel + ;; + mac | mpw | mac-mpw) + basic_machine=m68k-apple + ;; + pmac | pmac-mpw) + basic_machine=powerpc-apple + ;; + *-unknown) + # Make sure to match an already-canonicalized machine name. + ;; + *) + echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2 + exit 1 + ;; +esac + +# Here we canonicalize certain aliases for manufacturers. +case $basic_machine in + *-digital*) + basic_machine=`echo $basic_machine | sed 's/digital.*/dec/'` + ;; + *-commodore*) + basic_machine=`echo $basic_machine | sed 's/commodore.*/cbm/'` + ;; + *) + ;; +esac + +# Decode manufacturer-specific aliases for certain operating systems. + +if [ x"$os" != x"" ] +then +case $os in + # First match some system type aliases + # that might get confused with valid system types. + # -solaris* is a basic system type, with this one exception. + -solaris1 | -solaris1.*) + os=`echo $os | sed -e 's|solaris1|sunos4|'` + ;; + -solaris) + os=-solaris2 + ;; + -svr4*) + os=-sysv4 + ;; + -unixware*) + os=-sysv4.2uw + ;; + -gnu/linux*) + os=`echo $os | sed -e 's|gnu/linux|linux-gnu|'` + ;; + # First accept the basic system types. + # The portable systems comes first. + # Each alternative MUST END IN A *, to match a version number. + # -sysv* is not here because it comes later, after sysvr4. + -gnu* | -bsd* | -mach* | -minix* | -genix* | -ultrix* | -irix* \ + | -*vms* | -sco* | -esix* | -isc* | -aix* | -sunos | -sunos[34]*\ + | -hpux* | -unos* | -osf* | -luna* | -dgux* | -solaris* | -sym* \ + | -amigaos* | -amigados* | -msdos* | -newsos* | -unicos* | -aof* \ + | -aos* \ + | -nindy* | -vxsim* | -vxworks* | -ebmon* | -hms* | -mvs* \ + | -clix* | -riscos* | -uniplus* | -iris* | -rtu* | -xenix* \ + | -hiux* | -386bsd* | -knetbsd* | -mirbsd* | -netbsd* \ + | -openbsd* | -solidbsd* \ + | -ekkobsd* | -kfreebsd* | -freebsd* | -riscix* | -lynxos* \ + | -bosx* | -nextstep* | -cxux* | -aout* | -elf* | -oabi* \ + | -ptx* | -coff* | -ecoff* | -winnt* | -domain* | -vsta* \ + | -udi* | -eabi* | -lites* | -ieee* | -go32* | -aux* \ + | -chorusos* | -chorusrdb* \ + | -cygwin* | -pe* | -psos* | -moss* | -proelf* | -rtems* \ + | -mingw32* | -linux-gnu* | -linux-newlib* | -linux-uclibc* \ + | -uxpv* | -beos* | -mpeix* | -udk* \ + | -interix* | -uwin* | -mks* | -rhapsody* | -darwin* | -opened* \ + | -openstep* | -oskit* | -conix* | -pw32* | -nonstopux* \ + | -storm-chaos* | -tops10* | -tenex* | -tops20* | -its* \ + | -os2* | -vos* | -palmos* | -uclinux* | -nucleus* \ + | -morphos* | -superux* | -rtmk* | -rtmk-nova* | -windiss* \ + | -powermax* | -dnix* | -nx6 | -nx7 | -sei* | -dragonfly* \ + | -skyos* | -haiku* | -rdos* | -toppers*) + # Remember, each alternative MUST END IN *, to match a version number. + ;; + -qnx*) + case $basic_machine in + x86-* | i*86-*) + ;; + *) + os=-nto$os + ;; + esac + ;; + -nto-qnx*) + ;; + -nto*) + os=`echo $os | sed -e 's|nto|nto-qnx|'` + ;; + -sim | -es1800* | -hms* | -xray | -os68k* | -none* | -v88r* \ + | -windows* | -osx | -abug | -netware* | -os9* | -beos* | -haiku* \ + | -macos* | -mpw* | -magic* | -mmixware* | -mon960* | -lnews*) + ;; + -mac*) + os=`echo $os | sed -e 's|mac|macos|'` + ;; + -linux-dietlibc) + os=-linux-dietlibc + ;; + -linux*) + os=`echo $os | sed -e 's|linux|linux-gnu|'` + ;; + -sunos5*) + os=`echo $os | sed -e 's|sunos5|solaris2|'` + ;; + -sunos6*) + os=`echo $os | sed -e 's|sunos6|solaris3|'` + ;; + -opened*) + os=-openedition + ;; + -os400*) + os=-os400 + ;; + -wince*) + os=-wince + ;; + -osfrose*) + os=-osfrose + ;; + -osf*) + os=-osf + ;; + -utek*) + os=-bsd + ;; + -dynix*) + os=-bsd + ;; + -acis*) + os=-aos + ;; + -atheos*) + os=-atheos + ;; + -syllable*) + os=-syllable + ;; + -386bsd) + os=-bsd + ;; + -ctix* | -uts*) + os=-sysv + ;; + -nova*) + os=-rtmk-nova + ;; + -ns2 ) + os=-nextstep2 + ;; + -nsk*) + os=-nsk + ;; + # Preserve the version number of sinix5. + -sinix5.*) + os=`echo $os | sed -e 's|sinix|sysv|'` + ;; + -sinix*) + os=-sysv4 + ;; + -tpf*) + os=-tpf + ;; + -triton*) + os=-sysv3 + ;; + -oss*) + os=-sysv3 + ;; + -svr4) + os=-sysv4 + ;; + -svr3) + os=-sysv3 + ;; + -sysvr4) + os=-sysv4 + ;; + # This must come after -sysvr4. + -sysv*) + ;; + -ose*) + os=-ose + ;; + -es1800*) + os=-ose + ;; + -xenix) + os=-xenix + ;; + -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*) + os=-mint + ;; + -aros*) + os=-aros + ;; + -kaos*) + os=-kaos + ;; + -zvmoe) + os=-zvmoe + ;; + -none) + ;; + *) + # Get rid of the `-' at the beginning of $os. + os=`echo $os | sed 's/[^-]*-//'` + echo Invalid configuration \`$1\': system \`$os\' not recognized 1>&2 + exit 1 + ;; +esac +else + +# Here we handle the default operating systems that come with various machines. +# The value should be what the vendor currently ships out the door with their +# machine or put another way, the most popular os provided with the machine. + +# Note that if you're going to try to match "-MANUFACTURER" here (say, +# "-sun"), then you have to tell the case statement up towards the top +# that MANUFACTURER isn't an operating system. Otherwise, code above +# will signal an error saying that MANUFACTURER isn't an operating +# system, and we'll never get to this point. + +case $basic_machine in + spu-*) + os=-elf + ;; + *-acorn) + os=-riscix1.2 + ;; + arm*-rebel) + os=-linux + ;; + arm*-semi) + os=-aout + ;; + c4x-* | tic4x-*) + os=-coff + ;; + # This must come before the *-dec entry. + pdp10-*) + os=-tops20 + ;; + pdp11-*) + os=-none + ;; + *-dec | vax-*) + os=-ultrix4.2 + ;; + m68*-apollo) + os=-domain + ;; + i386-sun) + os=-sunos4.0.2 + ;; + m68000-sun) + os=-sunos3 + # This also exists in the configure program, but was not the + # default. + # os=-sunos4 + ;; + m68*-cisco) + os=-aout + ;; + mips*-cisco) + os=-elf + ;; + mips*-*) + os=-elf + ;; + or32-*) + os=-coff + ;; + *-tti) # must be before sparc entry or we get the wrong os. + os=-sysv3 + ;; + sparc-* | *-sun) + os=-sunos4.1.1 + ;; + *-be) + os=-beos + ;; + *-haiku) + os=-haiku + ;; + *-ibm) + os=-aix + ;; + *-knuth) + os=-mmixware + ;; + *-wec) + os=-proelf + ;; + *-winbond) + os=-proelf + ;; + *-oki) + os=-proelf + ;; + *-hp) + os=-hpux + ;; + *-hitachi) + os=-hiux + ;; + i860-* | *-att | *-ncr | *-altos | *-motorola | *-convergent) + os=-sysv + ;; + *-cbm) + os=-amigaos + ;; + *-dg) + os=-dgux + ;; + *-dolphin) + os=-sysv3 + ;; + m68k-ccur) + os=-rtu + ;; + m88k-omron*) + os=-luna + ;; + *-next ) + os=-nextstep + ;; + *-sequent) + os=-ptx + ;; + *-crds) + os=-unos + ;; + *-ns) + os=-genix + ;; + i370-*) + os=-mvs + ;; + *-next) + os=-nextstep3 + ;; + *-gould) + os=-sysv + ;; + *-highlevel) + os=-bsd + ;; + *-encore) + os=-bsd + ;; + *-sgi) + os=-irix + ;; + *-siemens) + os=-sysv4 + ;; + *-masscomp) + os=-rtu + ;; + f30[01]-fujitsu | f700-fujitsu) + os=-uxpv + ;; + *-rom68k) + os=-coff + ;; + *-*bug) + os=-coff + ;; + *-apple) + os=-macos + ;; + *-atari*) + os=-mint + ;; + *) + os=-none + ;; +esac +fi + +# Here we handle the case where we know the os, and the CPU type, but not the +# manufacturer. We pick the logical manufacturer. +vendor=unknown +case $basic_machine in + *-unknown) + case $os in + -riscix*) + vendor=acorn + ;; + -sunos*) + vendor=sun + ;; + -aix*) + vendor=ibm + ;; + -beos*) + vendor=be + ;; + -hpux*) + vendor=hp + ;; + -mpeix*) + vendor=hp + ;; + -hiux*) + vendor=hitachi + ;; + -unos*) + vendor=crds + ;; + -dgux*) + vendor=dg + ;; + -luna*) + vendor=omron + ;; + -genix*) + vendor=ns + ;; + -mvs* | -opened*) + vendor=ibm + ;; + -os400*) + vendor=ibm + ;; + -ptx*) + vendor=sequent + ;; + -tpf*) + vendor=ibm + ;; + -vxsim* | -vxworks* | -windiss*) + vendor=wrs + ;; + -aux*) + vendor=apple + ;; + -hms*) + vendor=hitachi + ;; + -mpw* | -macos*) + vendor=apple + ;; + -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*) + vendor=atari + ;; + -vos*) + vendor=stratus + ;; + esac + basic_machine=`echo $basic_machine | sed "s/unknown/$vendor/"` + ;; +esac + +echo $basic_machine$os +exit + +# Local variables: +# eval: (add-hook 'write-file-hooks 'time-stamp) +# time-stamp-start: "timestamp='" +# time-stamp-format: "%:y-%02m-%02d" +# time-stamp-end: "'" +# End: diff --git a/modules/maplib/autoconf/configure.ac b/modules/maplib/autoconf/configure.ac new file mode 100644 index 0000000..66da8e3 --- /dev/null +++ b/modules/maplib/autoconf/configure.ac @@ -0,0 +1,55 @@ +dnl -*- sh -*- +AC_INIT(src/maplib-module.c) +AC_PREFIX_DEFAULT(/usr/local) + +AC_CONFIG_AUX_DIR(autoconf) +AC_CANONICAL_HOST +AC_PROG_RANLIB +AC_PROG_INSTALL +AC_PROG_MAKE_SET + +JD_INIT +JD_ANSI_CC +JD_ELF_COMPILER +JD_IEEE_CFLAGS + +AC_PATH_XTRA + +JD_WITH_LIBRARY(slang) + +dnl# Add libraries here + +dnl# This macro inits the module installation dir +JD_SLANG_MODULE_INSTALL_DIR + +dnl Check these header since they cause trouble +AC_CHECK_HEADERS( \ +stdlib.h \ +unistd.h \ +) + +AC_CHECK_SIZEOF(short, 2) +AC_CHECK_SIZEOF(int, 4) +AC_CHECK_SIZEOF(long, 4) +AC_CHECK_SIZEOF(float, 4) +AC_CHECK_SIZEOF(double, 8) + +JD_SET_RPATH($libdir) +ELF_CFLAGS="$ELF_CFLAGS $IEEE_CFLAGS" +CFLAGS="$CFLAGS $IEEE_CFLAGS" + +AC_CONFIG_HEADER(src/config.h:src/config.hin) +AC_OUTPUT(Makefile:autoconf/Makefile.in src/Makefile) + +echo "" +echo "You are compiling with the following compiler configuration:" +echo " CC =" "$CC" +echo " CC_SHARED =" "$CC_SHARED" +echo " CFLAGS =" "$CFLAGS" +echo " LDFLAGS =" "$LDFLAGS" "$DYNAMIC_LINK_FLAGS" +echo "" +echo "The modules will be installed in $MODULE_INSTALL_DIR." +echo "Any associated .sl files will be install in $SL_FILES_INSTALL_DIR" +echo "" +echo "If any of these quantities are incorrect, edit src/Makefile accordingly." +echo "" diff --git a/modules/maplib/autoconf/i686config.cache b/modules/maplib/autoconf/i686config.cache new file mode 100644 index 0000000..d0a0149 --- /dev/null +++ b/modules/maplib/autoconf/i686config.cache @@ -0,0 +1,41 @@ +# This file is a shell script that caches the results of configure +# tests run on this system so they can be shared between configure +# scripts and configure runs. It is not useful on other systems. +# If it contains results you don't want to keep, you may remove or edit it. +# +# By default, configure uses ./config.cache as the cache file, +# creating it if it does not exist already. You can give configure +# the --cache-file=FILE option to use a different cache file; that is +# what configure does when it calls configure scripts in +# subdirectories, so they share the cache. +# Giving --cache-file=/dev/null disables caching, for debugging configure. +# config.status only pays attention to the cache file if you give it the +# --recheck option to rerun configure. +# +ac_cv_func_connect=${ac_cv_func_connect=yes} +ac_cv_func_gethostbyname=${ac_cv_func_gethostbyname=yes} +ac_cv_func_remove=${ac_cv_func_remove=yes} +ac_cv_func_shmat=${ac_cv_func_shmat=yes} +ac_cv_have_x=${ac_cv_have_x='have_x=yes ac_x_includes=/usr/X11R6/include ac_x_libraries=/usr/X11R6/lib'} +ac_cv_header_dlfcn_h=${ac_cv_header_dlfcn_h=yes} +ac_cv_header_stdlib_h=${ac_cv_header_stdlib_h=yes} +ac_cv_header_unistd_h=${ac_cv_header_unistd_h=yes} +ac_cv_lib_ICE_IceConnectionNumber=${ac_cv_lib_ICE_IceConnectionNumber=yes} +ac_cv_lib_dl_dlopen=${ac_cv_lib_dl_dlopen=yes} +ac_cv_lib_dnet_dnet_ntoa=${ac_cv_lib_dnet_dnet_ntoa=no} +ac_cv_lib_dnet_stub_dnet_ntoa=${ac_cv_lib_dnet_stub_dnet_ntoa=no} +ac_cv_path_install=${ac_cv_path_install='/usr/bin/install -c'} +ac_cv_prog_CC=${ac_cv_prog_CC='gcc -pipe'} +ac_cv_prog_CPP=${ac_cv_prog_CPP='gcc -pipe -E'} +ac_cv_prog_RANLIB=${ac_cv_prog_RANLIB=ranlib} +ac_cv_prog_cc_cross=${ac_cv_prog_cc_cross=no} +ac_cv_prog_cc_g=${ac_cv_prog_cc_g=yes} +ac_cv_prog_cc_works=${ac_cv_prog_cc_works=yes} +ac_cv_prog_gcc=${ac_cv_prog_gcc=yes} +ac_cv_prog_gcc_traditional=${ac_cv_prog_gcc_traditional=no} +ac_cv_prog_make_make_set=${ac_cv_prog_make_make_set=yes} +ac_cv_sizeof_double=${ac_cv_sizeof_double=8} +ac_cv_sizeof_float=${ac_cv_sizeof_float=4} +ac_cv_sizeof_int=${ac_cv_sizeof_int=4} +ac_cv_sizeof_long=${ac_cv_sizeof_long=4} +ac_cv_sizeof_short=${ac_cv_sizeof_short=2} diff --git a/modules/maplib/autoconf/install-sh b/modules/maplib/autoconf/install-sh new file mode 100755 index 0000000..e9de238 --- /dev/null +++ b/modules/maplib/autoconf/install-sh @@ -0,0 +1,251 @@ +#!/bin/sh +# +# install - install a program, script, or datafile +# This comes from X11R5 (mit/util/scripts/install.sh). +# +# Copyright 1991 by the Massachusetts Institute of Technology +# +# Permission to use, copy, modify, distribute, and sell this software and its +# documentation for any purpose is hereby granted without fee, provided that +# the above copyright notice appear in all copies and that both that +# copyright notice and this permission notice appear in supporting +# documentation, and that the name of M.I.T. not be used in advertising or +# publicity pertaining to distribution of the software without specific, +# written prior permission. M.I.T. makes no representations about the +# suitability of this software for any purpose. It is provided "as is" +# without express or implied warranty. +# +# Calling this script install-sh is preferred over install.sh, to prevent +# `make' implicit rules from creating a file called install from it +# when there is no Makefile. +# +# This script is compatible with the BSD install script, but was written +# from scratch. It can only install one file at a time, a restriction +# shared with many OS's install programs. + + +# set DOITPROG to echo to test this script + +# Don't use :- since 4.3BSD and earlier shells don't like it. +doit="${DOITPROG-}" + + +# put in absolute paths if you don't have them in your path; or use env. vars. + +mvprog="${MVPROG-mv}" +cpprog="${CPPROG-cp}" +chmodprog="${CHMODPROG-chmod}" +chownprog="${CHOWNPROG-chown}" +chgrpprog="${CHGRPPROG-chgrp}" +stripprog="${STRIPPROG-strip}" +rmprog="${RMPROG-rm}" +mkdirprog="${MKDIRPROG-mkdir}" + +transformbasename="" +transform_arg="" +instcmd="$mvprog" +chmodcmd="$chmodprog 0755" +chowncmd="" +chgrpcmd="" +stripcmd="" +rmcmd="$rmprog -f" +mvcmd="$mvprog" +src="" +dst="" +dir_arg="" + +while [ x"$1" != x ]; do + case $1 in + -c) instcmd="$cpprog" + shift + continue;; + + -d) dir_arg=true + shift + continue;; + + -m) chmodcmd="$chmodprog $2" + shift + shift + continue;; + + -o) chowncmd="$chownprog $2" + shift + shift + continue;; + + -g) chgrpcmd="$chgrpprog $2" + shift + shift + continue;; + + -s) stripcmd="$stripprog" + shift + continue;; + + -t=*) transformarg=`echo $1 | sed 's/-t=//'` + shift + continue;; + + -b=*) transformbasename=`echo $1 | sed 's/-b=//'` + shift + continue;; + + *) if [ x"$src" = x ] + then + src=$1 + else + # this colon is to work around a 386BSD /bin/sh bug + : + dst=$1 + fi + shift + continue;; + esac +done + +if [ x"$src" = x ] +then + echo "install: no input file specified" + exit 1 +else + true +fi + +if [ x"$dir_arg" != x ]; then + dst=$src + src="" + + if [ -d $dst ]; then + instcmd=: + chmodcmd="" + else + instcmd=mkdir + fi +else + +# Waiting for this to be detected by the "$instcmd $src $dsttmp" command +# might cause directories to be created, which would be especially bad +# if $src (and thus $dsttmp) contains '*'. + + if [ -f $src -o -d $src ] + then + true + else + echo "install: $src does not exist" + exit 1 + fi + + if [ x"$dst" = x ] + then + echo "install: no destination specified" + exit 1 + else + true + fi + +# If destination is a directory, append the input filename; if your system +# does not like double slashes in filenames, you may need to add some logic + + if [ -d $dst ] + then + dst="$dst"/`basename $src` + else + true + fi +fi + +## this sed command emulates the dirname command +dstdir=`echo $dst | sed -e 's,[^/]*$,,;s,/$,,;s,^$,.,'` + +# Make sure that the destination directory exists. +# this part is taken from Noah Friedman's mkinstalldirs script + +# Skip lots of stat calls in the usual case. +if [ ! -d "$dstdir" ]; then +defaultIFS=' +' +IFS="${IFS-${defaultIFS}}" + +oIFS="${IFS}" +# Some sh's can't handle IFS=/ for some reason. +IFS='%' +set - `echo ${dstdir} | sed -e 's@/@%@g' -e 's@^%@/@'` +IFS="${oIFS}" + +pathcomp='' + +while [ $# -ne 0 ] ; do + pathcomp="${pathcomp}${1}" + shift + + if [ ! -d "${pathcomp}" ] ; + then + $mkdirprog "${pathcomp}" + else + true + fi + + pathcomp="${pathcomp}/" +done +fi + +if [ x"$dir_arg" != x ] +then + $doit $instcmd $dst && + + if [ x"$chowncmd" != x ]; then $doit $chowncmd $dst; else true ; fi && + if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dst; else true ; fi && + if [ x"$stripcmd" != x ]; then $doit $stripcmd $dst; else true ; fi && + if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dst; else true ; fi +else + +# If we're going to rename the final executable, determine the name now. + + if [ x"$transformarg" = x ] + then + dstfile=`basename $dst` + else + dstfile=`basename $dst $transformbasename | + sed $transformarg`$transformbasename + fi + +# don't allow the sed command to completely eliminate the filename + + if [ x"$dstfile" = x ] + then + dstfile=`basename $dst` + else + true + fi + +# Make a temp file name in the proper directory. + + dsttmp=$dstdir/#inst.$$# + +# Move or copy the file name to the temp name + + $doit $instcmd $src $dsttmp && + + trap "rm -f ${dsttmp}" 0 && + +# and set any options; do chmod last to preserve setuid bits + +# If any of these fail, we abort the whole thing. If we want to +# ignore errors from any of these, just make sure not to ignore +# errors from the above "$doit $instcmd $src $dsttmp" command. + + if [ x"$chowncmd" != x ]; then $doit $chowncmd $dsttmp; else true;fi && + if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dsttmp; else true;fi && + if [ x"$stripcmd" != x ]; then $doit $stripcmd $dsttmp; else true;fi && + if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dsttmp; else true;fi && + +# Now rename the file to the real destination. + + $doit $rmcmd -f $dstdir/$dstfile && + $doit $mvcmd $dsttmp $dstdir/$dstfile + +fi && + + +exit 0 diff --git a/modules/maplib/autoconf/mkinsdir.sh b/modules/maplib/autoconf/mkinsdir.sh new file mode 100755 index 0000000..cd1fe0a --- /dev/null +++ b/modules/maplib/autoconf/mkinsdir.sh @@ -0,0 +1,32 @@ +#! /bin/sh +# mkinstalldirs --- make directory hierarchy +# Author: Noah Friedman +# Created: 1993-05-16 +# Public domain + +errstatus=0 + +for file +do + set fnord `echo ":$file" | sed -ne 's/^:\//#/;s/^://;s/\// /g;s/^#/\//;p'` + shift + + pathcomp= + for d in ${1+"$@"} ; do + pathcomp="$pathcomp$d" + case "$pathcomp" in + -* ) pathcomp=./$pathcomp ;; + esac + + if test ! -d "$pathcomp"; then + echo "mkdir $pathcomp" 1>&2 + mkdir "$pathcomp" || errstatus=$? + fi + + pathcomp="$pathcomp/" + done +done + +exit $errstatus + +# mkinstalldirs ends here diff --git a/modules/maplib/doc/tm/Makefile b/modules/maplib/doc/tm/Makefile new file mode 100644 index 0000000..f074e12 --- /dev/null +++ b/modules/maplib/doc/tm/Makefile @@ -0,0 +1,90 @@ +# -*- sh -*- +# +# To create the SGML files, you will need to install the tm-utils +# package. See http://www.jedsoft.org/ for more information. +# +TMEXPAND = /aluche/d1/web/tm-dist/bin/tmexpand +SL2TM = sl2tm +MACRODIR = /aluche/d1/web/tm-dist/macros +TM2HLP = $(TMEXPAND) -I$(MACRODIR) -Mslhlp + +MODULE = maplib +HLPFUNS_TM = $(MODULE)funs.tm +AUTOGEN_TM = +MODULE_DEPS = $(MODULE)funs.tm $(AUTOGEN_TM) +HLP_FILE_DEPS = + +TXT_FILES = $(MODULE).txt +SGML_FILES = $(MODULE).sgml +HTML_FILES = $(MODULE).html +TEX_FILES = $(MODULE).tex +PS_FILES = $(MODULE).ps +PDF_FILES = $(MODULE).pdf +HLP_FILE = $(MODULE).hlp + +SGML2LATEX = sgml2latex -p letter -o tex +SGML2HTML = sgml2html +SGML2TXT = sgml2txt -f +LATEX = latex +PDFLATEX = pdflatex + +TEXTDIR = ../text +PSDIR = ../ps +HTMLDIR = ../html +SGMLDIR = ../sgml +PDFDIR = ../pdf +HELPDIR = ../help + +SUBDIRS = $(TEXTDIR) $(HTMLDIR) $(PSDIR) $(SGMLDIR) $(PDFDIR) $(HELPDIR) +SRCDIR = `pwd` + +default: $(TXT_FILES) $(HLP_FILE) +all: $(HTML_FILES) $(PDF_FILES) $(TXT_FILES) $(HLP_FILE) +text-files: $(TXT_FILES) +#----- SGML Files ----------------------------------------------------------- +$(MODULE).sgml : $(MODULE).tm $(MODULE_DEPS) + $(TMEXPAND) -I$(MACRODIR) $(MODULE).tm $(MODULE).sgml +#----- HTML Files ----------------------------------------------------------- +$(MODULE).html : $(MODULE).sgml + $(SGML2HTML) $(MODULE).sgml +#----- TeX Files ------------------------------------------------------------ +$(MODULE).tex : $(MODULE).sgml + $(SGML2LATEX) $(MODULE).sgml + ./fixtex.sl $(MODULE).tex +#----- PDF Files ----------------------------------------------------------- +$(MODULE).pdf : $(MODULE).tex + $(MAKE) texclean + $(PDFLATEX) $(MODULE).tex + $(PDFLATEX) $(MODULE).tex + $(PDFLATEX) $(MODULE).tex +#----- PS Files ----------------------------------------------------------- +$(MODULE).ps : $(MODULE).tex texclean + $(LATEX) $(MODULE).tex + $(LATEX) $(MODULE).tex + $(LATEX) $(MODULE).tex + dvips -o $(MODULE).ps $(MODULE).dvi +#----- Text Files ----------------------------------------------------------- +$(MODULE).txt: $(MODULE).sgml + $(SGML2TXT) $(MODULE).sgml + ./fixtxt $(MODULE).txt +#---------------------------------------------------------------------------- +help-files: $(HLP_FILE) +$(HLP_FILE): $(HLPFUNS_TM) $(HLP_FILE_DEPS) + $(TMEXPAND) -I$(MACRODIR) -Mslhlp $(HLPFUNS_TM) $(HLP_FILE) +texclean: + -rm -f *.dvi *.log *.aux *.toc *.out +clean: texclean + -rm -f *~ rtl/*.BAK rtl/*~ *.tmp *-error +distclean: clean + -rm -f *.html *.ps $(HLP_FILE) $(TXT_FILES) $(TEX_FILES) $(SGML_FILES) $(PDF_FILES) $(AUTOGEN_TM) +install-txt: $(TXT_FILES) + -mv $(TXT_FILES) ../text +install-help: $(HLP_FILE) + -mkdir -p $(HELPDIR) + -mv $(HLP_FILE) $(HELPDIR) +install-all: all install-help install-txt $(PDF_FILES) + -mkdir -p $(HTMLDIR) $(PSDIR) $(PDFDIR) + -mv *.html $(HTMLDIR) + -mv $(PDF_FILES) ../pdf +# -mv $(PS_FILES) ../ps +install: install-txt install-help diff --git a/modules/maplib/doc/tm/fixtex.sl b/modules/maplib/doc/tm/fixtex.sl new file mode 100644 index 0000000..a0dd364 --- /dev/null +++ b/modules/maplib/doc/tm/fixtex.sl @@ -0,0 +1,131 @@ +#!/usr/bin/env jed-script + +private variable Version = "0.3.2-0"; + +if (__argc != 2) +{ + message ("Version $Version Usage: ./fixtex.sl "$); + quit_jed (); +} + +variable file = __argv[1]; +() = read_file (file); + +% Patch up the >,< signs +bob (); +replace ("$<$", "<"); +replace ("$>$", ">"); + +% It appears that sgml2tex screws up _for in section titles, producing \_{for}. +replace ("ion\\_{", "ion{\\_"); + +% Make the first chapter a preface +bob (); +if (bol_fsearch ("\\chapter{Preface}")) +{ + push_spot (); + push_mark (); + go_right (8); insert ("*"); % \chapter{ --> \chapter*{ + () = bol_fsearch ("\\chapter{"); + push_spot (); + + insert("\\tableofcontents\n"); + eol (); + insert ("\n\\pagenumbering{arabic}"); + + pop_spot (); + narrow (); + bob (); + replace ("\\section{", "\\section*{"); + widen (); + + if (bol_bsearch ("\\tableofcontents")) + delete_line (); + + pop_spot (); + if (bol_bsearch ("\\maketitle")) + insert ("\\pagenumbering{roman}\n"); + +} + +static define fixup_urldefs () +{ + % pdflatex cannot grok urldef + bob (); + while (bol_fsearch("\\urldef{") and ffind ("\\url{")) + { + variable line = line_as_string (); + bol (); + insert ("\\ifpdf\n"); + + deln (7); insert ("\\newcommand"); + push_mark (); + ()=ffind ("}"); + variable macro = bufsubstr (); + () = ffind ("\\url"); + go_left (1); + trim (); + insert("{"); + + % pdflatex cannot grok # in urls. Nuke em. + if (ffind ("#")) + { + del_eol (); + insert ("}"); + } + eol (); + insert ("}\n\\else\n"); + insert (line); newline (); + insert ("\\fi\n"); + } +} + +static define remove_repeated_urls () +{ + variable name, url; + variable names = Assoc_Type[Int_Type, 0]; + while (bol_fsearch ("{\\em ")) + { + go_right (4); + skip_white (); + push_mark (); + () = ffind ("}"); + !if (looking_at ("} {\\tt ")) + { + pop_mark(0); + continue; + } + name = bufsubstr (); + if (names[name]) + { + go_right(1); + push_mark (); + () = ffind ("}"); + go_right(1); + del_region (); + } + else + { + names[name] = 1; + go_right(1); + () = ffind ("}"); + go_right (1); + } + + % Now remove empty lines inserted by the broken sgml2latex program. + skip_white (); + !if (eolp ()) + continue; + go_right(1); + skip_white (); + if (eolp ()) + del (); + } +} + +fixup_urldefs (); +remove_repeated_urls (); +save_buffer (); +quit_jed (); + + diff --git a/modules/maplib/doc/tm/fixtxt b/modules/maplib/doc/tm/fixtxt new file mode 100755 index 0000000..9228668 --- /dev/null +++ b/modules/maplib/doc/tm/fixtxt @@ -0,0 +1,97 @@ +#!/usr/bin/env jed-script + +if (__argc != 2) +{ + () = fprintf (stderr, "Usage: %s file.txt\n", __argv[0]); + exit (1); +} + +% The txt file looks ugly and the contents at the beginning are +% totally misleading. + +static define process_file (file) +{ + variable txt; + + () = read_file (file); + % trim excess blank lines + trim_buffer (); + + % fix the underscore chars + bob (); + while (fsearch ("_.ds h ")) + { + deln (7); + insert ("_"); + % Unfortunately, there are other things associated with this that are + % messed up. See my debian linuxdoc bug report. In particular, the + % table of contents associated with this are hosed and possibly the + % rest of the text on this line. Here is a fix for contents. + push_spot (); + bol_skip_white (); + push_mark (); + skip_chars ("0-9."); + variable sect = bufsubstr (); + skip_white (); + push_mark (); + eol (); + txt = bufsubstr (); + eob (); + () = bsearch ("Table of Contents"); + sect = strcat (" ",sect," "); + if (bol_fsearch (sect)) + { + go_right(strlen (sect)); + del_eol (); + insert (txt); + } + pop_spot (); + } + + % Delete the contents at the beginning. They are wrong. + bob (); + if (fsearch ("Table of Contents")) + { + bol (); + push_mark (); + if (fsearch ("____________________________________________")) + { + go_down(1); + del_region (); + % Grab the contents from the bottom + push_spot (); + eob (); + () = bsearch ("Table of Contents"); + bol (); + push_mark (); + % Get rid of . . . stufff since the page numbers are meaningless + while (re_fsearch ("\\d$")) + { + bol_skip_white (); + % Keep only levels 1. and 1.2. + if (re_looking_at ("\d+\.\d+\.\d+"R)) + { + delete_line (); + continue; + } + eol (); + push_mark (); + bskip_chars ("[0-9]"); + bskip_chars (" ."); + del_region (); + } + eob (); + txt = bufsubstr_delete (); + pop_spot (); + insert (txt); + } + else pop_mark (0); + } + + + save_buffer (); +} + +process_file (__argv[1]); +exit (0); + diff --git a/modules/maplib/doc/tm/maplib.tm b/modules/maplib/doc/tm/maplib.tm new file mode 100644 index 0000000..f98e7e9 --- /dev/null +++ b/modules/maplib/doc/tm/maplib.tm @@ -0,0 +1,183 @@ +#% -*- mode: tm; mode: fold -*- + +#%{{{Macros + +#i linuxdoc.tm +#d it#1 $1 + +#d slang \bf{S-lang} +#d exmp#1 \tt{$1} +#d var#1 \tt{$1} + +#d ivar#1 \tt{$1} +#d ifun#1 \tt{$1} +#d cvar#1 \tt{$1} +#d cfun#1 \tt{$1} +#d svar#1 \tt{$1} +#d sfun#1 \tt{$1} +#d icon#1 \tt{$1} + +#d chapter#1 $1

+#d preface +#d tag#1 $1 + +#d function#1 \sect{$1\label{$1}} +#d variable#1 \sect{$1\label{$1}} +#d function_sect#1 \sect{$1} +#d begin_constant_sect#1 \sect{$1} +#d constant#1 $1 +#d end_constant_sect + +#d synopsis#1 Synopsis $1 +#d keywords#1 Keywords $1 +#d usage#1 Usage $1 +#d description Description +#d example Example +#d notes Notes +#d seealso#1 See Also \linuxdoc_list_to_ref{$1} +#d done

+#d -1 -1 +#d 0 0 +#d 1 1 +#d 2 2 +#d 3 3 +#d 4 4 +#d 5 5 +#d 6 6 +#d 7 7 +#d 8 8 +#d 9 9 +#d NULL NULL +#d documentstyle book + +#%}}} + +#d module#1 \tt{$1} +#d file#1 \tt{$1} +#d slang-documentation \ + \url{http://www.jedsoft.org/slang/doc/html/slang.html}{S-Lang documentation} + +\linuxdoc +\begin{\documentstyle} + +\title S-Lang Maplib Module Reference +\author John E. Davis, \tt{} +\date \__today__ + +\toc + +\chapter{Introduction to the Maplib Module} +The routines in this module implement various mapping projections from +a unit sphere to a surface such as a plane or cylinder. + +In all the projections, points on the sphere are specified using +latitude and longitude coordinates expressed in degrees. Values of +latitude run from -90 degrees at the south pole to +90 degrees at the +north pole. Longitude values run from -180 to 180 in an "easterly" +direction. + +At the moment, the following map mappings are supported by the module: +\begin{descrip} + \tag{Gnomic} + A perspective projection from the center of a sphere to a plane + tangent to some point on the surface of the sphere. Great + circles on the sphere are mapped to straight lines on the plane. + \tag{Orthographic} + A perspective projection of the unit sphere to a tangent plane + on the unit sphere from an infinite distance. + \tag{Stereographic} + A perspective projection to a tangent plane from the point on the + unit sphere that is antipodal to the point of tangency. + \tag{Lambert} + An azimuthal equal area projection. + \tag{Hammer-Aitoff} + An equal area projection of the sphere onto an ellipse. +\end{descrip} + In addition, the module supports the additional transformations: +\begin{descrip} + \tag{Linear} + A simple 1-1 mapping from a point on one plane to a point on + another. The mapping may involve translation, scaling, or + rotation. + \tag{Sphere} + A rotation of a sphere onto itself. +\end{descrip} + +Addition map projections will be added in future versions of the module. + +\chapter{Usage} + + In order to a particular map projection, it must first be created via + the \ifun{maplib_new} function. It takes a single string parameter + that specifies the particular mapping and returns a structure that + defines the map. For example, a Gnomic transformation may be + allocated using +#v+ + p = maplib_new ("gnomic"); +#v- + The structure returned by the \ifun{maplib_new} function contains + fields that are specified to the mapping. In the case of the Gnomic + transformation, the structure has the fields: +#v+ + field-name default-value description + name gnomic The name of the transformation + lon0 0 The longitude of the tangent point + lat0 90 The latitude of the tangent point + x0 0 (x0,y0) are the coordinates of the + y0 0 tangent point in the tangent plane + xscale 1 Scale factor in the x direction + yscale 1 Scale factor in the y direction +#v- + As the table shows, the default location of the tangent plane is at + the north pole of the unit sphere. The location of the tangent + plane may be changed to an arbitrary point on the sphere by setting + the \exmp{lon0} and \exmp{lat0} parameters to the desired values. + + The \ifun{maplib_project} function is used to carry out the mapping + of a point on the unit sphere. It takes three arguments: the + structure that defines the transformation, and the longitude and + latitude of the point to be mapped. For example, +#v+ + (x,y) = maplib_project (p, 10, 70); +#v- + computes the coordinates of point with a longitude of 10 degrees and + a latitude of 70 degrees under the mapping specified by \exmp{p}. + + Similarly, the reverse transformation back to the sphere may be + carried out using the \ifun{maplib_deproject} function: +#v+ + (lon,lat) = maplib_deproject (p, x, y); +#v- + + For some purposes one is interested in transformation from one image + surface to another. For example, consider two tangent planes: one at + the north pole and one at a longitude of 20 and a latitude of 80 + degrees. To transform points from the latter plane to the one at the + north pole under the gnomic mapping, it is necessary to first + allocate the appropriate transformations: +#v+ + A = maplib_new ("gnomic"); A.lon0 = 0; A.lat0 = 90; + B = maplib_new ("gnomic"); B.lon0 = 20; B.lat0 = 80; +#v- + One way to transform a point \exmp{(x_B,y_B)} on the plane defined + by the transformation \exmp{B} to the plane at the north pole + defined by \exmp{A} is via: +#v+ + (lon, lat) = maplib_deproject (B, x_B, y_B); + (x_A, y_A) = maplib_project (A, lon, lat); +#v- + The problem with this approach is that there may be some loss of + accuracy by computing the intermediate coordinates. This is because + if the coordinates given to either \exmp{maplib_project} or + \exmp{maplib_deproject} are single precision values, the functions + will return the results as single precision values. For this + reason, the \module{maplib} module includes a function called + \ifun{maplib_reproject} that avoids this problem: +#v+ + (x_A,y_A) = maplib_reproject (A, B, x_A, x_B); +#v- + +\chapter{Maplib Module Function Reference} +#i maplibfuns.tm + +\end{\documentstyle} diff --git a/modules/maplib/doc/tm/maplibfuns.tm b/modules/maplib/doc/tm/maplibfuns.tm new file mode 100644 index 0000000..e8eeb31 --- /dev/null +++ b/modules/maplib/doc/tm/maplibfuns.tm @@ -0,0 +1,123 @@ +#d tag#1 $1 + +\function{maplib_new} +\synopsis{Create a new mapping instance} +\usage{m = maplib_new (String_Type mapname)} +\description + This function creates a new instance of a mapping of the specified + name. If the mapping exists, the function returns a structure whose + fields depend upon the specified mapping. Otherwise the function + will generate an exception. + + The following mappings are supported: +#v+ + mapname description + gnomic Gnomic + ortho Orthographic + stereo Stereographic + lambert Lambert Azimuthal Equal-Area + hammer Hammer-Aitoff + sphere Rotation of a sphere + linear Linear Transformation +#v- + The fields of the structure returned by the \ifun{maplib_new} + function vary with the name of the mapping. Unless otherwise + specified, most of the maps contain the following fields: +#v+ + field-name default-value description + name The name of the transformation + lon0 0 The longitude of the map center + lat0 90 The latitude of the map center + x0 0 (x0,y0) are the coordinates of the + y0 0 plane at the map center + xscale 1 Scale factor in the x direction + yscale 1 Scale factor in the y direction +#v- + For tangent plane projections, (lon0,lat0) specify the position of + the tangent plane on the sphere. + + The following transformations return a structure whose fields differ + from the above: +\begin{descrip} + \tag{sphere} +#v+ + field-name default-value description + name sphere Rotation of the unit sphere + lon0,lat0 (0,90) The rotation takes the point (lon0,lat0) + lon1,lat1 (0,90) into the point (lon1,lat1) + beta 0 Additional rotation about (lon1,lat1) +#v- + \tag{linear} +#v+ + field-name default-value description + name linear A linear transformation + x0,y0 (0,0) (x',y') = (x1,y1) + A#(x-x0,y-y0) + x1,y1 (0,0) + A [1,0,0,1] +#v- +\end{descrip} +\example +#v+ + m = maplib_new ("gnomic"); + m.lon0 = 20; + m.lat0 = 35; + (x,y) = maplib_project (m, 45, 22); +#v- +\seealso{maplib_project, maplib_deproject, maplib_reproject} +\done + +\function{maplib_project} +\synopsis{Project} +\usage{(x,y) = maplib_project (Struct_Type m, Double_Type lon, Double_Type lat)} +\description + This function applies the mapping specified by the first parameter + \exmp{m} to the longitude and latitude pairs \exmp{(lon,lat)}. The + coordinates of the projected points will be returned. +\notes + For some transformations, the parameters \exmp{lon} and \exmp{lat} + need not represent longitude and latitude coordinates. The + \exmp{"linear"} transformtion is one example. + + This function is the inverse of \ifun{maplib_deproject}. +\seealso{maplib_new, maplib_deproject, maplib_reproject} +\done + +\function{maplib_deproject} +\synopsis{Project} +\usage{(lon,lat) = maplib_project (Struct_Type m, Double_Type x, Double_Type y)} +\description + This function applies the inverse of the mapping specified by the + first parameter \exmp{m} to the projected coordinates \exmp{(x,y)} + and returns the result. +\notes + This function is the inverse of \ifun{maplib_project}. +\seealso{maplib_new, maplib_project, maplib_reproject} +\done + + +\function{maplib_reproject} +\synopsis{Reproject the coordinates to another projection} +\usage{(x1,y1)=maplib_reproject (m_to, m_from, x, y)} +#v+ + Struct_Type m_to, m_from; + Double_Type x, Double_Type y; +#v- +\description + The \ifun{maplib_reproject} function reprojects the coordinates + \exmp{(x,y)} associated with the mapping \exmp{m_from} to coordinates + described by the mapping \exmp{m_to}. This function is equivalent to +#v+ + (lon, lat) = maplib_deproject (m_from, x, y); + (x1, y1) = maplib_reproject (m_to, lon, lat); +#v- +\notes + It is strongly recommended that this function be used for + reprojections rather than the two step process outlined above. The + main reason is that if \exmp{(x,y)} are expressed in single + precision, then the intermediate coordinates \exmp{(lon, lat)} will + be returned as single precision values. Hence, there could be some + loss in precision when using the two step process. Using + \ifun{maplib_reproject} does not have this problem because double + precision is used throughout. +\seealso{maplib_new, maplib_project, maplib_deproject} +\done diff --git a/modules/maplib/doc/tm/rtl/maplibfuns.tm b/modules/maplib/doc/tm/rtl/maplibfuns.tm new file mode 100644 index 0000000..c9102fd --- /dev/null +++ b/modules/maplib/doc/tm/rtl/maplibfuns.tm @@ -0,0 +1,122 @@ + +\function{maplib_new} +\synopsis{Create a new mapping instance} +\usage{m = maplib_new (String_Type mapname)} +\description + This function creates a new instance of a mapping of the specified + name. If the mapping exists, the function returns a structure whose + fields depend upon the specified mapping. Otherwise the function + will generate an exception. + + The following mappings are supported: +#v+ + mapname description + gnomic Gnomic + ortho Orthographic + stereo Stereographic + lambert Lambert Azimuthal Equal-Area + hammer Hammer-Aitoff + sphere Rotation of a sphere + linear Linear Transformation +#v- + The fields of the structure returned by the \ifun{maplib_new} + function vary with the name of the mapping. Unless otherwise + specified, most of the maps contain the following fields: +#v+ + field-name default-value description + name The name of the transformation + lon0 0 The longitude of the map center + lat0 90 The latitude of the map center + x0 0 (x0,y0) are the coordinates of the + y0 0 plane at the map center + xscale 1 Scale factor in the x direction + yscale 1 Scale factor in the y direction +#v- + For tangent plane projections, (lon0,lat0) specify the position of + the tangent plane on the sphere. + + The following transformations return a structure whose fields differ + from the above: +\begin{descrip} + \tag{sphere} +#v+ + field-name default-value description + name sphere Rotation of the unit sphere + lon0,lat0 (0,90) The rotation takes the point (lon0,lat0) + lon1,lat1 (0,90) into the point (lon1,lat1) + beta 0 Additional rotation about (lon1,lat1) +#v- + \tag{linear} +#v+ + field-name default-value description + name linear A linear transformation + x0,y0 (0,0) (x',y') = (x1,y1) + A#(x-x0,y-y0) + x1,y1 (0,0) + A [1,0,0,1] +#v- +\end{descrip} +\example +#v+ + m = maplib_new ("gnomic"); + m.lon0 = 20; + m.lat0 = 35; + (x,y) = maplib_project (m, 45, 22); +#v- +\seealso{maplib_project, maplib_deproject, maplib_reproject} +\done + +\function{maplib_project} +\synopsis{Project} +\usage{(x,y) = maplib_project (Struct_Type m, Double_Type lon, Double_Type lat)} +\description + This function applies the mapping specified by the first parameter + \exmp{m} to the longitude and latitude pairs \exmp{(lon,lat)}. The + coordinates of the projected points will be returned. +\notes + For some transformations, the parameters \exmp{lon} and \exmp{lat} + need not represent longitude and latitude coordinates. The + \exmp{"linear"} transformtion is one example. + + This function is the inverse of \ifun{maplib_deproject}. +\seealso{maplib_new, maplib_deproject, maplib_reproject} +\done + +\function{maplib_deproject} +\synopsis{Project} +\usage{(lon,lat) = maplib_project (Struct_Type m, Double_Type x, Double_Type y)} +\description + This function applies the inverse of the mapping specified by the + first parameter \exmp{m} to the projected coordinates \exmp{(x,y)} + and returns the result. +\notes + This function is the inverse of \ifun{maplib_project}. +\seealso{maplib_new, maplib_project, maplib_reproject} +\done + + +\function{maplib_reproject} +\synopsis{Reproject the coordinates to another projection} +\usage{(x1,y1)=maplib_reproject (m_to, m_from, x, y)} +#v+ + Struct_Type m_to, m_from; + Double_Type x, Double_Type y; +#v- +\description + The \ifun{maplib_reproject} function reprojects the coordinates + \exmp{(x,y)} associated with the mapping \exmp{m_from} to coordinates + described by the mapping \exmp{m_to}. This function is equivalent to +#v+ + (lon, lat) = maplib_deproject (m_from, x, y); + (x1, y1) = maplib_reproject (m_to, lon, lat); +#v- +\notes + It is strongly recommended that this function be used for + reprojections rather than the two step process outlined above. The + main reason is that if \exmp{(x,y)} are expressed in single + precision, then the intermediate coordinates \exmp{(lon, lat)} will + be returned as single precision values. Hence, there could be some + loss in precision when using the two step process. Using + \ifun{maplib_reproject} does not have this problem because double + precision is used throughout. +\seealso{maplib_new, maplib_project, maplib_deproject} +\done diff --git a/modules/maplib/maplib.lis b/modules/maplib/maplib.lis new file mode 100644 index 0000000..36f2628 --- /dev/null +++ b/modules/maplib/maplib.lis @@ -0,0 +1,25 @@ +@maplib.lis +@configure 0755 +@COPYRIGHT +@README +@INSTALL.txt + +@autoconf/Makefile.in +@autoconf/aclocal.m4 +@autoconf/config.guess 0755 +@autoconf/config.sub 0755 +@autoconf/configure.in +@autoconf/install-sh 0755 +@autoconf/mkinsdir.sh 0755 + +@src/config.hin +@src/Makefile.in +@src/version.h +@src/maplib.sl +@src/maplib-module.c + +@doc/tm/Makefile +@doc/tm/fixtex.sl +@doc/tm/maplib.tm + +@src/tests/test_maplib.sl diff --git a/modules/maplib/misc/coastline.dat.gz b/modules/maplib/misc/coastline.dat.gz new file mode 100644 index 0000000..2afadd8 Binary files /dev/null and b/modules/maplib/misc/coastline.dat.gz differ diff --git a/modules/maplib/misc/readcoastline.sl b/modules/maplib/misc/readcoastline.sl new file mode 100644 index 0000000..5360c25 --- /dev/null +++ b/modules/maplib/misc/readcoastline.sl @@ -0,0 +1,450 @@ +require ("xfig"); +require ("maplib"); +require ("structfuns"); + +_debug_info=1; +static variable Coastline_Data_Type = struct +{ + lon, lat, next +}; + +static define new_contour (last) +{ + variable next = @Coastline_Data_Type; + if (last != NULL) + last.next = next; + return next; +} + +define read_coastline_data (file) +{ + % The coastline data file has contours separated by + % # -b + variable list = new_contour (NULL); + variable this = list; + variable i = 0; + variable n = 100; + variable lon = Double_Type[n], lat = Double_Type[n]; + foreach (fopen (file, "r")) + { + variable line = (); + variable x, y; + + if (2 != sscanf (line, "%g %g", &x, &y)) + { + if (i > 0) + { + this.lat = lat[[0:i-1]]; + this.lon = lon[[0:i-1]]; + this = new_contour (this); + i = 0; + } + continue; + } + + if (i >= n) + { + lat = [lat, lat]; + lon = [lon, lon]; + n *= 2; + } + + lat[i] = y; + lon[i] = x; + + i++; + } + + if (i > 0) + { + this.lat = lat[[0:i-1]]; + this.lon = lon[[0:i-1]]; + } + return list; +} + +static define read_cities (file) +{ + variable lines = fgetslines (fopen (file,"r")); + variable n = length (lines); + variable city = String_Type[n]; + variable country = String_Type[n]; + variable lon = Float_Type[n]; + variable lat = Float_Type[n]; + + variable i = 0; + foreach (lines) + { + variable line = (); + if (line[0] == '#') + continue; + variable xcity, xcountry, xlon, xlat; + if (4 != sscanf (line, "%[^,], %s\t%f\t%f", &xcity, &xcountry, &xlon, &xlat)) + continue; + + city[i] = xcity; + country[i] = xcountry; + lon[i] = xlon; + lat[i] = xlat; + i++; + } + + variable s = struct + { + city, country, lon, lat + }; + i = [0:i-1]; + s.city = city[i]; + s.country = country[i]; + s.lon = lon[i]; + s.lat = lat[i]; + return s; +} + +private define local_maplib_new (name) +{ + return maplib_new (name); + + if (name == "hammer") + { + variable m = struct + { + name, lon0, lat0, sphere, lambert + }; + m.name = name; + m.lon0 = 0.0; + m.lat0 = 90.0; + m.sphere = maplib_new ("sphere"); + m.lambert = maplib_new ("lambert"); + return m; + } + + return maplib_new (name); +} + +private define local_maplib_project (m, x, y) +{ + return maplib_project (m, x, y); + + if (m.name == "hammer") + { + variable sphere = m.sphere; + sphere.lon0 = m.lon0; + sphere.lat0 = m.lat0; + (x,y) = maplib_project (sphere, x, y); + (x,y) = maplib_project (m.lambert, 0.5*x, y); + return 2.0*x, y; + } + return maplib_project (m, x, y); +} + +define get_data_limits (c, m) +{ + variable x, y; + variable min_x, max_x, min_y, max_y; + + min_x = 1e37; + max_x = -1e37; + min_y = 1e37; + max_y = -1e37; + + variable cc; + foreach (c) using ("next") + { + cc = (); + (x, y) = local_maplib_project (m, cc.lon, cc.lat); + variable i = where ((x==x) and (y==y)); + min_x = min([min_x, x[i]]); + max_x = max([max_x, x[i]]); + min_y = min([min_y, y[i]]); + max_y = max([max_y, y[i]]); + } + return min_x, max_x, min_y, max_y; +} + +define plot_coastline_data (c, fun, m, lon_min, lon_max, lat_min, lat_max) +{ + variable lon = c.lon, lat = c.lat; + + if (0 == length (where ((lon >= lon_min) and (lon < lon_max)))) + return; + + if (0 == length (where ((lat >= lat_min) and (lat < lat_max)))) + return; + + (@fun) (local_maplib_project (m, lon, lat)); +} + +#iffalse +static define add_latitude_longitude_tics (w, m, x0, x1, y0, y1) +{ + variable lat0, lon0, lat1, lon1, lat, lon, x, y; + + (lon0, lat0) = local_maplib_deproject (m, x0, y0); + (lon1, lat1) = local_maplib_deproject (m, x0, y1); + if (lon0 == NULL) + { + x = 0.5*(x0+x1); + while () + } +} +#endif + +static define make_ylabel (w, lon, x, y, x0, x1, y0, y1) +{ + variable i = where (x == x); + x = x[i]; y = y[i]; + if (length(x) <= 2) + return; + variable sgn = (x >= x1); + variable dsgn = shift(sgn,1)-sgn; + dsgn[-1] = dsgn[-2]; + i = where (dsgn != 0); + if (0 == length(i)) + return; + + i = i[0]; + y = 0.5*(y[i]+y[i+1]); + if ((y < y0) or (y > y1)) + return; + variable obj = xfig_new_text (sprintf ("%g", lon)); + xfig_plot_add_object (w, obj, x1, y, -0.6, 0); +} + +private define plot_lines (w, x, y, x0, x1, y0, y1) +{ + variable dx = shift (x, 1) - x; + dx[-1] = 0; + variable dy = shift (x, 1) - x; + dy[-1] = 0; + variable dr = hypot (dx, dy); + variable i = where (dr > 0.05 * (hypot (x1-x0, y1-y0))) + 1; + x[i] = _NaN; + y[i] = _NaN; + xfig_plot_lines (w, x,y); +} + +define plot_data (c, cities, m, dlon, dlat, x0, x1, y0, y1, theta, file) +{ + variable lon0 = m.lon0, lat0 = m.lat0; + %variable lon0 = 0, lat0 = 0; + theta *= PI/180.0; + + x0 = max([-350,x0]); x1 = min([350,x1]); + y0 = max([-350,y0]); y1 = min([350,y1]); + + variable fp = xfig_create_file (file); + variable w = xfig_plot_new (18, 18); + xfig_plot_define_world (w, x0, x1, y0, y1); + %xfig_plot_add_x_axis (w, 0, "X"); + %xfig_plot_add_y_axis (w, 0, "Y"); + %add_latitude_longitude_tics (w, m, x0, x1, y0, y1); + xfig_plot_set_line_color (w, "blue4"); + xfig_plot_set_line_thickness (w, 1); + variable lon, lat, lons, lats, x, y; + variable i; + + lats = [-90:90:0.1]; + + _for (-180, 180, 10) + { + lon = (); + lons = lon + Double_Type[length(lats)]; + i = where ((abs(lons-lon0) <= dlon) and (abs(lats-lat0)<=dlat)); + (x,y) = local_maplib_project (m, lons[i], lats[i]); + (x,y) = maplib_rotate2d (x, y, theta); + %make_ylabel (w, lon, x, y, x0, x1, y0, y1); + plot_lines (w, x, y, x0, x1, y0, y1); + } + + lon = [-180:180.1:0.1]; + _for (-90, 90, 10) + { + lat = (); + lat = lat + Double_Type[length(lon)]; + i = where ((abs(lon-lon0) <= dlon) and (abs(lat-lat0)<=dlat)); + (x,y) = local_maplib_project (m, lon[i], lat[i]); + (x,y)=maplib_rotate2d (x, y, theta); + plot_lines (w, x, y, x0, x1, y0, y1); + } + + xfig_plot_set_line_color (w, "red"); + xfig_plot_set_line_thickness (w, 3); + xfig_plot_inc_line_depth (w, -1); + foreach (c) using ("next") + { + variable cc = (); + variable cc_lon = cc.lon; + variable cc_lat = cc.lat; + + i = where ((abs(cc_lon-lon0) <= dlon) and (abs(cc_lat-lat0)<=dlat)); + (x,y) = local_maplib_project (m, cc_lon[i], cc_lat[i]); + (x,y)=maplib_rotate2d (x, y, theta); + + plot_lines (w, x, y, x0, x1, y0, y1); + %xfig_plot_lines (w, x,y); + } + xfig_plot_set_line_color (w, "black"); + xfig_plot_set_point_size (w, 5); + + if (cities != NULL) + { + variable city_x, city_y; + (city_x, city_y) = local_maplib_project (m, cities.lon, cities.lat); + (city_x, city_y) = maplib_rotate2d (city_x, city_y, theta); + i = where ((city_x > x0) and (city_x < x1) + and (city_y > y0) and (city_y < y1)); + xfig_plot_points (w, city_x[i], city_y[i]); + foreach (i) + { + i = (); + variable obj = xfig_new_text (sprintf ("\\Large\\bf %s", cities.city[i])); + xfig_plot_add_object (w, obj, city_x[i], city_y[i], -0.6, 0); + } + } + xfig_render_object (w, fp); + xfig_close_file (fp); +} + +define fixup_n (m, lon0, lat0) +{ + variable theta0 = lat0 * PI/180.0; + variable phi0 = lon0 * PI/180.0; + variable phi = m.p_lon * PI/180.0; + variable theta = m.p_lat * PI/180.0; + variable R = m.p_len; + variable s0 = vector (cos(theta0)*cos(phi0), + cos(theta0)*sin(phi0), + sin(theta0)); + + variable p = vector (R*cos(theta)*cos(phi), + R*cos(theta)*sin(phi), R*sin(theta)); + variable n = p-s0; + normalize_vector (n); + theta = asin (n.z); + phi = atan2 (n.y, n.x); + m.n_lat = theta * 180.0/PI; + m.n_lon = phi * 180.0/PI; +} + +define cairo_map (c, cities, file) +{ + variable m = local_maplib_new ("plane"); + variable athens_lon = 23.44; + variable athens_lat = 38.00; + variable cairo_lon = 31.15; + variable cairo_lat = 30.03; + variable R = 1.35; + + m.p_lon = cairo_lon; + m.p_lat = cairo_lat; + m.p_len = R; + m.lon0 = athens_lon; + m.lat0 = athens_lat; + + variable i = where ((cities.city == "Cairo") + or (cities.city == "Athens") or (cities.city == "Madrid")); + + struct_filter (cities, i); + + fixup_n (m, athens_lon, athens_lat); + plot_data (c, cities, m, 180, 90, -12, 12, -10,14, -55, file); + exit (0); +} + +define make_plots () +{ + variable c = read_coastline_data ("coastline.dat"); + variable cities = read_cities ("cities.dat"); + variable m; + variable x0, x1, y0, y1; +#iffalse + cairo_map (c, cities, "cairo.ps"); + + m = local_maplib_new ("linear"); m.x0 = 0; m.y0 = 0; + (x0, x1, y0, y1) = get_data_limits (c, m); + x0 -= 10; x1 += 10; y0 -= 10; y1 += 10; + plot_data (c, cities, m, 180, 90, x0, x1, y0, y1, 0, "linear.ps"); +#endif + + + cities = NULL; + + variable lon0 = -70, lat0 = 42; + + m = local_maplib_new ("azeqdist"); m.lon0 = lon0; m.lat0 = lat0; m.beta=0; + (x0, x1, y0, y1) = get_data_limits (c, m); + x0 -= 10; x1 += 10; y0 -= 10; y1 += 10; + %c = NULL; + %plot_data (c, cities, m, 180, 90, x0, x1, y0, y1, 0, "lambert.ps"); + plot_data (c, cities, m, 3600, 1800, x0, x1, y0, y1, 0, "mercator.ps"); + return; + + m = local_maplib_new ("mercator"); m.lon0 = lon0; m.lat0 = lat0; m.beta=90; + (x0, x1, y0, y1) = get_data_limits (c, m); + x0 -= 10; x1 += 10; y0 -= 10; y1 += 10; + %c = NULL; + %plot_data (c, cities, m, 180, 90, x0, x1, y0, y1, 0, "lambert.ps"); + plot_data (c, cities, m, 3600, 1800, x0, x1, y0, y1, 0, "mercator.ps"); + return; + + m = local_maplib_new ("sinusoidal"); m.lon0 = lon0; m.lat0 = lat0; + (x0, x1, y0, y1) = get_data_limits (c, m); + x0 -= 10; x1 += 10; y0 -= 10; y1 += 10; + %c = NULL; + %plot_data (c, cities, m, 180, 90, x0, x1, y0, y1, 0, "lambert.ps"); + plot_data (c, cities, m, 3600, 1800, x0, x1, y0, y1, 0, "bonne.ps"); + return; + + m = local_maplib_new ("bonne"); m.lon0 = lon0; m.lat0 = lat0; + (x0, x1, y0, y1) = get_data_limits (c, m); + x0 -= 10; x1 += 10; y0 -= 10; y1 += 10; + %c = NULL; + %plot_data (c, cities, m, 180, 90, x0, x1, y0, y1, 0, "lambert.ps"); + plot_data (c, cities, m, 3600, 1800, x0, x1, y0, y1, 0, "bonne.ps"); + return; + + m = local_maplib_new ("hammer"); m.lon0 = lon0; m.lat0 = lat0; + (x0, x1, y0, y1) = get_data_limits (c, m); + x0 -= 10; x1 += 10; y0 -= 10; y1 += 10; + %c = NULL; + %plot_data (c, cities, m, 180, 90, x0, x1, y0, y1, 0, "lambert.ps"); + plot_data (c, cities, m, 3600, 1800, x0, x1, y0, y1, 0, "hammer.ps"); + return; + + m = local_maplib_new ("lambert"); m.lon0 = lon0; m.lat0 = lat0; + (x0, x1, y0, y1) = get_data_limits (c, m); + x0 -= 10; x1 += 10; y0 -= 10; y1 += 10; + %c = NULL; + %plot_data (c, cities, m, 180, 90, x0, x1, y0, y1, 0, "lambert.ps"); + plot_data (c, cities, m, 3600, 1800, x0, x1, y0, y1, 0, "lambert.ps"); + return; + + m = local_maplib_new ("stereo"); m.lon0 = 0; m.lat0 = 0; + (x0, x1, y0, y1) = get_data_limits (c, m); + x0 -= 10; x1 += 10; y0 -= 10; y1 += 10; + plot_data (c, cities, m, 180, 90, x0, x1, y0, y1, 0, "stereo.ps"); + + return; + + + m = local_maplib_new ("hammer"); m.lon0 = 0; m.lat0 = 0; + (x0, x1, y0, y1) = get_data_limits (c, m); + x0 -= 10; x1 += 10; y0 -= 10; y1 += 10; + plot_data (c, cities, m, 180, 90, x0, x1, y0, y1, 0, "hammer.ps"); + + return; + m = local_maplib_new ("gnomic"); m.lon0 = 0; m.lat0 = 0; + (x0, x1, y0, y1) = get_data_limits (c, m); + x0 -= 10; x1 += 10; y0 -= 10; y1 += 10; + plot_data (c, cities, m, 80, 80, x0, x1, y0, y1, 0, "gnomic.ps"); + + m = local_maplib_new ("ortho"); m.lon0 = 0; m.lat0 = 0; + (x0, x1, y0, y1) = get_data_limits (c, m); + x0 -= 10; x1 += 10; y0 -= 10; y1 += 10; + plot_data (c, cities, m, 90, 90, x0, x1, y0, y1, 0, "ortho.ps"); + +} +make_plots (); +exit (0); + diff --git a/modules/maplib/src/Makefile.in b/modules/maplib/src/Makefile.in new file mode 100644 index 0000000..083220d --- /dev/null +++ b/modules/maplib/src/Makefile.in @@ -0,0 +1,137 @@ +# -*- sh -*- + +#--------------------------------------------------------------------------- +# List of modules and associated .sl files to install +#--------------------------------------------------------------------------- +MODULES = maplib-module.so +SL_FILES = maplib.sl wcsfuns.sl +HLP_FILES = ../doc/help/maplib.hlp +DOC_FILES = ../COPYRIGHT ../README ../doc/text/maplib.txt +MODULE_VERSION = `./mkversion.sh` + +#--------------------------------------------------------------------------- +# Installation Directories +#--------------------------------------------------------------------------- +prefix = @prefix@ +exec_prefix = @exec_prefix@ +datarootdir = @datarootdir@ +MODULE_INSTALL_DIR = @MODULE_INSTALL_DIR@ +SL_FILES_INSTALL_DIR = @SL_FILES_INSTALL_DIR@ +HLP_FILES_INSTALL_DIR = $(SL_FILES_INSTALL_DIR)/help +DOC_FILES_INSTALL_DIR = $(datarootdir)/doc/slang-maplib + +#--------------------------------------------------------------------------- +# C Compiler to create a shared library +#--------------------------------------------------------------------------- +CC = @CC@ +CFLAGS = @CFLAGS@ @SLANG_DLL_CFLAGS@ +LDFLAGS = @LDFLAGS@ +CC_SHARED = @CC_SHARED@ + +#--------------------------------------------------------------------------- +# Location of the S-Lang library and its include file +#--------------------------------------------------------------------------- +SLANG_INC = @SLANG_INC@ +SLANG_LIB = @SLANG_LIB@ -lslang + +#--------------------------------------------------------------------------- +# Additional Libraries required by the module +#--------------------------------------------------------------------------- +RPATH = @RPATH@ +MODULE_LIBS = +#--------------------------------------------------------------------------- +# Misc Programs required for installation +#--------------------------------------------------------------------------- +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_MODULE = @INSTALL_MODULE@ +MKINSDIR = ../autoconf/mkinsdir.sh +RM = rm -f +LN = ln -s + +#--------------------------------------------------------------------------- +# DESTDIR is designed to facilitate making packages. Normally it is empty +#--------------------------------------------------------------------------- +DESTDIR = +DEST_MODULE_INSTALL_DIR = $(DESTDIR)$(MODULE_INSTALL_DIR) +DEST_SL_FILES_INSTALL_DIR = $(DESTDIR)$(SL_FILES_INSTALL_DIR) +DEST_HLP_FILES_INSTALL_DIR = $(DESTDIR)$(HLP_FILES_INSTALL_DIR) +DEST_DOC_FILES_INSTALL_DIR = $(DESTDIR)$(DOC_FILES_INSTALL_DIR) + +#--------------------------------------------------------------------------- +LIBS = $(SLANG_LIB) $(MODULE_LIBS) $(RPATH) $(DL_LIB) -lm +INCS = $(SLANG_INC) + +all: $(MODULES) + +#--------------------------------------------------------------------------- +# Put Rules to create the modules here +#--------------------------------------------------------------------------- +maplib-module.so: maplib-module.c + $(CC_SHARED) $(INCS) maplib-module.c -o maplib-module.so $(LIBS) +#--------------------------------------------------------------------------- +# Regression tests +#--------------------------------------------------------------------------- +test: + @for X in tests/test_*.sl; \ + do \ + slsh $$X; \ + done +#--------------------------------------------------------------------------- +# Installation Rules +#--------------------------------------------------------------------------- +install_directories: + $(MKINSDIR) $(DEST_MODULE_INSTALL_DIR) + $(MKINSDIR) $(DEST_SL_FILES_INSTALL_DIR) + $(MKINSDIR) $(DEST_HLP_FILES_INSTALL_DIR) + $(MKINSDIR) $(DEST_DOC_FILES_INSTALL_DIR) + +install_modules: + @for X in $(MODULES); \ + do \ + Y=$$X.$(MODULE_VERSION); \ + YDEST=$(DEST_MODULE_INSTALL_DIR)/$$Y; \ + echo $(INSTALL_MODULE) $$X $$YDEST; \ + $(INSTALL_MODULE) $$X $$YDEST; \ + if [ "$$?" != "0" ]; then \ + exit 1; \ + fi; \ + $(RM) $(DEST_MODULE_INSTALL_DIR)/$$X; \ + $(LN) $$Y $(DEST_MODULE_INSTALL_DIR)/$$X; \ + done + +install_slfiles: + @for X in $(SL_FILES); \ + do \ + echo $(INSTALL_DATA) $$X $(DEST_SL_FILES_INSTALL_DIR); \ + $(INSTALL_DATA) $$X $(DEST_SL_FILES_INSTALL_DIR); \ + if [ "$$?" != "0" ]; then \ + exit 1; \ + fi; \ + done +install_hlpfiles: + @for X in $(HLP_FILES); \ + do \ + echo $(INSTALL_DATA) $$X $(DEST_HLP_FILES_INSTALL_DIR); \ + $(INSTALL_DATA) $$X $(DEST_HLP_FILES_INSTALL_DIR); \ + if [ "$$?" != "0" ]; then \ + exit 1; \ + fi; \ + done +install_docfiles: + @for X in $(DOC_FILES); \ + do \ + echo $(INSTALL_DATA) $$X $(DEST_DOC_FILES_INSTALL_DIR); \ + $(INSTALL_DATA) $$X $(DEST_DOC_FILES_INSTALL_DIR); \ + if [ "$$?" != "0" ]; then \ + exit 1; \ + fi; \ + done + +install: all install_directories install_modules install_slfiles \ + install_hlpfiles install_docfiles + +clean: + -/bin/rm -f $(MODULES) *~ \#* +distclean: clean + -/bin/rm -f config.h Makefile diff --git a/modules/maplib/src/config.hin b/modules/maplib/src/config.hin new file mode 100644 index 0000000..4cfe151 --- /dev/null +++ b/modules/maplib/src/config.hin @@ -0,0 +1,15 @@ +/* -*- c -*- */ + +/* Define this if have stdlib.h */ +#undef HAVE_STDLIB_H + +/* Define this if you have unistd.h */ +#undef HAVE_UNISTD_H + +/* Set these to the appropriate values */ +#undef SIZEOF_SHORT +#undef SIZEOF_INT +#undef SIZEOF_LONG +#undef SIZEOF_FLOAT +#undef SIZEOF_DOUBLE + diff --git a/modules/maplib/src/maplib-module.c b/modules/maplib/src/maplib-module.c new file mode 100644 index 0000000..c93631b --- /dev/null +++ b/modules/maplib/src/maplib-module.c @@ -0,0 +1,3409 @@ +/* -*- mode: C; mode: fold; -*- */ +/* + Copyright (c) 2004-2008 Massachusetts Institute of Technology + + This software was developed by the MIT Center for Space Research + under contract SV1-61010 from the Smithsonian Institution. + + Permission to use, copy, modify, distribute, and sell this software + and its documentation for any purpose is hereby granted without fee, + provided that the above copyright notice appear in all copies and + that both that copyright notice and this permission notice appear in + the supporting documentation, and that the name of the Massachusetts + Institute of Technology not be used in advertising or publicity + pertaining to distribution of the software without specific, written + prior permission. The Massachusetts Institute of Technology makes + no representations about the suitability of this software for any + purpose. It is provided "as is" without express or implied warranty. + + THE MASSACHUSETTS INSTITUTE OF TECHNOLOGY DISCLAIMS ALL WARRANTIES + WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE MASSACHUSETTS + INSTITUTE OF TECHNOLOGY BE LIABLE FOR ANY SPECIAL, INDIRECT OR + CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS + OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, + NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION + WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +*/ + +/* Author: John E. Davis (davis@space.mit.edu) */ + +#include +#include +#include +#include +#if SLANG_VERSION < 20000 +# define POP_DOUBLE(x,y,z) SLang_pop_double(x,y,z) +#else +# define POP_DOUBLE(x,y,z) SLang_pop_double(x) +#endif + +#ifdef __cplusplus +extern "C" +{ +#endif +SLANG_MODULE(maplib); +#ifdef __cplusplus +} +#endif + +#include "version.h" + +#include +#ifndef PI +# define PI 3.14159265358979323846264338327950288 +#endif + +#ifdef DEGREES +# undef DEGREES +#endif +#define DEGREES(x) ((180.0/PI)*(x)) +#ifdef RADIANS +# undef RADIANS +#endif +#define RADIANS(x) ((PI/180.0)*(x)) + +/* In this file, theta and phi specify standard spherical coordinates. + * whose values are given in radians. In contrast, lat and lon represent + * latitude and longitude coordinates specified in degrees, unless otherwise + * specified. + * They are related as follows: + * + * theta = PI/180*(90-lat); theta_hat = -lat_hat + * phi = PI/180*lon; phi_hat = lon_hat + */ +#define THETA_TO_LAT(theta) (90.0 - DEGREES(theta)) +#define LAT_TO_THETA(lat) RADIANS(90.0 - (lat)) +#define PHI_TO_LON(phi) DEGREES(phi) +#define LON_TO_PHI(lon) RADIANS(lon) + +#define VECTOR_DIFF(c,a,b) \ + c[0]=a[0]-b[0]; \ + c[1]=a[1]-b[1]; \ + c[2]=a[2]-b[2] +#define VECTOR_SUM(c,a,b) \ + c[0]=a[0]+b[0]; \ + c[1]=a[1]+b[1]; \ + c[2]=a[2]+b[2] +#define VECTOR_COMBINE_SUM(c,x,s,a,t,b) \ + c[0]=x[0]+(s)*a[0]+(t)*b[0]; \ + c[1]=x[1]+(s)*a[1]+(t)*b[1]; \ + c[2]=x[2]+(s)*a[2]+(t)*b[2]; +#define VECTOR_A_PLUS_BT(c,a,b,t) \ + c[0]=a[0]+(t)*b[0]; \ + c[1]=a[1]+(t)*b[1]; \ + c[2]=a[2]+(t)*b[2] +#define VECTOR_MUL(b,a,t) \ + b[0] = (t)*a[0]; \ + b[1] = (t)*a[1]; \ + b[2] = (t)*a[2]; +#define VECTOR_ASSIGN(b,a) \ + b[0] = a[0]; \ + b[1] = a[1]; \ + b[2] = a[2] + +#define DOTPROD(a,b) (a[0]*b[0]+a[1]*b[1]+a[2]*b[2]) + +static double Maplib_NaN; + +/*{{{ Spherical Coordinate Routines */ + +static double hypot3d (double x, double y, double z) +{ + double tmp; + + x = fabs(x); + y = fabs(y); + z = fabs(z); + + /* Want x <= y <= z */ + if (y < x) + { + tmp = x; + x = y; + y = tmp; + } + + if (z < y) + { + tmp = z; + if (z < x) + { + z = x; + x = tmp; + } + else + { + z = y; + y = tmp; + } + } + + if (z == 0.0) + return 0.0; + + x /= z; + y /= z; + return z * sqrt (1.0 + x*x + y*y); +} + + +static void vector_to_spherical (double x, double y, double z, + double *rp, double *thetap, double *phip) +{ + double r = hypot (x, y); + + if (r == 0.0) + { + if (z < 0) + { + *thetap = PI; + *rp = -z; + } + else + { + *thetap = 0.0; + *rp = z; + } + *phip = 0.0; + return; + } + + *thetap = atan2 (r, z); + *phip = atan2 (y, x); + + *rp = hypot (r, z); +} + +static void spherical_to_vector (double r, double theta, double phi, double v[3]) +{ + double ct = r*cos(theta); + double st = r*sin(theta); + double cp = cos(phi); + double sp = sin(phi); + + v[0] = st*cp; + v[1] = st*sp; + v[2] = ct; +} + +static void get_spherical_basis (double theta, double phi, double *rhat, double *theta_hat, double *phi_hat) +{ + double ct = cos(theta); + double st = sin(theta); + double cp = cos(phi); + double sp = sin(phi); + + if (rhat != NULL) + { + rhat[0] = st*cp; rhat[1] = st*sp; rhat[2] = ct; + } + if (theta_hat != NULL) + { + theta_hat[0] = ct*cp; theta_hat[1] = ct*sp; theta_hat[2] = -st; + } + if (phi_hat != NULL) + { + phi_hat[0] = -sp; phi_hat[1] = cp; phi_hat[2] = 0.0; + } +} + +/* Returns -r <= x <= r */ +static double normalize_to_range (double x, double r) +{ + double r2; + + if ((x >= -r) && (x <= r)) + return x; + + r2 = 2.0 * r; + x = fmod (x, r2); + if (x < -r) + x += r2; + else if (x > r) + x -= r2; + return x; +} + +static void normalize_lon_lat_degrees (double *lonp, double *latp) +{ + double lon, lat; + + lon = normalize_to_range (*lonp, 180.0); + lat = normalize_to_range (*latp, 180.0); + + if (lat > 90.0) + { + lat = 180.0 - lat; + lon = normalize_to_range (lon-180.0, 180.0); + } + else if (lat < -90) + { + lat = 180.0 + lat; + lon = normalize_to_range (lon-180.0, 180.0); + } + + *lonp = lon; + *latp = lat; +} + +static int normalize_vector (double v[3]) +{ + double len = hypot3d (v[0],v[1],v[2]); + if (len == 0.0) + return -1; + len = 1.0/len; + VECTOR_MUL(v,v,len); + return 0; +} + +/* Given two sets of othonormal systems, (x1,x2,x3) and (y1,y2,y3), find the + * rotation angle and direction that rotates (x1,x2,x3) into (y1,y2,y3). + */ +static int find_rotation (double x_1[3], double x_2[3], double x_3[3], + double y_1[3], double y_2[3], double y_3[3], + double axis[3], double *cos_thetap, double *sin_thetap) +{ + double cos_theta, sin_theta; + double omega[3]; + + cos_theta = 0.5 * (DOTPROD(y_1,x_1) + DOTPROD(y_2,x_2) + DOTPROD(y_3,x_3) - 1.0); + if (cos_theta > 1.0) cos_theta = 1.0; + else if (cos_theta < -1.0) cos_theta = -1.0; + + sin_theta = sqrt (1.0 - cos_theta*cos_theta); + if (sin_theta == 0.0) + { + if (cos_theta > 0.0) + { + /* Identity transform */ + omega[0] = omega[1] = omega[2] = 0.0; + } + else + { + omega[0] = sqrt (0.5*(1.0 + DOTPROD(y_1,x_1))); + omega[1] = sqrt (0.5*(1.0 + DOTPROD(y_2,x_2))); + omega[2] = sqrt (0.5*(1.0 + DOTPROD(y_3,x_3))); + /* Now determine the signs. */ + if ((omega[0] >= omega[1]) && (omega[0] >= omega[2])) + { + if (DOTPROD(y_1,x_2) < 0) omega[1] = -omega[1]; + if (DOTPROD(y_1,x_3) < 0) omega[2] = -omega[2]; + } + else if ((omega[1] >= omega[0]) && (omega[1] >= omega[2])) + { + if (DOTPROD(y_2,x_1) < 0) omega[0] = -omega[0]; + if (DOTPROD(y_2,x_3) < 0) omega[2] = -omega[2]; + } + else + { + if (DOTPROD(y_3,x_1) < 0) omega[0] = -omega[0]; + if (DOTPROD(y_3,x_2) < 0) omega[1] = -omega[1]; + } + (void) normalize_vector (omega); + } + } + else + { + double factor = 0.5/sin_theta; + omega[0] = factor * (DOTPROD(y_2,x_3) - DOTPROD(y_3,x_2)); + omega[1] = factor * (DOTPROD(y_3,x_1) - DOTPROD(y_1,x_3)); + omega[2] = factor * (DOTPROD(y_1,x_2) - DOTPROD(y_2,x_1)); + (void) normalize_vector (omega); + } + axis[0] = omega[0]*x_1[0] + omega[1]*x_2[0] + omega[2]*x_3[0]; + axis[1] = omega[0]*x_1[1] + omega[1]*x_2[1] + omega[2]*x_3[1]; + axis[2] = omega[0]*x_1[2] + omega[1]*x_2[2] + omega[2]*x_3[2]; + + *cos_thetap = cos_theta; + *sin_thetap = sin_theta; + return 0; +} + +static void create_lonlat_basis (double lon, double lat, + double n_hat[3], double lon_hat[3], double lat_hat[3]) +{ + double cos_lat = cos (lat); + double sin_lat = sin (lat); + double cos_lon = cos (lon); + double sin_lon = sin (lon); + + n_hat[0] = cos_lat*cos_lon; n_hat[1] = cos_lat*sin_lon; n_hat[2] = sin_lat; + lon_hat[0] = -sin_lon; lon_hat[1] = cos_lon; lon_hat[2] = 0.0; + lat_hat[0] = -sin_lat*cos_lon; lat_hat[1] = -sin_lat*sin_lon; lat_hat[2] = cos_lat; +} + +/* Rotate a vector v about unit vector n by theta */ +static void rotate_vector (double v[3], double n[3], double cos_theta, double sin_theta) +{ + double v_dot_n; + double v0, v1, v2, n0, n1, n2; + + v0 = v[0]; v1 = v[1]; v2 = v[2]; + n0 = n[0]; n1 = n[1]; n2 = n[2]; + + v_dot_n = v0*n0 + v1*n1 + v2*n2; + v_dot_n *= (1.0 - cos_theta); + v[0] = v0*cos_theta + v_dot_n*n0 + sin_theta*(n1*v2 - n2*v1); + v[1] = v1*cos_theta + v_dot_n*n1 + sin_theta*(n2*v0 - n0*v2); + v[2] = v2*cos_theta + v_dot_n*n2 + sin_theta*(n0*v1 - n1*v0); +} + +typedef struct +{ + double theta; + double cos_theta, sin_theta; + double omega[3]; +} +Sphere_Rotate_Type; +/* Initialize a transform that maps (lon0,lat0) --> (lon1,lat1) and applies + * an additional rotation about the final point by beta. + */ +static int init_sphere_xform (Sphere_Rotate_Type *s, + double lon0, double lat0, + double lon1, double lat1, + double beta) +{ + double lon0_hat[3], lat0_hat[3], n0_hat[3]; + double lon1_hat[3], lat1_hat[3], n1_hat[3]; + + create_lonlat_basis (lon0, lat0, n0_hat, lon0_hat, lat0_hat); + create_lonlat_basis (lon1, lat1, n1_hat, lon1_hat, lat1_hat); + + if (beta != 0.0) + { + /* Rotate lon and lat vectors about the normal by beta */ + double cos_beta = cos (beta); + double sin_beta = sin (beta); + rotate_vector (lon1_hat, n1_hat, cos_beta, sin_beta); + rotate_vector (lat1_hat, n1_hat, cos_beta, sin_beta); + } + find_rotation (n0_hat, lon0_hat, lat0_hat, n1_hat, lon1_hat, lat1_hat, + s->omega, &s->cos_theta, &s->sin_theta); + s->theta = atan2 (s->sin_theta, s->cos_theta); + + return 0; +} + +static void rotate_sphere (Sphere_Rotate_Type *s, int dir, + double lon, double lat, + double *lonp, double *latp) +{ + double p[3], pz; + double cos_lat = cos (lat); + + p[0] = cos_lat * cos(lon); + p[1] = cos_lat * sin(lon); + p[2] = sin(lat); + + /* FIXME: : If rotating about the pole, and if lon,lat corresponds to the + * pole, then the returned lon should be lon+rotation angle + */ + if (((lat == PI/2.0) || (lat == -PI/2.0)) + && ((s->omega[2] == 1.0) || (s->omega[2] == -1.0))) + { + *lonp = normalize_to_range (lon + s->omega[2] * s->theta, PI); + *latp = lat; + return; + } + + rotate_vector (p, s->omega, s->cos_theta, dir*s->sin_theta); + lon = atan2 (p[1], p[0]); + pz = p[2]; + if (pz > 1.0) pz = 1.0; else if (pz < -1.0) pz = -1.0; + lat = asin (pz); + + *lonp = lon; + *latp = lat; +} + +/*}}}*/ + +/*{{{ Generic Tangent Plane projection routines */ + +/* These routines assume that the plane is tangent to the unit sphere at some point + * s0. The normal to the plane is also s0. + * + * The location of the observer from where rays eminate is given by p. + * + * The vector x represents a point on the plane. + * + * The basis vectors at the point s0 are aligned with the local + * lon,lat vectors. + */ + +/* If solution_type is 1, then we are seeking the primary soln. */ +static int project_to_plane (double s0[3], double p, double phat[3], + double s[3], + /* int solution_type, */ + double x[3]) +{ + double t, t1; + double phat_dot_s0, s_dot_s0; + double a, b; + double pt1[3]; + int solution_type = 1; + + if (p > 1.0) + { /* outside sphere */ + if (DOTPROD(phat,s) < 1.0/p) + { + if (solution_type == 1) + { + x[0] = x[1] = x[2] = Maplib_NaN; + return -1; + } + } + else if (solution_type != 1) + { + x[0] = x[1] = x[2] = Maplib_NaN; + return -1; + } + } + + /* See pg 9 of maplib notebook */ + phat_dot_s0 = DOTPROD(phat,s0); + s_dot_s0 = DOTPROD(s,s0); + if (p >= 1.0) + { + a = phat_dot_s0 - 1.0/p; + b = phat_dot_s0 - s_dot_s0/p; + t = a/b; + t1 = (1.0 - s_dot_s0)/b; /* this is p(1-t) */ + } + else + { + a = 1.0 - p*phat_dot_s0; + b = s_dot_s0 - p*phat_dot_s0; + t=a/b; + t1 = p*(1-t); + } + VECTOR_MUL(pt1, phat, t1); + VECTOR_A_PLUS_BT(x,pt1,s,t); + return 0; +} + +static int project_to_plane_coords (double s[3], double s0[3], double p, double phat[3], + double txhat[3], double tyhat[3], + double *tx, double *ty) +{ + int ret; + double x[3]; + + ret = project_to_plane (s0, p, phat, s, x); + /* We have: + * x - s0 = tx*tx_hat + ty*ty_hat + */ + + VECTOR_DIFF(x,x,s0); + *tx = DOTPROD(x,txhat); + *ty = DOTPROD(x,tyhat); + return ret; +} + + + +static int project_from_plane (double s0[3], double p, double phat[3], double x[3], double s[3]) +{ + double t, t1; + double a, b, c; + double phat_dot_x, p2, x2, p_dot_x; + double alpha, beta; + int solution_type = 1; + + phat_dot_x = DOTPROD(phat,x); + p_dot_x = p*phat_dot_x; + x2 = DOTPROD(x,x); + p2 = p*p; + if (p2 > 1.0) + { + int sgn = 1; + + /* Pages 18,19 of maplib notebook */ + a = 1.0 - 1.0/p2; + b = (phat_dot_x/p - 1.0)/a; + c = (1 + x2/p2 - 2.0*phat_dot_x/p)/a; + alpha = -b; + beta = sqrt (b*b-c); + if (alpha >= 0) + { + if (solution_type != 1) + sgn = -1; + } + else if (solution_type == 1) + sgn = -1; + t = alpha + sgn * beta; + + /* For large p, 1-t goes like 1/p. */ + alpha = (-1.0/p + phat_dot_x)/a; + beta = sqrt (-x2*a + 1.0 + phat_dot_x*(phat_dot_x-2.0/p)); + beta = beta/a; + t1 = alpha - sgn*beta; /* (1-t)*p */ + } + else + { + /* Pg 17 of maplib notebook */ + int sgn = 1; + b = 2.0 * (p_dot_x - p2); + c = (x2 + p2 - 2.0*p_dot_x); + if (p2 == 1.0) + t = -c/b; + else + { + a = p2 - 1.0; + b = b/(2.0*a); + c = c / a; + alpha = -b; + beta = sqrt (b*b - c); + if (DOTPROD(s0,x) >= p*DOTPROD(s0,phat)) + { + if (solution_type != 1) + sgn = -1; + } + else if (solution_type == 1) + sgn = -1; + t = alpha + sgn * beta; + } + t1 = (1.0 - t)*p; + } + t1 = -t1; + VECTOR_A_PLUS_BT(s,x,phat,t1); + t = 1.0/t; + VECTOR_MUL(s,s,t); + return 0; +} + +static int project_from_plane_coords (double tx, double ty, + double s0[3], double p, double phat[3], + double txhat[3], double tyhat[3], + double s[3]) +{ + int ret; + double x[3]; + + VECTOR_COMBINE_SUM(x,s0,tx,txhat,ty,tyhat); + ret = project_from_plane (s0, p, phat, x, s); + + return ret; +} + +static int compute_plane_vectors (double theta_0, double phi_0, /* s0 */ + double xhat[3], double yhat[3], double zhat[3]) +{ + double theta0_hat[3], phi0_hat[3]; + + get_spherical_basis (theta_0, phi_0, zhat, theta0_hat, phi0_hat); + + VECTOR_ASSIGN (xhat, phi0_hat); + VECTOR_ASSIGN (yhat, theta0_hat); + VECTOR_MUL(yhat,yhat,-1.0); /* lat_hat = -theta_hat */ + + return 0; +} + + +/*}}}*/ + +/*{{{ Tangent Plane Projection Routines */ + +/* This routine returns a vector from the center of the sphere to the point + * (tx,ty) on the tangent plane. This vector does not depend upon the + * specific projection. + */ +static void tangent_plane_to_vector (double ex[3], double ey[3], double ez[3], + double tx, double ty, + double v[3]) +{ + VECTOR_COMBINE_SUM(v,ez,tx,ex,ty,ey); +} + +/* In this routine, v is a vector from the center of the sphere to the + * tangent plane at v0. The tangent plane coordinates are returned. + * + * v*t = v0 + tx*ex+ty*ey + * t = 1.0/(v.v0) + * + */ +static int vector_to_tangent_plane (double v[3], + double ex[3], double ey[3], double ez[3], + double *tx, double *ty) +{ + double v0, v1, v2; + double t = DOTPROD(v,ez); + int ret; + + /* If t == 0, then we will get infinity. Let's hope IEEE Inf is available */ + if (t == 0.0) + ret = -1; + else + ret = 0; + + t = 1.0/t; + + v0 = v[0]*t; + v1 = v[1]*t; + v2 = v[2]*t; + + *tx = v0*ex[0] + v1*ex[1] + v2*ex[2]; + *ty = v0*ey[0] + v1*ey[1] + v2*ey[2]; + + return ret; +} + + +/* In this routine, p is a unit vector on the sphere to be projected from + * infinity to the tangent plane located at ez. + * The tangent plane coordinates are returned. + * + * v = p + (1-p.ez)ez; + */ +static int ortho_project_vector (double p[3], + double ex[3], double ey[3], double ez[3], + double *tx, double *ty) +{ + double v[3]; + double c; + c = (1.0 - DOTPROD(p,ez)); + VECTOR_A_PLUS_BT(v,p,ez,c); + + return vector_to_tangent_plane (v, ex, ey, ez, tx, ty); +} + +/* This routine is the inverse of ortho_project_vector */ +static int ortho_deproject_vector (double ex[3], double ey[3], double ez[3], + double tx, double ty, + double p[3]) +{ + double x[3]; + double c; + int ret = 0; + + tangent_plane_to_vector (ex, ey, ez, tx, ty, x); + c = 2.0 - DOTPROD(x,x); + if (c < 0.0) + ret = -1; + + c = sqrt (c) - 1.0; + VECTOR_A_PLUS_BT(p, x, ez, c); + return ret; +} + + +/*}}}*/ + +/*{{{ push/pop functions */ + +static int pop_2_floating_arrays_1 (SLang_Array_Type **atp, SLang_Array_Type **btp, + int *is_scalarp) +{ + int btype, atype, ctype; + SLang_Array_Type *at, *bt; + int is_scalar; + + if (-1 == (btype = SLang_peek_at_stack1 ())) + return -1; + + is_scalar = (SLANG_ARRAY_TYPE != SLang_peek_at_stack ()); + + if (-1 == SLroll_stack (2)) + return -1; + + atype = SLang_peek_at_stack1 (); + is_scalar = is_scalar && (SLANG_ARRAY_TYPE != SLang_peek_at_stack ()); + + if ((atype == SLANG_FLOAT_TYPE) && (btype == SLANG_FLOAT_TYPE)) + ctype = SLANG_FLOAT_TYPE; + else + ctype = SLANG_DOUBLE_TYPE; + + if (-1 == SLang_pop_array_of_type (&at, ctype)) + return -1; + if (-1 == SLang_pop_array_of_type (&bt, ctype)) + { + SLang_free_array (at); + return -1; + } + *atp = at; + *btp = bt; + *is_scalarp = is_scalar; + return 0; +} + +static int pop_2_floating_arrays (SLang_Array_Type **atp, SLang_Array_Type **btp, + int *is_scalarp) +{ + SLang_Array_Type *at, *bt; + int is_scalar; + + if (-1 == pop_2_floating_arrays_1 (&at, &bt, &is_scalar)) + return -1; + + if (at->num_elements != bt->num_elements) + { + SLang_verror (SL_TYPE_MISMATCH, "Expecting two arrays of the same size"); + SLang_free_array (at); + SLang_free_array (bt); + return -1; + } + + *atp = at; + *btp = bt; + *is_scalarp = is_scalar; + return 0; +} + +static SLang_Array_Type *create_or_reuse_array (SLang_Array_Type *at) +{ + if ((at->num_refs == 1) && (0 == (at->flags & SLARR_DATA_VALUE_IS_READ_ONLY))) + { + at->num_refs++; + return at; + } + + return SLang_create_array (at->data_type, 0, NULL, at->dims, at->num_dims); +} + +static int create_or_reuse_2_arrays (SLang_Array_Type *at0, SLang_Array_Type *at1, + SLang_Array_Type **bt0p, SLang_Array_Type **bt1p) +{ + SLang_Array_Type *bt0, *bt1; + + if (NULL == (bt0 = create_or_reuse_array (at0))) + return -1; + + if (NULL == (bt1 = create_or_reuse_array (at1))) + { + SLang_free_array (bt0); + return -1; + } + + *bt0p = bt0; + *bt1p = bt1; + return 0; +} + +static int pop_reusable_arrays (SLang_Array_Type **xp, SLang_Array_Type **yp, + SLang_Array_Type **x1p, SLang_Array_Type **y1p, + int *is_scalarp) +{ + SLang_Array_Type *x, *y; + + if (-1 == pop_2_floating_arrays (&x, &y, is_scalarp)) + return -1; + + if (-1 == create_or_reuse_2_arrays (x, y, x1p, y1p)) + { + SLang_free_array (y); + SLang_free_array (x); + return -1; + } + + *xp = x; + *yp = y; + return 0; +} + + + +static int push_array_maybe_scalar (SLang_Array_Type *a, int is_scalar) +{ + if (is_scalar) + return SLang_push_value (a->data_type, a->data); + + return SLang_push_array (a, 0); +} + +static void get_tp_basis (double theta, double phi, + double tx_hat[3], double ty_hat[3], double tz_hat[3]) +{ + get_spherical_basis (theta, phi, tz_hat, ty_hat, tx_hat); + ty_hat[0] = -ty_hat[0]; + ty_hat[1] = -ty_hat[1]; + ty_hat[2] = -ty_hat[2]; +} + +static int pop_mxm_matrix (SLang_Array_Type **ap, unsigned int m) +{ + SLang_Array_Type *a; + + if (-1 == SLang_pop_array_of_type (&a, SLANG_DOUBLE_TYPE)) + return -1; + + if ((a->num_dims != 2) + || (a->dims[0] != (int)m) + || (a->dims[1] != (int)m)) + { + SLang_verror (SL_TYPE_MISMATCH, "Expecting a %u x %u array", m, m); + SLang_free_array (a); + return -1; + } + *ap = a; + return 0; +} + +/*}}}*/ + +/* Projection Methods */ + +#define REQUIRED_FIELDS \ + char *name; \ + double lon0, lat0 /* map center */ + +/*{{{ Linear Projection */ + +/* The linear projection transforms (x,y) via + * (x',y') = (x1,y1) + A#(x-x0,y-y0) + */ +typedef struct +{ + REQUIRED_FIELDS; + double x_0, y_0; + double x_1, y_1; + SLang_Array_Type *at; + double a[4]; + double a_inv[4]; +} +Linear_Projection_Type; + +static SLang_CStruct_Field_Type Linear_Projection_Struct[] = +{ + MAKE_CSTRUCT_FIELD(Linear_Projection_Type, name, "name", SLANG_STRING_TYPE, 0), + MAKE_CSTRUCT_FIELD(Linear_Projection_Type, x_0, "x0", SLANG_DOUBLE_TYPE, 0), + MAKE_CSTRUCT_FIELD(Linear_Projection_Type, y_0, "y0", SLANG_DOUBLE_TYPE, 0), + MAKE_CSTRUCT_FIELD(Linear_Projection_Type, x_1, "x1", SLANG_DOUBLE_TYPE, 0), + MAKE_CSTRUCT_FIELD(Linear_Projection_Type, y_1, "y1", SLANG_DOUBLE_TYPE, 0), + MAKE_CSTRUCT_FIELD(Linear_Projection_Type, at, "A", SLANG_ARRAY_TYPE, 0), + SLANG_END_CSTRUCT_TABLE +}; + +static int linear_new (char *name) +{ + Linear_Projection_Type g; + SLang_Array_Type *at; + int dims[2]; + int ret; + + dims[0] = 2; + dims[1] = 2; + + if (NULL == (at = SLang_create_array (SLANG_DOUBLE_TYPE, 0, NULL, dims, 2))) + return -1; + ((double *)at->data)[0] = 1.0; + ((double *)at->data)[1] = 0.0; + ((double *)at->data)[2] = 0.0; + ((double *)at->data)[3] = 1.0; + g.at = at; + + g.name = name; + g.x_0 = g.y_0 = 0.0; + g.x_1 = g.y_1 = 0.0; + + ret = SLang_push_cstruct (&g, Linear_Projection_Struct); + SLang_free_array (at); + return ret; +} + +static void linear_free (void *g) +{ + if (g == NULL) + return; + + SLang_free_cstruct (g, Linear_Projection_Struct); + SLfree ((char *)g); +} + +static int make_2x2_inverse (double a[4], double ainv[4]) +{ + double det = a[0]*a[3] - a[1]*a[2]; + + if (det == 0.0) + { + SLang_verror (SL_INVALID_PARM, "Transformation matrix must have an inverse"); + return -1; + } + ainv[0] = a[3]/det; + ainv[1] = -a[1]/det; + ainv[2] = -a[2]/det; + ainv[3] = a[0]/det; + + return 0; +} + +static void *linear_pop (char *name) +{ + Linear_Projection_Type *g; + SLang_Array_Type *at; + double *a; + + (void) name; + + if (NULL == (g = (Linear_Projection_Type *)SLmalloc (sizeof (Linear_Projection_Type)))) + return NULL; + + if (-1 == SLang_pop_cstruct (g, Linear_Projection_Struct)) + { + SLfree ((char *)g); + return NULL; + } + + at = g->at; + a = g->a; + if (at == NULL) + { + a[0] = 1.0; + a[1] = 0.0; + a[2] = 0.0; + a[3] = 1.0; + } + else + { + if (-1 == SLang_push_array (at, 0)) + { + linear_free (g); + return NULL; + } + + if (-1 == pop_mxm_matrix (&at, 2)) + { + linear_free (g); + return NULL; + } + + a[0] = ((double *)at->data)[0]; + a[1] = ((double *)at->data)[1]; + a[2] = ((double *)at->data)[2]; + a[3] = ((double *)at->data)[3]; + SLang_free_array (at); + } + + if (-1 == make_2x2_inverse (a, g->a_inv)) + { + linear_free (g); + return NULL; + } + + return g; +} + +static int linear_project_f_internal (double *a, + double x_0, double y_0, + double x_1, double y_1, + float *x, float *y, + float *newx, float *newy, + unsigned int num) +{ + double a_00 = a[0], a_01 = a[1]; + double a_10 = a[2], a_11 = a[3]; + unsigned int i; + + for (i = 0; i < num; i++) + { + double xx = x[i] - x_0; + double yy = y[i] - y_0; + newx[i] = x_1 + (a_00*xx + a_01*yy); + newy[i] = y_1 + (a_10*xx + a_11*yy); + } + return 0; +} + +static int linear_project_f (void *vg, + float *x, float *y, + float *newx, float *newy, + unsigned int num) +{ + Linear_Projection_Type *g = (Linear_Projection_Type *)vg; + return linear_project_f_internal (g->a, g->x_0, g->y_0, g->x_1, g->y_1, x, y, newx, newy, num); +} + +static int linear_deproject_f (void *vg, + float *x, float *y, + float *newx, float *newy, + unsigned int num) +{ + Linear_Projection_Type *g = (Linear_Projection_Type *)vg; + return linear_project_f_internal (g->a_inv, g->x_1, g->y_1, g->x_0, g->y_0, x, y, newx, newy, num); +} + +static int linear_project_d_internal (double *a, + double x_0, double y_0, + double x_1, double y_1, + double *x, double *y, + double *newx, double *newy, + unsigned int num) +{ + double a_00 = a[0], a_01 = a[1]; + double a_10 = a[2], a_11 = a[3]; + unsigned int i; + + for (i = 0; i < num; i++) + { + double xx = x[i] - x_0; + double yy = y[i] - y_0; + newx[i] = x_1 + (a_00*xx + a_01*yy); + newy[i] = y_1 + (a_10*xx + a_11*yy); + } + return 0; +} + +static int linear_project_d (void *vg, + double *x, double *y, + double *newx, double *newy, + unsigned int num) +{ + Linear_Projection_Type *g = (Linear_Projection_Type *)vg; + return linear_project_d_internal (g->a, g->x_0, g->y_0, g->x_1, g->y_1, x, y, newx, newy, num); +} + +static int linear_deproject_d (void *vg, + double *x, double *y, + double *newx, double *newy, + unsigned int num) +{ + Linear_Projection_Type *g = (Linear_Projection_Type *)vg; + return linear_project_d_internal (g->a_inv, g->x_1, g->y_1, g->x_0, g->y_0, x, y, newx, newy, num); +} + + + +/*}}}*/ + +/*{{{ Sphere Projection (sphere to sphere) */ + +/* This mapping maps a sphere onto itself: lon,lat --> lon,lat. It takes the + * position of the pole, and a final rotation angle (beta) about that. + */ +typedef struct +{ + REQUIRED_FIELDS; + double lon1, lat1; + double beta; + Sphere_Rotate_Type sphere_xform; +} +Sphere_Projection_Type; + +static SLang_CStruct_Field_Type Sphere_Projection_Struct[] = +{ + MAKE_CSTRUCT_FIELD(Sphere_Projection_Type, name, "name", SLANG_STRING_TYPE, 0), + MAKE_CSTRUCT_FIELD(Sphere_Projection_Type, lon0, "lon0", SLANG_DOUBLE_TYPE, 0), + MAKE_CSTRUCT_FIELD(Sphere_Projection_Type, lat0, "lat0", SLANG_DOUBLE_TYPE, 0), + MAKE_CSTRUCT_FIELD(Sphere_Projection_Type, lon1, "lon1", SLANG_DOUBLE_TYPE, 0), + MAKE_CSTRUCT_FIELD(Sphere_Projection_Type, lat1, "lat1", SLANG_DOUBLE_TYPE, 0), + MAKE_CSTRUCT_FIELD(Sphere_Projection_Type, beta, "beta", SLANG_DOUBLE_TYPE, 0), + SLANG_END_CSTRUCT_TABLE +}; + +static int sphere_new (char *name) +{ + Sphere_Projection_Type g; + + g.name = name; + g.lon0 = 0.0; + g.lat0 = 90.0; + g.lon1 = 0.0; + g.lat1 = 90.0; + g.beta = 0.0; + + return SLang_push_cstruct (&g, Sphere_Projection_Struct); +} + +static void sphere_free (void *g) +{ + if (g == NULL) + return; + + SLang_free_cstruct (g, Sphere_Projection_Struct); + SLfree ((char *)g); +} + +static void *sphere_pop (char *name) +{ + Sphere_Projection_Type *g; + + (void) name; + + if (NULL == (g = (Sphere_Projection_Type *)SLmalloc (sizeof (Sphere_Projection_Type)))) + return NULL; + + if (-1 == SLang_pop_cstruct (g, Sphere_Projection_Struct)) + { + SLfree ((char *)g); + return NULL; + } + if (-1 == init_sphere_xform (&g->sphere_xform, RADIANS(g->lon0), RADIANS(g->lat0), + RADIANS(g->lon1), RADIANS(g->lat1), + RADIANS(g->beta))) + { + SLfree ((char *)g); + return NULL; + } + return g; +} + +static int sphere_project_f (void *vg, + float *x, float *y, + float *newx, float *newy, + unsigned int num) +{ + Sphere_Projection_Type *g = (Sphere_Projection_Type *)vg; + Sphere_Rotate_Type *s; + unsigned int i; + + s = &g->sphere_xform; + for (i = 0; i < num; i++) + { + double lon1, lat1; + rotate_sphere (s, 1, RADIANS(x[i]), RADIANS(y[i]), &lon1, &lat1); + newx[i] = (float)DEGREES(lon1); + newy[i] = (float)DEGREES(lat1); + } + return 0; +} + +static int sphere_deproject_f (void *vg, + float *x, float *y, + float *newx, float *newy, + unsigned int num) +{ + Sphere_Projection_Type *g = (Sphere_Projection_Type *)vg; + Sphere_Rotate_Type *s; + unsigned int i; + + s = &g->sphere_xform; + for (i = 0; i < num; i++) + { + double lon1, lat1; + rotate_sphere (s, -1, RADIANS(x[i]), RADIANS(y[i]), &lon1, &lat1); + newx[i] = (float)DEGREES(lon1); + newy[i] = (float)DEGREES(lat1); + } + return 0; +} + +static int sphere_project_d (void *vg, + double *x, double *y, + double *newx, double *newy, + unsigned int num) +{ + Sphere_Projection_Type *g = (Sphere_Projection_Type *)vg; + Sphere_Rotate_Type *s; + unsigned int i; + + s = &g->sphere_xform; + for (i = 0; i < num; i++) + { + double lon1, lat1; + rotate_sphere (s, 1, RADIANS(x[i]), RADIANS(y[i]), &lon1, &lat1); + newx[i] = DEGREES(lon1); + newy[i] = DEGREES(lat1); + } + return 0; +} + +static int sphere_deproject_d (void *vg, + double *x, double *y, + double *newx, double *newy, + unsigned int num) +{ + Sphere_Projection_Type *g = (Sphere_Projection_Type *)vg; + Sphere_Rotate_Type *s; + unsigned int i; + + s = &g->sphere_xform; + for (i = 0; i < num; i++) + { + double lon1, lat1; + rotate_sphere (s, -1, RADIANS(x[i]), RADIANS(y[i]), &lon1, &lat1); + newx[i] = DEGREES(lon1); + newy[i] = DEGREES(lat1); + } + return 0; +} + +/*}}}*/ + +/*{{{ Gnomic Projection */ + +typedef struct +{ + REQUIRED_FIELDS; + double tx0, ty0, txscale, tyscale; + double tx_hat[3], ty_hat[3], tz_hat[3]; +} +Gnomic_Projection_Type; + +static SLang_CStruct_Field_Type Gnomic_Projection_Struct[] = +{ + MAKE_CSTRUCT_FIELD(Gnomic_Projection_Type, name, "name", SLANG_STRING_TYPE, 0), + MAKE_CSTRUCT_FIELD(Gnomic_Projection_Type, lon0, "lon0", SLANG_DOUBLE_TYPE, 0), + MAKE_CSTRUCT_FIELD(Gnomic_Projection_Type, lat0, "lat0", SLANG_DOUBLE_TYPE, 0), + MAKE_CSTRUCT_FIELD(Gnomic_Projection_Type, tx0, "x0", SLANG_DOUBLE_TYPE, 0), + MAKE_CSTRUCT_FIELD(Gnomic_Projection_Type, ty0, "y0", SLANG_DOUBLE_TYPE, 0), + MAKE_CSTRUCT_FIELD(Gnomic_Projection_Type, txscale, "xscale", SLANG_DOUBLE_TYPE, 0), + MAKE_CSTRUCT_FIELD(Gnomic_Projection_Type, tyscale, "yscale", SLANG_DOUBLE_TYPE, 0), + SLANG_END_CSTRUCT_TABLE +}; + +static int gnomic_new (char *name) +{ + Gnomic_Projection_Type g; + + g.name = name; + g.lon0 = 0.0; + g.lat0 = 90.0; + g.tx0 = g.ty0 = 0; + g.txscale = 1.0; + g.tyscale = 1.0; + + return SLang_push_cstruct (&g, Gnomic_Projection_Struct); +} + +static void *gnomic_pop (char *name) +{ + Gnomic_Projection_Type *g; + double phi0, theta0; + + if (NULL == (g = (Gnomic_Projection_Type *)SLmalloc (sizeof (Gnomic_Projection_Type)))) + return NULL; + + if (-1 == SLang_pop_cstruct (g, Gnomic_Projection_Struct)) + { + SLfree ((char *)g); + return NULL; + } + + if ((0.0 == g->txscale) || (0.0 == g->tyscale)) + { + SLang_verror (SL_INVALID_PARM, "%s txscale and tyscale must be non-zero", name); + SLang_free_cstruct (g, Gnomic_Projection_Struct); + return NULL; + } + + g->txscale = RADIANS(g->txscale); + g->tyscale = RADIANS(g->tyscale); + phi0 = LON_TO_PHI(g->lon0); + theta0 = LAT_TO_THETA(g->lat0); + get_tp_basis (theta0, phi0, g->tx_hat, g->ty_hat, g->tz_hat); + return g; +} + +static void gnomic_free (void *g) +{ + if (g == NULL) + return; + + SLang_free_cstruct (g, Gnomic_Projection_Struct); + SLfree ((char *)g); +} + +static int gnomic_project_f (void *vg, + float *lon, float *lat, + float *tx, float *ty, + unsigned int num) +{ + Gnomic_Projection_Type *g = (Gnomic_Projection_Type *)vg; + double tx0 = g->tx0, ty0 = g->ty0; + double *tx_hat = g->tx_hat, *ty_hat = g->ty_hat, *tz_hat = g->tz_hat; + double inv_txscale, inv_tyscale; + unsigned int i; + + inv_txscale = 1.0/g->txscale; + inv_tyscale = 1.0/g->tyscale; + + for (i = 0; i < num; i++) + { + double tx_i, ty_i; + double v[3]; + double theta, phi; + + theta = LAT_TO_THETA(lat[i]); + phi = LON_TO_PHI(lon[i]); + spherical_to_vector (1.0, theta, phi, v); + (void) vector_to_tangent_plane (v, tx_hat, ty_hat, tz_hat, &tx_i, &ty_i); + tx[i] = tx0 + tx_i*inv_txscale; + ty[i] = ty0 + ty_i*inv_tyscale; + } + return 0; +} + +static int gnomic_project_d (void *vg, + double *lon, double *lat, + double *tx, double *ty, + unsigned int num) +{ + Gnomic_Projection_Type *g = (Gnomic_Projection_Type *)vg; + double tx0 = g->tx0, ty0 = g->ty0; + double *tx_hat = g->tx_hat, *ty_hat = g->ty_hat, *tz_hat = g->tz_hat; + double inv_txscale, inv_tyscale; + unsigned int i; + + inv_txscale = 1.0/g->txscale; + inv_tyscale = 1.0/g->tyscale; + + for (i = 0; i < num; i++) + { + double tx_i, ty_i; + double v[3]; + double theta, phi; + + theta = LAT_TO_THETA(lat[i]); + phi = LON_TO_PHI(lon[i]); + spherical_to_vector (1.0, theta, phi, v); + (void) vector_to_tangent_plane (v, tx_hat, ty_hat, tz_hat, &tx_i, &ty_i); + tx[i] = tx0 + tx_i*inv_txscale; + ty[i] = ty0 + ty_i*inv_tyscale; + } + return 0; +} + +static int gnomic_deproject_f (void *vg, + float *tx, float *ty, + float *lon, float *lat, + unsigned int num) +{ + Gnomic_Projection_Type *g = (Gnomic_Projection_Type *)vg; + double tx0 = g->tx0, ty0 = g->ty0; + double txscale = g->txscale, tyscale = g->tyscale; + double *tx_hat = g->tx_hat, *ty_hat = g->ty_hat, *tz_hat = g->tz_hat; + unsigned int i; + + for (i = 0; i < num; i++) + { + double tx_i, ty_i; + double v[3]; + double r, theta, phi; + + tx_i = (tx[i] - tx0) * txscale; + ty_i = (ty[i] - ty0) * tyscale; + tangent_plane_to_vector (tx_hat, ty_hat, tz_hat, tx_i, ty_i, v); + vector_to_spherical (v[0], v[1], v[2], &r, &theta, &phi); + lon[i] = PHI_TO_LON(phi); + lat[i] = THETA_TO_LAT(theta); + } + return 0; +} + +static int gnomic_deproject_d (void *vg, + double *tx, double *ty, + double *lon, double *lat, + unsigned int num) +{ + Gnomic_Projection_Type *g = (Gnomic_Projection_Type *)vg; + double tx0 = g->tx0, ty0 = g->ty0; + double txscale = g->txscale, tyscale = g->tyscale; + double *tx_hat = g->tx_hat, *ty_hat = g->ty_hat, *tz_hat = g->tz_hat; + unsigned int i; + + for (i = 0; i < num; i++) + { + double tx_i, ty_i; + double v[3]; + double r, theta, phi; + + tx_i = (tx[i] - tx0) * txscale; + ty_i = (ty[i] - ty0) * tyscale; + tangent_plane_to_vector (tx_hat, ty_hat, tz_hat, tx_i, ty_i, v); + vector_to_spherical (v[0], v[1], v[2], &r, &theta, &phi); + lon[i] = PHI_TO_LON(phi); + lat[i] = THETA_TO_LAT(theta); + } + return 0; +} + +static int gnomic_reproject_f (void *vga, float *txa, float *tya, + void *vgb, float *txb, float *tyb, + unsigned int num) +{ + Gnomic_Projection_Type *ga = (Gnomic_Projection_Type *)vga; + Gnomic_Projection_Type *gb = (Gnomic_Projection_Type *)vgb; + double txa0 = ga->tx0, tya0 = ga->ty0; + double txb0 = gb->tx0, tyb0 = gb->ty0; + double *txa_hat = ga->tx_hat, *tya_hat = ga->ty_hat, *tza_hat = ga->tz_hat; + double *txb_hat = gb->tx_hat, *tyb_hat = gb->ty_hat, *tzb_hat = gb->tz_hat; + double txascale, tyascale, inv_txbscale, inv_tybscale; + unsigned int i; + + txascale = ga->txscale; + tyascale = ga->tyscale; + inv_txbscale = 1.0/gb->txscale; + inv_tybscale = 1.0/gb->tyscale; + + for (i = 0; i < num; i++) + { + double tx_i, ty_i; + double v[3]; + + tx_i = (txa[i] - txa0) * txascale; + ty_i = (tya[i] - tya0) * tyascale; + + tangent_plane_to_vector (txa_hat, tya_hat, tza_hat, tx_i, ty_i, v); + (void) vector_to_tangent_plane (v, txb_hat, tyb_hat, tzb_hat, &tx_i, &ty_i); + txb[i] = txb0 + tx_i*inv_txbscale; + tyb[i] = tyb0 + ty_i*inv_tybscale; + } + return 0; +} + +static int gnomic_reproject_d (void *vga, double *txa, double *tya, + void *vgb, double *txb, double *tyb, + unsigned int num) +{ + Gnomic_Projection_Type *ga = (Gnomic_Projection_Type *)vga; + Gnomic_Projection_Type *gb = (Gnomic_Projection_Type *)vgb; + double txa0 = ga->tx0, tya0 = ga->ty0; + double txb0 = gb->tx0, tyb0 = gb->ty0; + double *txa_hat = ga->tx_hat, *tya_hat = ga->ty_hat, *tza_hat = ga->tz_hat; + double *txb_hat = gb->tx_hat, *tyb_hat = gb->ty_hat, *tzb_hat = gb->tz_hat; + double txascale, tyascale, inv_txbscale, inv_tybscale; + unsigned int i; + + txascale = ga->txscale; + tyascale = ga->tyscale; + inv_txbscale = 1.0/gb->txscale; + inv_tybscale = 1.0/gb->tyscale; + + for (i = 0; i < num; i++) + { + double tx_i, ty_i; + double v[3]; + + tx_i = (txa[i] - txa0) * txascale; + ty_i = (tya[i] - tya0) * tyascale; + + tangent_plane_to_vector (txa_hat, tya_hat, tza_hat, tx_i, ty_i, v); + (void) vector_to_tangent_plane (v, txb_hat, tyb_hat, tzb_hat, &tx_i, &ty_i); + txb[i] = txb0 + tx_i*inv_txbscale; + tyb[i] = tyb0 + ty_i*inv_tybscale; + } + return 0; +} + + +/*}}}*/ + +/*{{{ Ortho Projection */ + +typedef struct +{ + REQUIRED_FIELDS; + double tx0, ty0, txscale, tyscale; + double tx_hat[3], ty_hat[3], tz_hat[3]; +} +Ortho_Projection_Type; + +static SLang_CStruct_Field_Type Ortho_Projection_Struct[] = +{ + MAKE_CSTRUCT_FIELD(Ortho_Projection_Type, name, "name", SLANG_STRING_TYPE, 0), + MAKE_CSTRUCT_FIELD(Ortho_Projection_Type, lon0, "lon0", SLANG_DOUBLE_TYPE, 0), + MAKE_CSTRUCT_FIELD(Ortho_Projection_Type, lat0, "lat0", SLANG_DOUBLE_TYPE, 0), + MAKE_CSTRUCT_FIELD(Ortho_Projection_Type, tx0, "x0", SLANG_DOUBLE_TYPE, 0), + MAKE_CSTRUCT_FIELD(Ortho_Projection_Type, ty0, "y0", SLANG_DOUBLE_TYPE, 0), + MAKE_CSTRUCT_FIELD(Ortho_Projection_Type, txscale, "xscale", SLANG_DOUBLE_TYPE, 0), + MAKE_CSTRUCT_FIELD(Ortho_Projection_Type, tyscale, "yscale", SLANG_DOUBLE_TYPE, 0), + SLANG_END_CSTRUCT_TABLE +}; + +static int ortho_new (char *name) +{ + Ortho_Projection_Type g; + + g.name = name; + g.lon0 = 0.0; + g.lat0 = 90.0; + g.tx0 = g.ty0 = 0; + g.txscale = 1.0; + g.tyscale = 1.0; + + return SLang_push_cstruct (&g, Ortho_Projection_Struct); +} + +static void *ortho_pop (char *name) +{ + Ortho_Projection_Type *g; + double phi0, theta0; + + if (NULL == (g = (Ortho_Projection_Type *)SLmalloc (sizeof (Ortho_Projection_Type)))) + return NULL; + + if (-1 == SLang_pop_cstruct (g, Ortho_Projection_Struct)) + { + SLfree ((char *)g); + return NULL; + } + + if ((0.0 == g->txscale) || (0.0 == g->tyscale)) + { + SLang_verror (SL_INVALID_PARM, "%s txscale and tyscale must be non-zero", name); + SLang_free_cstruct (g, Ortho_Projection_Struct); + return NULL; + } + + g->txscale = RADIANS(g->txscale); + g->tyscale = RADIANS(g->tyscale); + phi0 = LON_TO_PHI(g->lon0); + theta0 = LAT_TO_THETA(g->lat0); + get_tp_basis (theta0, phi0, g->tx_hat, g->ty_hat, g->tz_hat); + return g; +} + +static void ortho_free (void *g) +{ + if (g == NULL) + return; + + SLang_free_cstruct (g, Ortho_Projection_Struct); + SLfree ((char *)g); +} + +static int ortho_project_f (void *vg, + float *lon, float *lat, + float *tx, float *ty, + unsigned int num) +{ + Ortho_Projection_Type *g = (Ortho_Projection_Type *)vg; + double tx0 = g->tx0, ty0 = g->ty0; + double *tx_hat = g->tx_hat, *ty_hat = g->ty_hat, *tz_hat = g->tz_hat; + double inv_txscale, inv_tyscale; + unsigned int i; + + inv_txscale = 1.0/g->txscale; + inv_tyscale = 1.0/g->tyscale; + + for (i = 0; i < num; i++) + { + double tx_i, ty_i; + double v[3]; + double theta, phi; + + theta = LAT_TO_THETA(lat[i]); + phi = LON_TO_PHI(lon[i]); + spherical_to_vector (1.0, theta, phi, v); + (void) ortho_project_vector (v, tx_hat, ty_hat, tz_hat, &tx_i, &ty_i); + tx[i] = tx0 + tx_i*inv_txscale; + ty[i] = ty0 + ty_i*inv_tyscale; + } + return 0; +} + +static int ortho_project_d (void *vg, + double *lon, double *lat, + double *tx, double *ty, + unsigned int num) +{ + Ortho_Projection_Type *g = (Ortho_Projection_Type *)vg; + double tx0 = g->tx0, ty0 = g->ty0; + double *tx_hat = g->tx_hat, *ty_hat = g->ty_hat, *tz_hat = g->tz_hat; + double inv_txscale, inv_tyscale; + unsigned int i; + + inv_txscale = 1.0/g->txscale; + inv_tyscale = 1.0/g->tyscale; + + for (i = 0; i < num; i++) + { + double tx_i, ty_i; + double v[3]; + double theta, phi; + + theta = LAT_TO_THETA(lat[i]); + phi = LON_TO_PHI(lon[i]); + spherical_to_vector (1.0, theta, phi, v); + (void) ortho_project_vector (v, tx_hat, ty_hat, tz_hat, &tx_i, &ty_i); + tx[i] = tx0 + tx_i*inv_txscale; + ty[i] = ty0 + ty_i*inv_tyscale; + } + return 0; +} + +static int ortho_deproject_f (void *vg, + float *tx, float *ty, + float *lon, float *lat, + unsigned int num) +{ + Ortho_Projection_Type *g = (Ortho_Projection_Type *)vg; + double tx0 = g->tx0, ty0 = g->ty0; + double txscale = g->txscale, tyscale = g->tyscale; + double *tx_hat = g->tx_hat, *ty_hat = g->ty_hat, *tz_hat = g->tz_hat; + unsigned int i; + + for (i = 0; i < num; i++) + { + double tx_i, ty_i; + double v[3]; + double r, theta, phi; + + tx_i = (tx[i] - tx0) * txscale; + ty_i = (ty[i] - ty0) * tyscale; + (void) ortho_deproject_vector (tx_hat, ty_hat, tz_hat, tx_i, ty_i, v); + vector_to_spherical (v[0], v[1], v[2], &r, &theta, &phi); + lon[i] = PHI_TO_LON(phi); + lat[i] = THETA_TO_LAT(theta); + } + return 0; +} + +static int ortho_deproject_d (void *vg, + double *tx, double *ty, + double *lon, double *lat, + unsigned int num) +{ + Ortho_Projection_Type *g = (Ortho_Projection_Type *)vg; + double tx0 = g->tx0, ty0 = g->ty0; + double txscale = g->txscale, tyscale = g->tyscale; + double *tx_hat = g->tx_hat, *ty_hat = g->ty_hat, *tz_hat = g->tz_hat; + unsigned int i; + + for (i = 0; i < num; i++) + { + double tx_i, ty_i; + double v[3]; + double r, theta, phi; + + tx_i = (tx[i] - tx0) * txscale; + ty_i = (ty[i] - ty0) * tyscale; + (void) ortho_deproject_vector (tx_hat, ty_hat, tz_hat, tx_i, ty_i, v); + vector_to_spherical (v[0], v[1], v[2], &r, &theta, &phi); + lon[i] = PHI_TO_LON(phi); + lat[i] = THETA_TO_LAT(theta); + } + return 0; +} + +/*}}}*/ + +/*{{{ Generic Plane Projection */ + +typedef struct +{ + REQUIRED_FIELDS; + double tx0, ty0, txscale, tyscale; + double p_lon, p_lat, p_len; + double tx_hat[3], ty_hat[3]; + double s0[3]; /* pos of tangent plane on sphere -- also its normal */ + double phat[3]; /* unit vector to observer position */ +} +Plane_Projection_Type; + +static SLang_CStruct_Field_Type Plane_Projection_Struct[] = +{ + MAKE_CSTRUCT_FIELD(Plane_Projection_Type, name, "name", SLANG_STRING_TYPE, 0), + MAKE_CSTRUCT_FIELD(Plane_Projection_Type, lon0, "lon0", SLANG_DOUBLE_TYPE, 0), + MAKE_CSTRUCT_FIELD(Plane_Projection_Type, lat0, "lat0", SLANG_DOUBLE_TYPE, 0), + MAKE_CSTRUCT_FIELD(Plane_Projection_Type, tx0, "x0", SLANG_DOUBLE_TYPE, 0), + MAKE_CSTRUCT_FIELD(Plane_Projection_Type, ty0, "y0", SLANG_DOUBLE_TYPE, 0), + MAKE_CSTRUCT_FIELD(Plane_Projection_Type, txscale, "xscale", SLANG_DOUBLE_TYPE, 0), + MAKE_CSTRUCT_FIELD(Plane_Projection_Type, tyscale, "yscale", SLANG_DOUBLE_TYPE, 0), + MAKE_CSTRUCT_FIELD(Plane_Projection_Type, p_lon, "p_lon", SLANG_DOUBLE_TYPE, 0), + MAKE_CSTRUCT_FIELD(Plane_Projection_Type, p_lat, "p_lat", SLANG_DOUBLE_TYPE, 0), + MAKE_CSTRUCT_FIELD(Plane_Projection_Type, p_len, "p_len", SLANG_DOUBLE_TYPE, 0), + SLANG_END_CSTRUCT_TABLE +}; + +static int plane_new (char *name) +{ + Plane_Projection_Type g; + + g.name = name; + g.lon0 = 0.0; + g.lat0 = 90.0; + g.tx0 = g.ty0 = 0; + g.txscale = 1.0; + g.tyscale = 1.0; + + g.p_lon = 0.0; + g.p_lat = -90.0; + g.p_len = 0.0; /* gnomic */ + + return SLang_push_cstruct (&g, Plane_Projection_Struct); +} + +static void *plane_pop (char *name) +{ + Plane_Projection_Type *g; + + if (NULL == (g = (Plane_Projection_Type *)SLmalloc (sizeof (Plane_Projection_Type)))) + return NULL; + + if (-1 == SLang_pop_cstruct (g, Plane_Projection_Struct)) + { + SLfree ((char *)g); + return NULL; + } + + if ((0.0 == g->txscale) || (0.0 == g->tyscale)) + { + SLang_verror (SL_INVALID_PARM, "%s txscale and tyscale must be non-zero", name); + SLang_free_cstruct (g, Plane_Projection_Struct); + return NULL; + } + + g->txscale = RADIANS(g->txscale); + g->tyscale = RADIANS(g->tyscale); + + g->p_len = fabs (g->p_len); + (void) compute_plane_vectors (LAT_TO_THETA(g->lat0), LON_TO_PHI(g->lon0), + g->tx_hat, g->ty_hat, g->s0); + spherical_to_vector (1.0, LAT_TO_THETA(g->p_lat), LON_TO_PHI(g->p_lon), g->phat); + return g; +} + +static void plane_free (void *g) +{ + if (g == NULL) + return; + + SLang_free_cstruct (g, Plane_Projection_Struct); + SLfree ((char *)g); +} + +static int plane_project_f (void *vg, + float *lon, float *lat, + float *tx, float *ty, + unsigned int num) +{ + Plane_Projection_Type *g = (Plane_Projection_Type *)vg; + double tx0 = g->tx0, ty0 = g->ty0; + double *tx_hat = g->tx_hat, *ty_hat = g->ty_hat; + double *phat = g->phat, *s0 = g->s0; + double plen = g->p_len; + double inv_txscale, inv_tyscale; + unsigned int i; + + inv_txscale = 1.0/g->txscale; + inv_tyscale = 1.0/g->tyscale; + + for (i = 0; i < num; i++) + { + double tx_i, ty_i; + double s[3]; + double theta, phi; + + theta = LAT_TO_THETA(lat[i]); + phi = LON_TO_PHI(lon[i]); + spherical_to_vector (1.0, theta, phi, s); + (void) project_to_plane_coords (s, s0, plen, phat, tx_hat, ty_hat, &tx_i, &ty_i); + tx[i] = tx0 + tx_i*inv_txscale; + ty[i] = ty0 + ty_i*inv_tyscale; + } + return 0; +} + +static int plane_project_d (void *vg, + double *lon, double *lat, + double *tx, double *ty, + unsigned int num) +{ + Plane_Projection_Type *g = (Plane_Projection_Type *)vg; + double tx0 = g->tx0, ty0 = g->ty0; + double *tx_hat = g->tx_hat, *ty_hat = g->ty_hat; + double *phat = g->phat, *s0 = g->s0; + double plen = g->p_len; + double inv_txscale, inv_tyscale; + unsigned int i; + + inv_txscale = 1.0/g->txscale; + inv_tyscale = 1.0/g->tyscale; + + for (i = 0; i < num; i++) + { + double tx_i, ty_i; + double s[3]; + double theta, phi; + + theta = LAT_TO_THETA(lat[i]); + phi = LON_TO_PHI(lon[i]); + spherical_to_vector (1.0, theta, phi, s); + (void) project_to_plane_coords (s, s0, plen, phat, tx_hat, ty_hat, &tx_i, &ty_i); + tx[i] = tx0 + tx_i*inv_txscale; + ty[i] = ty0 + ty_i*inv_tyscale; + } + return 0; +} + + +static int plane_deproject_f (void *vg, + float *tx, float *ty, + float *lon, float *lat, + unsigned int num) +{ + Plane_Projection_Type *g = (Plane_Projection_Type *)vg; + double tx0 = g->tx0, ty0 = g->ty0; + double txscale = g->txscale, tyscale = g->tyscale; + double *tx_hat = g->tx_hat, *ty_hat = g->ty_hat; + double *phat = g->phat, *s0 = g->s0; + double plen = g->p_len; + unsigned int i; + + for (i = 0; i < num; i++) + { + double tx_i, ty_i; + double s[3]; + double r, theta, phi; + + tx_i = (tx[i] - tx0) * txscale; + ty_i = (ty[i] - ty0) * tyscale; + (void) project_from_plane_coords (tx_i, ty_i, s0, plen, phat, tx_hat, ty_hat, s); + vector_to_spherical (s[0], s[1], s[2], &r, &theta, &phi); + lon[i] = PHI_TO_LON(phi); + lat[i] = THETA_TO_LAT(theta); + } + return 0; +} + +static int plane_deproject_d (void *vg, + double *tx, double *ty, + double *lon, double *lat, + unsigned int num) +{ + Plane_Projection_Type *g = (Plane_Projection_Type *)vg; + double tx0 = g->tx0, ty0 = g->ty0; + double txscale = g->txscale, tyscale = g->tyscale; + double *tx_hat = g->tx_hat, *ty_hat = g->ty_hat; + double *phat = g->phat, *s0 = g->s0; + double plen = g->p_len; + unsigned int i; + + for (i = 0; i < num; i++) + { + double tx_i, ty_i; + double s[3]; + double r, theta, phi; + + tx_i = (tx[i] - tx0) * txscale; + ty_i = (ty[i] - ty0) * tyscale; + (void) project_from_plane_coords (tx_i, ty_i, s0, plen, phat, tx_hat, ty_hat, s); + + vector_to_spherical (s[0], s[1], s[2], &r, &theta, &phi); + lon[i] = PHI_TO_LON(phi); + lat[i] = THETA_TO_LAT(theta); + } + return 0; +} + +/*}}}*/ + +/*{{{ Stereographic */ + +typedef Plane_Projection_Type Stereo_Projection_Type; + +static SLang_CStruct_Field_Type Stereo_Projection_Struct[] = +{ + MAKE_CSTRUCT_FIELD(Stereo_Projection_Type, name, "name", SLANG_STRING_TYPE, 0), + MAKE_CSTRUCT_FIELD(Stereo_Projection_Type, lon0, "lon0", SLANG_DOUBLE_TYPE, 0), + MAKE_CSTRUCT_FIELD(Stereo_Projection_Type, lat0, "lat0", SLANG_DOUBLE_TYPE, 0), + MAKE_CSTRUCT_FIELD(Stereo_Projection_Type, tx0, "x0", SLANG_DOUBLE_TYPE, 0), + MAKE_CSTRUCT_FIELD(Stereo_Projection_Type, ty0, "y0", SLANG_DOUBLE_TYPE, 0), + MAKE_CSTRUCT_FIELD(Stereo_Projection_Type, txscale, "xscale", SLANG_DOUBLE_TYPE, 0), + MAKE_CSTRUCT_FIELD(Stereo_Projection_Type, tyscale, "yscale", SLANG_DOUBLE_TYPE, 0), + SLANG_END_CSTRUCT_TABLE +}; + +static int stereo_new (char *name) +{ + Stereo_Projection_Type g; + + g.name = name; + g.lon0 = 0.0; + g.lat0 = 90.0; + g.tx0 = g.ty0 = 0; + g.txscale = 1.0; + g.tyscale = 1.0; + + return SLang_push_cstruct (&g, Stereo_Projection_Struct); +} + +static void *stereo_pop (char *name) +{ + Stereo_Projection_Type *g; + + if (NULL == (g = (Stereo_Projection_Type *)SLmalloc (sizeof (Stereo_Projection_Type)))) + return NULL; + + if (-1 == SLang_pop_cstruct (g, Stereo_Projection_Struct)) + { + SLfree ((char *)g); + return NULL; + } + + if ((0.0 == g->txscale) || (0.0 == g->tyscale)) + { + SLang_verror (SL_INVALID_PARM, "%s txscale and tyscale must be non-zero", name); + SLang_free_cstruct (g, Stereo_Projection_Struct); + return NULL; + } + + g->txscale = RADIANS(g->txscale); + g->tyscale = RADIANS(g->tyscale); + + normalize_lon_lat_degrees (&g->lon0, &g->lat0); + + g->p_lon = g->lon0; + g->p_lat = -g->lat0; + g->p_len = 1.0; + + (void) compute_plane_vectors (LAT_TO_THETA(g->lat0), LON_TO_PHI(g->lon0), + g->tx_hat, g->ty_hat, g->s0); + spherical_to_vector (1.0, LAT_TO_THETA(g->p_lat), LON_TO_PHI(g->p_lon), g->phat); + return g; +} + +static void stereo_free (void *g) +{ + if (g == NULL) + return; + + SLang_free_cstruct (g, Stereo_Projection_Struct); + SLfree ((char *)g); +} +/*}}}*/ + +/*{{{ Lambert */ + +typedef struct +{ + REQUIRED_FIELDS; + double tx0, ty0; + double txscale, tyscale; + double cos_lat0, sin_lat0; +} +Lambert_Projection_Type; + +static SLang_CStruct_Field_Type Lambert_Projection_Struct[] = +{ + MAKE_CSTRUCT_FIELD(Lambert_Projection_Type, name, "name", SLANG_STRING_TYPE, 0), + MAKE_CSTRUCT_FIELD(Lambert_Projection_Type, lon0, "lon0", SLANG_DOUBLE_TYPE, 0), + MAKE_CSTRUCT_FIELD(Lambert_Projection_Type, lat0, "lat0", SLANG_DOUBLE_TYPE, 0), + MAKE_CSTRUCT_FIELD(Lambert_Projection_Type, tx0, "x0", SLANG_DOUBLE_TYPE, 0), + MAKE_CSTRUCT_FIELD(Lambert_Projection_Type, ty0, "y0", SLANG_DOUBLE_TYPE, 0), + MAKE_CSTRUCT_FIELD(Lambert_Projection_Type, txscale, "xscale", SLANG_DOUBLE_TYPE, 0), + MAKE_CSTRUCT_FIELD(Lambert_Projection_Type, tyscale, "yscale", SLANG_DOUBLE_TYPE, 0), + SLANG_END_CSTRUCT_TABLE +}; + +static int lambert_new (char *name) +{ + Lambert_Projection_Type g; + + g.name = name; + g.lon0 = 0.0; + g.lat0 = 90.0; + g.tx0 = g.ty0 = 0; + g.txscale = 1.0; + g.tyscale = 1.0; + + return SLang_push_cstruct (&g, Lambert_Projection_Struct); +} + +static void *lambert_pop (char *name) +{ + Lambert_Projection_Type *g; + double lat0; + + if (NULL == (g = (Lambert_Projection_Type *)SLmalloc (sizeof (Lambert_Projection_Type)))) + return NULL; + + if (-1 == SLang_pop_cstruct (g, Lambert_Projection_Struct)) + { + SLfree ((char *)g); + return NULL; + } + + if ((0.0 == g->txscale) || (0.0 == g->tyscale)) + { + SLang_verror (SL_INVALID_PARM, "%s txscale and tyscale must be non-zero", name); + SLang_free_cstruct (g, Lambert_Projection_Struct); + return NULL; + } + + g->txscale = RADIANS(g->txscale); + g->tyscale = RADIANS(g->tyscale); + normalize_lon_lat_degrees (&g->lon0, &g->lat0); + lat0 = RADIANS(g->lat0); + g->cos_lat0 = cos (lat0); + g->sin_lat0 = sin (lat0); + return g; +} + +static void lambert_free (void *g) +{ + if (g == NULL) + return; + + SLang_free_cstruct (g, Lambert_Projection_Struct); + SLfree ((char *)g); +} + +static int lambert_lonlat_to_xy (double lon, double lat, double lon0, + double cos_lat0, double sin_lat0, + double *xp, double *yp) +{ + double r, x, y; + double cos_lat = cos (lat); + double sin_lat = sin (lat); + double cos_lon, sin_lon; + + lon = fmod (lon, 2*PI); /* lon could be huge */ + lon -= lon0; + + cos_lon = cos (lon); + sin_lon = sin (lon); + + r = 1.0 + sin_lat0*sin_lat + cos_lat0*cos_lat*cos_lon; + if (r <= 1e-9) + { +#if 0 + x = 2.0*sin_lon; + y = -2.0*cos_lon; + if (sin_lat0 < 0) + y = -y; + *xp = x; + *yp = y; + return 0; +#endif + } + r = sqrt (2.0/r); + + x = r * (cos_lat*sin_lon); + y = r * (cos_lat0 * sin_lat - sin_lat0*cos_lat*cos_lon); + + *xp = x; + *yp = y; + return 0; +} + +static int lambert_xy_to_lonlat (double x, double y, + double lon0, + double cos_lat0, double sin_lat0, + double *lonp, double *latp) +{ + double r, y_r, x_r; + double theta, c, s; + double arg, lon, lat; + + r = hypot (x, y); + if (r > 2.0) + { + *latp = *lonp = Maplib_NaN; + return -1; + } + + theta = 2.0 * asin(0.5*r); + c = cos (theta); + s = sin (theta); + + if (r == 0.0) + y_r = x_r = 1.0; + else + { + y_r = y/r; + x_r = x/r; + } + + arg = c * sin_lat0 + y_r * s * cos_lat0; + if (fabs(arg) > 1.0) + { + *lonp = *latp = Maplib_NaN; + return -1; + } + lat = asin (arg); + lon = lon0 + atan2 (s*x_r, c*cos_lat0 - y_r*s*sin_lat0); + + lon = fmod (lon, 2*PI); + if (lon < -PI) + lon += 2*PI; + + *lonp = lon; + *latp = lat; + return 0; +} + +static int lambert_project_d (void *vg, + double *lon, double *lat, + double *tx, double *ty, + unsigned int num) +{ + Lambert_Projection_Type *g = (Lambert_Projection_Type *)vg; + double tx0 = g->tx0, ty0 = g->ty0; + double inv_txscale, inv_tyscale; + double cos_lat0, sin_lat0, lon0, lat0; + unsigned int i; + + lon0 = RADIANS(g->lon0); + lat0 = RADIANS(g->lat0); + cos_lat0 = g->cos_lat0; + sin_lat0 = g->sin_lat0; + + inv_txscale = 1.0/g->txscale; + inv_tyscale = 1.0/g->tyscale; + + for (i = 0; i < num; i++) + { + double tx_i, ty_i; + double lon_i, lat_i; + + lon_i = RADIANS(lon[i]); + lat_i = RADIANS(lat[i]); + (void) lambert_lonlat_to_xy (lon_i, lat_i, lon0, cos_lat0, sin_lat0, + &tx_i, &ty_i); + tx[i] = tx0 + tx_i*inv_txscale; + ty[i] = ty0 + ty_i*inv_tyscale; + } + return 0; +} + + +static int lambert_deproject_d (void *vg, + double *tx, double *ty, + double *lon, double *lat, + unsigned int num) +{ + Lambert_Projection_Type *g = (Lambert_Projection_Type *)vg; + double tx0 = g->tx0, ty0 = g->ty0; + double txscale = g->txscale, tyscale = g->tyscale; + double cos_lat0, sin_lat0, lon0, lat0; + unsigned int i; + + lon0 = RADIANS(g->lon0); + lat0 = RADIANS(g->lat0); + cos_lat0 = g->cos_lat0; + sin_lat0 = g->sin_lat0; + + for (i = 0; i < num; i++) + { + double tx_i, ty_i; + double lon_i, lat_i; + + tx_i = (tx[i] - tx0) * txscale; + ty_i = (ty[i] - ty0) * tyscale; + (void) lambert_xy_to_lonlat (tx_i, ty_i, lon0, cos_lat0, sin_lat0, + &lon_i, &lat_i); + lon[i] = DEGREES(lon_i); + lat[i] = DEGREES(lat_i); + } + return 0; +} + +static int lambert_project_f (void *vg, + float *lon, float *lat, + float *tx, float *ty, + unsigned int num) +{ + Lambert_Projection_Type *g = (Lambert_Projection_Type *)vg; + double tx0 = g->tx0, ty0 = g->ty0; + double inv_txscale, inv_tyscale; + double cos_lat0, sin_lat0, lon0, lat0; + unsigned int i; + + lon0 = RADIANS(g->lon0); + lat0 = RADIANS(g->lat0); + cos_lat0 = g->cos_lat0; + sin_lat0 = g->sin_lat0; + + inv_txscale = 1.0/g->txscale; + inv_tyscale = 1.0/g->tyscale; + + for (i = 0; i < num; i++) + { + double tx_i, ty_i; + double lon_i, lat_i; + + lon_i = RADIANS(lon[i]); + lat_i = RADIANS(lat[i]); + (void) lambert_lonlat_to_xy (lon_i, lat_i, lon0, cos_lat0, sin_lat0, + &tx_i, &ty_i); + tx[i] = tx0 + tx_i*inv_txscale; + ty[i] = ty0 + ty_i*inv_tyscale; + } + return 0; +} + + +static int lambert_deproject_f (void *vg, + float *tx, float *ty, + float *lon, float *lat, + unsigned int num) +{ + Lambert_Projection_Type *g = (Lambert_Projection_Type *)vg; + double tx0 = g->tx0, ty0 = g->ty0; + double txscale = g->txscale, tyscale = g->tyscale; + double cos_lat0, sin_lat0, lon0, lat0; + unsigned int i; + + lon0 = RADIANS(g->lon0); + lat0 = RADIANS(g->lat0); + cos_lat0 = g->cos_lat0; + sin_lat0 = g->sin_lat0; + + for (i = 0; i < num; i++) + { + double tx_i, ty_i; + double lon_i, lat_i; + + tx_i = (tx[i] - tx0) * txscale; + ty_i = (ty[i] - ty0) * tyscale; + (void) lambert_xy_to_lonlat (tx_i, ty_i, lon0, cos_lat0, sin_lat0, + &lon_i, &lat_i); + lon[i] = DEGREES(lon_i); + lat[i] = DEGREES(lat_i); + } + return 0; +} + + +/*}}}*/ + +/*{{{ Generic */ + +typedef struct +{ + REQUIRED_FIELDS; /* name, lon0, lat0 (degrees) */ + double beta; + double tx0, ty0; + double txscale, tyscale; + double ref_lon, ref_lat; /* sphere will be rotated to this position */ + int apply_sphere_rotation; + Sphere_Rotate_Type sphere_xform; + void *client_data; + struct Generic_Info_Type *info; +} +Generic_Projection_Type; + +typedef struct Generic_Info_Type +{ + char *name; + int (*init)(Generic_Projection_Type *); + void (*deinit)(void *); + int (*project)(void *, double, double, double *, double *); + int (*deproject)(void *, double, double, double *, double *); + double lon0, lat0; /* degrees */ +} +Generic_Info_Type; + +/*{{{ Hammer */ + +static int hammer_project (void *cd, double lon, double lat, double *xp, double *yp) +{ + double x; + int ret = lambert_lonlat_to_xy (0.5*lon, lat, 0.0, 1.0, 0.0, &x, yp); + (void) cd; + *xp = 2.0 * x; + return ret; +} + +static int hammer_deproject (void *cd, double x, double y, double *lonp, double *latp) +{ + double lon; + int ret = lambert_xy_to_lonlat (0.5*x, y, 0.0, 1.0, 0.0, &lon, latp); + (void) cd; + *lonp = 2.0 * lon; + return ret; +} + +/*}}}*/ + +/*{{{ Mercator */ + +static int mercator_project (void *cd, double lon, double lat, double *xp, double *yp) +{ + (void) cd; + *xp = lon; + *yp = log (tan (PI/4 + 0.5*lat)); + return 0; +} + +static int mercator_deproject (void *cd, double x, double y, double *lonp, double *latp) +{ + (void) cd; + *lonp = x; + *latp = 2.0*(atan(exp(y)) - (PI/4)); + return 0; +} + +/*}}}*/ + +/*{{{ Azimuthal Equidist (azeqdist) */ + +static int azeqdist_project (void *cd, double lon, double lat, double *xp, double *yp) +{ + (void) cd; + lat = PI/2 - lat; + *xp = lat * sin(lon); + *yp = -lat * cos(lon); + return 0; +} + +static int azeqdist_deproject (void *cd, double x, double y, double *lonp, double *latp) +{ + (void) cd; + + *lonp = atan2(x,-y); + *latp = PI/2 - hypot (x,y); + return 0; +} + +/*}}}*/ + +/*{{{ Bonne */ + +/* The equations here are taken from Snyder 1987 */ +typedef struct +{ + double lon0, lat0; /* radians */ + double cot_lat0; + double cot_lat0_plus_lat0; +} +Bonne_Type; + +static void bonne_deinit (void *p) +{ + if (p != NULL) + SLfree ((char *)p); +} + +static int bonne_init (Generic_Projection_Type *g) +{ + Bonne_Type *b; + + if (NULL == (b = (Bonne_Type *)SLmalloc (sizeof (Bonne_Type)))) + return -1; + g->client_data = b; + /* Transformation is oblique */ + g->ref_lon = g->lon0; + g->ref_lat = g->lat0; + + b->lon0 = RADIANS(g->lon0); + b->lat0 = RADIANS(g->lat0); + b->cot_lat0 = 1.0/tan(b->lat0); + b->cot_lat0_plus_lat0 = b->cot_lat0 + b->lat0; + return 0; +} + +static int bonne_project (void *cd, double lon, double lat, double *xp, double *yp) +{ + double rho, e, dlon; + Bonne_Type *b = (Bonne_Type *)cd; + + if ((lat == b->lat0) + && (lat == PI/2)) + { + *xp = *yp = 0.0; + return 0; + } + + rho = (b->cot_lat0_plus_lat0 - lat); + dlon = lon - b->lon0; + if ((dlon < -PI) || (dlon > PI)) + dlon = normalize_to_range (dlon, PI); + + e = dlon*cos(lat)/rho; + *xp = rho*sin(e); + *yp = b->cot_lat0 - rho*cos(e); + return 0; +} + +static int bonne_deproject (void *cd, double x, double y, double *lonp, double *latp) +{ + double rho, dy; + Bonne_Type *b = (Bonne_Type *)cd; + double lon, lat; + + dy = b->cot_lat0 - y; + rho = hypot (x, dy); + if (b->cot_lat0 < 0) + rho = -rho; + + lat = b->cot_lat0_plus_lat0 - rho; + if (b->lat0 < 0) + { + x = -x; + dy = -dy; + } + lon = b->lon0 + rho * atan2 (x, dy)/cos(lat); + if ((lon < -PI) || (lon > PI)) + lon = normalize_to_range (lon, PI); + + *lonp = lon; + *latp = lat; + return 0; +} + +/*}}}*/ + +/*{{{ Sinusoidal */ + +/* The equations here are taken from Snyder 1987 */ + +typedef struct +{ + double lon0; /* radians */ +} +Sinusoidal_Type; + +static void sinusoidal_deinit (void *p) +{ + if (p != NULL) + SLfree ((char *)p); +} + +static int sinusoidal_init (Generic_Projection_Type *g) +{ + Sinusoidal_Type *b; + + if (NULL == (b = (Sinusoidal_Type *)SLmalloc (sizeof (Sinusoidal_Type)))) + return -1; + g->client_data = b; + + /* Transformation is oblique */ + g->ref_lon = g->lon0; + g->ref_lat = g->lat0; + + b->lon0 = RADIANS(g->lon0); + return 0; +} + +static int sinusoidal_project (void *cd, double lon, double lat, double *xp, double *yp) +{ + Sinusoidal_Type *b = (Sinusoidal_Type *)cd; + + lon = lon - b->lon0; + if ((lon < -PI) || (lon > PI)) + lon = normalize_to_range (lon, PI); + + *xp = lon * cos (lat); + *yp = lat; + return 0; +} + +static int sinusoidal_deproject (void *cd, double x, double y, double *lonp, double *latp) +{ + Sinusoidal_Type *b = (Sinusoidal_Type *)cd; + double lon; + + *latp = y; + lon = b->lon0 + x/cos(y); + + if ((lon < -PI) || (lon > PI)) + lon = normalize_to_range (lon, PI); + + *lonp = lon; + return 0; +} + +/*}}}*/ + +static Generic_Info_Type Generic_Info_Table[] = +{ + {"hammer", NULL, NULL, hammer_project, hammer_deproject, 0.0, 0.0}, + {"mercator", NULL, NULL, mercator_project, mercator_deproject, 0.0, 0.0}, + {"azeqdist", NULL, NULL, azeqdist_project, azeqdist_deproject, 0.0, 90.0}, + {"bonne", bonne_init, bonne_deinit, bonne_project, bonne_deproject, 0.0, 45.0}, + {"sinusoidal", sinusoidal_init, sinusoidal_deinit, sinusoidal_project, sinusoidal_deproject, 0.0, 0.0}, + {NULL, NULL, NULL, NULL, NULL, 0.0, 0.0} +}; + +static Generic_Info_Type *lookup_generic_xform (char *name) +{ + Generic_Info_Type *info; + + info = Generic_Info_Table; + while (info->name != NULL) + { + if (0 == strcmp (name, info->name)) + return info; + info++; + } + SLang_verror (SL_INTERNAL_ERROR, "Generic projection %s not found", name); + return NULL; +} + +static SLang_CStruct_Field_Type Generic_Projection_Struct[] = +{ + MAKE_CSTRUCT_FIELD(Generic_Projection_Type, name, "name", SLANG_STRING_TYPE, 0), + MAKE_CSTRUCT_FIELD(Generic_Projection_Type, lon0, "lon0", SLANG_DOUBLE_TYPE, 0), + MAKE_CSTRUCT_FIELD(Generic_Projection_Type, lat0, "lat0", SLANG_DOUBLE_TYPE, 0), + MAKE_CSTRUCT_FIELD(Generic_Projection_Type, beta, "beta", SLANG_DOUBLE_TYPE, 0), + MAKE_CSTRUCT_FIELD(Generic_Projection_Type, tx0, "x0", SLANG_DOUBLE_TYPE, 0), + MAKE_CSTRUCT_FIELD(Generic_Projection_Type, ty0, "y0", SLANG_DOUBLE_TYPE, 0), + MAKE_CSTRUCT_FIELD(Generic_Projection_Type, txscale, "xscale", SLANG_DOUBLE_TYPE, 0), + MAKE_CSTRUCT_FIELD(Generic_Projection_Type, tyscale, "yscale", SLANG_DOUBLE_TYPE, 0), + SLANG_END_CSTRUCT_TABLE +}; + +static int generic_new (char *name) +{ + Generic_Projection_Type g; + Generic_Info_Type *info; + + if (NULL == (info = lookup_generic_xform (name))) + return -1; + + g.name = name; + g.lon0 = info->lon0; + g.lat0 = info->lat0; + g.beta = 0.0; + g.tx0 = g.ty0 = 0; + g.txscale = 1.0; + g.tyscale = 1.0; + + return SLang_push_cstruct (&g, Generic_Projection_Struct); +} + +static void generic_free (void *vg) +{ + Generic_Projection_Type *g = (Generic_Projection_Type *)vg; + if (g == NULL) + return; + + if ((g->info != NULL) && (g->info->deinit != NULL)) + (*g->info->deinit)(g->client_data); + + SLang_free_cstruct (g, Generic_Projection_Struct); + SLfree ((char *)g); +} + +static void *generic_pop (char *name) +{ + Generic_Projection_Type *g; + Generic_Info_Type *info; + + if (NULL == (info = lookup_generic_xform (name))) + return NULL; + + if (NULL == (g = (Generic_Projection_Type *)SLmalloc (sizeof (Generic_Projection_Type)))) + return NULL; + + if (-1 == SLang_pop_cstruct (g, Generic_Projection_Struct)) + { + SLfree ((char *)g); + return NULL; + } + + if ((0.0 == g->txscale) || (0.0 == g->tyscale)) + { + SLang_verror (SL_INVALID_PARM, "%s txscale and tyscale must be non-zero", name); + SLfree ((char *)g); + return NULL; + } + + g->txscale = RADIANS(g->txscale); + g->tyscale = RADIANS(g->tyscale); + normalize_lon_lat_degrees (&g->lon0, &g->lat0); + g->info = info; + g->ref_lon = info->lon0; + g->ref_lat = info->lat0; + g->client_data = NULL; + + if ((info->init != NULL) && (-1 == (*info->init)(g))) + { + SLfree ((char *)g); + return NULL; + } + /* From here on, we can call generic_free to free g */ + + g->apply_sphere_rotation = 0; + if ((g->lon0 != g->ref_lon) || (g->lat0 != g->ref_lat) || (g->beta != 0.0)) + { + if (-1 == init_sphere_xform (&g->sphere_xform, RADIANS(g->lon0), RADIANS(g->lat0), RADIANS(g->ref_lon), RADIANS(g->ref_lat), RADIANS(g->beta))) + { + generic_free (g); + return NULL; + } + g->apply_sphere_rotation = 1; + } + return g; +} + +static int generic_project_d (void *vg, + double *lon, double *lat, + double *tx, double *ty, + unsigned int num) +{ + Generic_Projection_Type *g = (Generic_Projection_Type *)vg; + int (*project)(void *, double, double, double *, double *); + void *client_data; + double tx0 = g->tx0, ty0 = g->ty0; + double inv_txscale, inv_tyscale; + unsigned int i; + + client_data = g->client_data; + project = g->info->project; + if (project == NULL) + { + SLang_verror (SL_NOT_IMPLEMENTED, "Projection %s does not support projecting", g->name); + return -1; + } + + if (g->apply_sphere_rotation) + { + Sphere_Rotate_Type *s = &g->sphere_xform; + for (i = 0; i < num; i++) + { + double tx1, ty1; + rotate_sphere (s, 1, RADIANS(lon[i]), RADIANS(lat[i]), &tx1, &ty1); + tx[i] = DEGREES(tx1); + ty[i] = DEGREES(ty1); + } + lon = tx; + lat = ty; + } + + inv_txscale = 1.0/g->txscale; + inv_tyscale = 1.0/g->tyscale; + for (i = 0; i < num; i++) + { + double tx_i, ty_i; + double lon_i, lat_i; + + lon_i = RADIANS(lon[i]); + lat_i = RADIANS(lat[i]); + (void) (*project)(client_data, lon_i, lat_i, &tx_i, &ty_i); + tx[i] = tx0 + tx_i*inv_txscale; + ty[i] = ty0 + ty_i*inv_tyscale; + } + return 0; +} + + +static int generic_deproject_d (void *vg, + double *tx, double *ty, + double *lon, double *lat, + unsigned int num) +{ + Generic_Projection_Type *g = (Generic_Projection_Type *)vg; + int (*deproject)(void *, double, double, double *, double *); + void *client_data; + double tx0 = g->tx0, ty0 = g->ty0; + double txscale = g->txscale, tyscale = g->tyscale; + unsigned int i; + + client_data = g->client_data; + deproject = g->info->deproject; + if (deproject == NULL) + { + SLang_verror (SL_NOT_IMPLEMENTED, "Projection %s does not support deprojecting", g->name); + return -1; + } + + for (i = 0; i < num; i++) + { + double tx_i, ty_i; + double lon_i, lat_i; + + tx_i = (tx[i] - tx0) * txscale; + ty_i = (ty[i] - ty0) * tyscale; + (void) (*deproject)(client_data, tx_i, ty_i, &lon_i, &lat_i); + lon[i] = DEGREES(lon_i); + lat[i] = DEGREES(lat_i); + } + + if (g->apply_sphere_rotation) + { + Sphere_Rotate_Type *s = &g->sphere_xform; + for (i = 0; i < num; i++) + { + double lon1, lat1; + rotate_sphere (s, -1, RADIANS(lon[i]), RADIANS(lat[i]), &lon1, &lat1); + lon[i] = DEGREES(lon1); + lat[i] = DEGREES(lat1); + } + } + return 0; +} + +static int generic_project_f (void *vg, + float *lon, float *lat, + float *tx, float *ty, + unsigned int num) +{ + Generic_Projection_Type *g = (Generic_Projection_Type *)vg; + int (*project)(void *, double, double, double *, double *); + void *client_data; + double tx0 = g->tx0, ty0 = g->ty0; + double inv_txscale, inv_tyscale; + unsigned int i; + + client_data = g->client_data; + project = g->info->project; + if (project == NULL) + { + SLang_verror (SL_NOT_IMPLEMENTED, "Projection %s does not support projecting", g->name); + return -1; + } + + if (g->apply_sphere_rotation) + { + Sphere_Rotate_Type *s = &g->sphere_xform; + for (i = 0; i < num; i++) + { + double tx1, ty1; + rotate_sphere (s, 1, RADIANS(lon[i]), RADIANS(lat[i]), &tx1, &ty1); + tx[i] = DEGREES(tx1); + ty[i] = DEGREES(ty1); + } + lon = tx; + lat = ty; + } + + inv_txscale = 1.0/g->txscale; + inv_tyscale = 1.0/g->tyscale; + for (i = 0; i < num; i++) + { + double tx_i, ty_i; + double lon_i, lat_i; + + lon_i = RADIANS(lon[i]); + lat_i = RADIANS(lat[i]); + (void) (*project)(client_data, lon_i, lat_i, &tx_i, &ty_i); + tx[i] = tx0 + tx_i*inv_txscale; + ty[i] = ty0 + ty_i*inv_tyscale; + } + return 0; +} + + +static int generic_deproject_f (void *vg, + float *tx, float *ty, + float *lon, float *lat, + unsigned int num) +{ + Generic_Projection_Type *g = (Generic_Projection_Type *)vg; + int (*deproject)(void *, double, double, double *, double *); + void *client_data; + double tx0 = g->tx0, ty0 = g->ty0; + double txscale = g->txscale, tyscale = g->tyscale; + unsigned int i; + + client_data = g->client_data; + deproject = g->info->deproject; + if (deproject == NULL) + { + SLang_verror (SL_NOT_IMPLEMENTED, "Projection %s does not support deprojecting", g->name); + return -1; + } + + for (i = 0; i < num; i++) + { + double tx_i, ty_i; + double lon_i, lat_i; + + tx_i = (tx[i] - tx0) * txscale; + ty_i = (ty[i] - ty0) * tyscale; + (void) (*deproject)(client_data, tx_i, ty_i, &lon_i, &lat_i); + lon[i] = DEGREES(lon_i); + lat[i] = DEGREES(lat_i); + } + + if (g->apply_sphere_rotation) + { + Sphere_Rotate_Type *s = &g->sphere_xform; + for (i = 0; i < num; i++) + { + double lon1, lat1; + rotate_sphere (s, -1, RADIANS(lon[i]), RADIANS(lat[i]), &lon1, &lat1); + lon[i] = DEGREES(lon1); + lat[i] = DEGREES(lat1); + } + } + return 0; +} + +/*}}}*/ + +/* Intrinsic functions */ + +typedef struct Projection_Info_Type +{ + char *name; + int (*new_projection) (char *); + void *(*pop_projection) (char *); + void (*free_projection) (void *); + int (*project_fun_d) (void *, double *, double *, double *, double *, unsigned int); + int (*deproject_fun_d) (void *, double *, double *, double *, double *, unsigned int); + int (*reproject_fun_d) (void *, double *, double *, void *, double *, double *, unsigned int); + int (*project_fun_f) (void *, float *, float *, float *, float *, unsigned int); + int (*deproject_fun_f) (void *, float *, float *, float *, float *, unsigned int); + int (*reproject_fun_f) (void *, float *, float *, void *, float *, float *, unsigned int); +} +Projection_Info_Type; + +static Projection_Info_Type Projection_List[] = +{ + {"linear", + linear_new, linear_pop, linear_free, + linear_project_d, linear_deproject_d, NULL, + linear_project_f, linear_deproject_f, NULL, + }, + {"sphere", + sphere_new, sphere_pop, sphere_free, + sphere_project_d, sphere_deproject_d, NULL, + sphere_project_f, sphere_deproject_f, NULL, + }, + {"gnomic", + gnomic_new, gnomic_pop, gnomic_free, + gnomic_project_d, gnomic_deproject_d, gnomic_reproject_d, + gnomic_project_f, gnomic_deproject_f, gnomic_reproject_f + }, + {"plane", + plane_new, plane_pop, plane_free, + plane_project_d, plane_deproject_d, NULL, + plane_project_f, plane_deproject_f, NULL, + }, + {"ortho", + ortho_new, ortho_pop, ortho_free, + ortho_project_d, ortho_deproject_d, NULL, + ortho_project_f, ortho_deproject_f, NULL, + }, + {"stereo", + stereo_new, stereo_pop, stereo_free, + plane_project_d, plane_deproject_d, NULL, + plane_project_f, plane_deproject_f, NULL, + }, + {"lambert", + lambert_new, lambert_pop, lambert_free, + lambert_project_d, lambert_deproject_d, NULL, + lambert_project_f, lambert_deproject_f, NULL, + }, + {"hammer", + generic_new, generic_pop, generic_free, + generic_project_d, generic_deproject_d, NULL, + generic_project_f, generic_deproject_f, NULL, + }, + {"mercator", + generic_new, generic_pop, generic_free, + generic_project_d, generic_deproject_d, NULL, + generic_project_f, generic_deproject_f, NULL, + }, + {"azeqdist", + generic_new, generic_pop, generic_free, + generic_project_d, generic_deproject_d, NULL, + generic_project_f, generic_deproject_f, NULL, + }, + {"bonne", + generic_new, generic_pop, generic_free, + generic_project_d, generic_deproject_d, NULL, + generic_project_f, generic_deproject_f, NULL, + }, + {"sinusoidal", + generic_new, generic_pop, generic_free, + generic_project_d, generic_deproject_d, NULL, + generic_project_f, generic_deproject_f, NULL, + }, + { + NULL, + NULL, NULL, NULL, + NULL, NULL, NULL, + NULL, NULL, NULL + } +}; + +static void get_projections (void) +{ + SLang_Array_Type *at; + Projection_Info_Type *p; + int i, num; + char **names; + + num = 0; + p = Projection_List; + while (p->name != NULL) + { + num++; + p++; + } + + if (NULL == (at = SLang_create_array (SLANG_STRING_TYPE, 1, NULL, &num, 1))) + return; + + names = (char **) at->data; + p = Projection_List; + for (i = 0; i < num; i++) + { + if (NULL == (names[i] = SLang_create_slstring (p->name))) + { + SLang_free_array (at); + return; + } + p++; + } + (void) SLang_push_array (at, 1); +} + + +typedef struct +{ + Projection_Info_Type *pinfo; + void *projection_data; +} +Projection_Type; + +static Projection_Info_Type *lookup_projection (char *name) +{ + Projection_Info_Type *p; + + p = Projection_List; + while (p->name != NULL) + { + if ((p->name[0] == name[0]) + && (0 == strcmp (p->name, name))) + return p; + p++; + } + SLang_verror (SL_INVALID_PARM, "Projection %s is unknown or unsupported", name); + return NULL; +} + +static void project_new (char *name) +{ + Projection_Info_Type *pinfo; + + if (NULL == (pinfo = lookup_projection (name))) + return; + + (void) (*pinfo->new_projection)(name); +} + +typedef struct +{ + char *name; +} +Any_Projection_Type; + +static SLang_CStruct_Field_Type Any_Projection_Struct[] = +{ + MAKE_CSTRUCT_FIELD(Any_Projection_Type, name, "name", SLANG_STRING_TYPE, 0), + SLANG_END_CSTRUCT_TABLE +}; + +static int pop_projection (Projection_Info_Type **pinfop, + void **projection_datap) +{ + Any_Projection_Type p; + Projection_Info_Type *pinfo; + int ret; + + if (-1 == SLdup_n (1)) + return -1; + + if (-1 == SLang_pop_cstruct (&p, Any_Projection_Struct)) + return -1; + + if ((NULL == (pinfo = lookup_projection (p.name))) + || (NULL == (*projection_datap = (pinfo->pop_projection (p.name))))) + ret = -1; + else + ret = 0; + + SLang_free_cstruct (&p, Any_Projection_Struct); + *pinfop = pinfo; + return ret; +} + + +static int do_reprojection (Projection_Info_Type *pinfo_to, void *projection_data_to, + Projection_Info_Type *pinfo_from, void *projection_data_from, + SLang_Array_Type *at_xfrom, SLang_Array_Type *at_yfrom, + SLang_Array_Type *at_xto, SLang_Array_Type *at_yto) +{ + unsigned int num = at_xfrom->num_elements; + unsigned int i; +#define MAX_REPROJECT 1024 + + if (at_xfrom->data_type == SLANG_FLOAT_TYPE) + { + float *xa = (float *)at_xfrom->data; + float *ya = (float *)at_yfrom->data; + float *xb = (float *)at_xto->data; + float *yb = (float *)at_yto->data; + double tmpx[MAX_REPROJECT], tmpy[MAX_REPROJECT]; +#if 1 + if ((pinfo_to == pinfo_from) + && (pinfo_to->reproject_fun_f != NULL)) + return (*pinfo_to->reproject_fun_f)(projection_data_from, xa, ya, + projection_data_to, xb, yb, num); +#endif + i = 0; + while (i < num) + { + unsigned int j; + unsigned int dn = num - i; + if (dn > MAX_REPROJECT) + dn = MAX_REPROJECT; + + for (j = 0; j < dn; j++) + { + tmpx[j] = xa[j]; + tmpy[j] = ya[j]; + } + if (-1 == (*pinfo_from->deproject_fun_d)(projection_data_from, + tmpx, tmpy, tmpx, tmpy, + dn)) + return -1; + + if (-1 == (*pinfo_to->project_fun_d)(projection_data_to, + tmpx, tmpy, tmpx, tmpy, + dn)) + return -1; + + for (j = 0; j < dn; j++) + { + xb[j] = tmpx[j]; + yb[j] = tmpy[j]; + } + xa += dn; + xb += dn; + ya += dn; + yb += dn; + i += dn; + } + return 0; + } + else + { + + double *xa = (double *)at_xfrom->data; + double *ya = (double *)at_yfrom->data; + double *xb = (double *)at_xto->data; + double *yb = (double *)at_yto->data; + + if ((pinfo_to == pinfo_from) + && (pinfo_to->reproject_fun_d != NULL)) + return (*pinfo_to->reproject_fun_d)(projection_data_from, xa, ya, + projection_data_to, xb, yb, num); + + if (-1 == (*pinfo_from->deproject_fun_d)(projection_data_from, xa, ya, + xb, yb, num)) + return -1; + if (-1 == (*pinfo_to->project_fun_d)(projection_data_to, xb, yb, + xb, yb, num)) + return -1; + + return 0; + } +} + +static void project_intrin_internal (int direction) +{ + SLang_Array_Type *at_xfrom, *at_yfrom; + SLang_Array_Type *at_xto, *at_yto; + int is_scalar; + Projection_Info_Type *pinfo; + void *projection_data; + int (*fun_d) (void *, double *, double *, double *, double *, unsigned int); + int (*fun_f) (void *, float *, float *, float *, float *, unsigned int); + + if (-1 == pop_reusable_arrays (&at_xfrom, &at_yfrom, &at_xto, &at_yto, &is_scalar)) + return; + + if (-1 == pop_projection (&pinfo, &projection_data)) + { + SLang_free_array (at_yto); + SLang_free_array (at_xto); + SLang_free_array (at_yfrom); + SLang_free_array (at_xfrom); + return; + } + + if (direction == 0) + { + void *projection_data_to; + Projection_Info_Type *pinfo_to; + + if (-1 == pop_projection (&pinfo_to, &projection_data_to)) + goto free_return; + + if (-1 == do_reprojection (pinfo_to, projection_data_to, + pinfo, projection_data, + at_xfrom, at_yfrom, at_xto, at_yto)) + { + (*pinfo_to->free_projection)(projection_data_to); + goto free_return; + } + (*pinfo_to->free_projection)(projection_data_to); + } + else + { + if (direction == 1) + { + fun_d = pinfo->project_fun_d; + fun_f = pinfo->project_fun_f; + } + else + { + fun_d = pinfo->deproject_fun_d; + fun_f = pinfo->deproject_fun_f; + } + + if (at_xfrom->data_type == SLANG_FLOAT_TYPE) + { + if (-1 == (*fun_f)(projection_data, + (float*)at_xfrom->data, (float*)at_yfrom->data, + (float*)at_xto->data, (float*)at_yto->data, + at_xfrom->num_elements)) + goto free_return; + } + else + { + if (-1 == (*fun_d)(projection_data, + (double*)at_xfrom->data, (double*)at_yfrom->data, + (double*)at_xto->data, (double*)at_yto->data, + at_xfrom->num_elements)) + goto free_return; + } + } + + + (void) push_array_maybe_scalar (at_xto, is_scalar); + (void) push_array_maybe_scalar (at_yto, is_scalar); + + free_return: + + (*pinfo->free_projection)(projection_data); + + SLang_free_array (at_yto); + SLang_free_array (at_xto); + SLang_free_array (at_yfrom); + SLang_free_array (at_xfrom); +} + +static void project_intrin (void) +{ + if (SLang_Num_Function_Args != 3) + { + SLang_verror (SL_USAGE_ERROR, "Usage: (x,y)=maplib_project(map_info,lon,lat)"); + return; + } + project_intrin_internal (1); +} + +static void deproject_intrin (void) +{ + if (SLang_Num_Function_Args != 3) + { + SLang_verror (SL_USAGE_ERROR, "Usage: (x,y)=maplib_deproject(map_info,lon,lat)"); + return; + } + project_intrin_internal (-1); +} + +static void reproject_intrin (void) +{ + if (SLang_Num_Function_Args != 4) + { + SLang_verror (SL_USAGE_ERROR, "Usage: (x1,y1)=maplib_reproject(map_info1,map_info0,x0,y0)"); + return; + } + project_intrin_internal (0); +} + +static void rotate2d_d (double *x, double *y, unsigned int n, + double theta, double x_0, double y_0, + double *x_1, double *y_1) +{ + unsigned int i; + double c = cos (theta); + double s = sin (theta); + + for (i = 0; i < n; i++) + { + double x_i = x[i]-x_0; + double y_i = y[i]-y_0; + + x_1[i] = x_0 + c*x_i - s*y_i; + y_1[i] = y_0 + s*x_i + c*y_i; + } +} + +static void rotate2d_f (float *x, float *y, unsigned int n, + double theta, double x_0, double y_0, + float *x_1, float *y_1) +{ + unsigned int i; + double c = cos (theta); + double s = sin (theta); + + for (i = 0; i < n; i++) + { + double x_i = x[i]-x_0; + double y_i = y[i]-y_0; + + x_1[i] = x_0 + c*x_i - s*y_i; + y_1[i] = y_0 + s*x_i + c*y_i; + } +} + +static void rotate2d_intrin (void) +{ + double theta; + SLang_Array_Type *x, *y, *x_1, *y_1; + int is_scalar; + double x_0 = 0.0, y_0 = 0.0; + + if (SLang_Num_Function_Args == 5) + { + if (-1 == POP_DOUBLE (&y_0,NULL,NULL)) + return; + if (-1 == POP_DOUBLE (&x_0,NULL,NULL)) + return; + } + else if (SLang_Num_Function_Args != 3) + { + SLang_verror (SL_USAGE_ERROR, "Usage: (x1,y1)=maplib_rotate2d(x,y,theta_radians[,x0,y0])"); + return; + } + if (-1 == POP_DOUBLE (&theta, NULL, NULL)) + return; + + if (-1 == pop_reusable_arrays (&x, &y, &x_1, &y_1, &is_scalar)) + return; + + if (x->data_type == SLANG_FLOAT_TYPE) + rotate2d_f ((float *)x->data, (float *)y->data, x->num_elements, + theta, x_0, y_0, (float *)x_1->data, (float *)y_1->data); + else + rotate2d_d ((double *)x->data, (double *)y->data, x->num_elements, + theta, x_0, y_0, (double *)x_1->data, (double *)y_1->data); + + (void) push_array_maybe_scalar (x_1, is_scalar); + (void) push_array_maybe_scalar (y_1, is_scalar); + + SLang_free_array (y_1); + SLang_free_array (x_1); + SLang_free_array (y); + SLang_free_array (x); +} + + +static void meshgrid_intrin (void) +{ + SLang_Array_Type *at_x, *at_y, *at_xx, *at_yy; + int data_type; + int is_scalar; + int dims[2]; + unsigned int nx, ny; + + if (SLang_Num_Function_Args != 2) + { + SLang_verror (SL_USAGE_ERROR, "(X,Y)=maplib_meshgrid (x,y)"); + return; + } + + if (-1 == pop_2_floating_arrays_1 (&at_x, &at_y, &is_scalar)) + return; + + data_type = at_x->data_type; + nx = (unsigned int) at_x->num_elements; + ny = (unsigned int) at_y->num_elements; + dims[0] = (int) nx; + dims[1] = (int) ny; + + if (NULL == (at_xx = SLang_create_array (data_type, 0, NULL, dims, 2))) + { + SLang_free_array (at_y); + SLang_free_array (at_x); + return; + } + + if (NULL == (at_yy = SLang_create_array (data_type, 0, NULL, dims, 2))) + { + SLang_free_array (at_xx); + SLang_free_array (at_y); + SLang_free_array (at_x); + return; + } + + if (data_type == SLANG_FLOAT_TYPE) + { + float *x = (float *)at_x->data; + float *y = (float *)at_y->data; + float *xx = (float *)at_xx->data; + float *yy = (float *)at_yy->data; + unsigned int i, j; + + /* xx_ij = x_i; yy_ij = y_j */ + for (i = 0; i < nx; i++) + { + float x_i = x[i]; + for (j = 0; j < ny; j++) + { + xx[j] = x_i; + yy[j] = y[j]; + } + xx += ny; + yy += ny; + } + } + else + { + double *x = (double *)at_x->data; + double *y = (double *)at_y->data; + double *xx = (double *)at_xx->data; + double *yy = (double *)at_yy->data; + unsigned int i, j; + + /* xx_ij = x_i; yy_ij = y_j */ + for (i = 0; i < nx; i++) + { + double x_i = x[i]; + for (j = 0; j < ny; j++) + { + xx[j] = x_i; + yy[j] = y[j]; + } + xx += ny; + yy += ny; + } + } + + SLang_free_array (at_y); + SLang_free_array (at_x); + (void) SLang_push_array (at_xx, 1); + (void) SLang_push_array (at_yy, 1); +} + +static SLang_Intrin_Fun_Type Module_Intrinsics [] = +{ + MAKE_INTRINSIC_0 ("maplib_get_projections", get_projections, SLANG_VOID_TYPE), + MAKE_INTRINSIC_0 ("maplib_project", project_intrin, SLANG_VOID_TYPE), + MAKE_INTRINSIC_0 ("maplib_deproject", deproject_intrin, SLANG_VOID_TYPE), + MAKE_INTRINSIC_0 ("maplib_reproject", reproject_intrin, SLANG_VOID_TYPE), + MAKE_INTRINSIC_1 ("maplib_new", project_new, SLANG_VOID_TYPE, SLANG_STRING_TYPE), + MAKE_INTRINSIC_0 ("maplib_meshgrid", meshgrid_intrin, SLANG_VOID_TYPE), + MAKE_INTRINSIC_0 ("maplib_rotate2d", rotate2d_intrin, SLANG_VOID_TYPE), + + SLANG_END_INTRIN_FUN_TABLE +}; + +static SLang_Intrin_Var_Type Module_Variables [] = +{ + MAKE_VARIABLE("_maplib_module_version_string", &Module_Version_String, SLANG_STRING_TYPE, 1), + SLANG_END_INTRIN_VAR_TABLE +}; + +static SLang_IConstant_Type Module_IConstants [] = +{ + MAKE_ICONSTANT("_maplib_module_version", MODULE_VERSION_NUMBER), + SLANG_END_ICONST_TABLE +}; + + +int init_maplib_module_ns (char *ns_name) +{ + SLang_NameSpace_Type *ns = SLns_create_namespace (ns_name); + if (ns == NULL) + return -1; + + if ( + (-1 == SLns_add_intrin_var_table (ns, Module_Variables, NULL)) + || (-1 == SLns_add_intrin_fun_table (ns, Module_Intrinsics, NULL)) + || (-1 == SLns_add_iconstant_table (ns, Module_IConstants, NULL))) + return -1; + + /* Hack */ + Maplib_NaN = sqrt (-1.0); + + return 0; +} + +/* This function is optional */ +void deinit_maplib_module (void) +{ +} diff --git a/modules/maplib/src/maplib.sl b/modules/maplib/src/maplib.sl new file mode 100644 index 0000000..44eafee --- /dev/null +++ b/modules/maplib/src/maplib.sl @@ -0,0 +1,11 @@ +set_import_module_path (".:" + get_import_module_path ()); +#ifeval (_slang_version < 20000) +if (current_namespace () != "") + import ("maplib", current_namespace ()); +else +#endif + import ("maplib"); + +#ifexists provide +provide ("maplib"); +#endif diff --git a/modules/maplib/src/mkversion.sh b/modules/maplib/src/mkversion.sh new file mode 100755 index 0000000..bed2bb9 --- /dev/null +++ b/modules/maplib/src/mkversion.sh @@ -0,0 +1,4 @@ +#version 1.0 +# The initial echo is necessary because the solaris version of sed cannot +# grok input without a trailing newline. +echo `grep "^#define MODULE_[MP]" version.h | sed -e 's/[^0-9]*//' | tr '\012' .` | sed -e 's/.$//' diff --git a/modules/maplib/src/tests/test_maplib.sl b/modules/maplib/src/tests/test_maplib.sl new file mode 100644 index 0000000..bdfd359 --- /dev/null +++ b/modules/maplib/src/tests/test_maplib.sl @@ -0,0 +1,304 @@ +static variable MODULE_NAME = "maplib"; +prepend_to_slang_load_path ("."); +set_import_module_path (".:" + get_import_module_path ()); + +require (MODULE_NAME); + +% Useful functions +static define print (x) +{ + x = string (x); + () = fputs (x, stdout); + () = fflush (stdout); +} + +static define failed () +{ + variable s = __pop_args (_NARGS); + s = sprintf (__push_args(s)); + () = fprintf (stderr, "Failed: %s\n", s); + exit (1); +} + +static variable Random_Number = _time (); +static define urand_1 (x) +{ + Random_Number = typecast (Random_Number * 69069UL + 1013904243UL, UInt32_Type); + return Random_Number/4294967296.0; +} +static define urand (n) +{ + if (n == 0) + return Double_Type[0]; + + return array_map (Double_Type, &urand_1, [1:n]); +} + +vmessage ("testing %s routines\n", MODULE_NAME); +_debug_info = 1; + +% Regression tests go here + +% The idea behind these tests is that the specific cases will be compare +% to a more general projection with parameters set to mimick to specific +% case. + +static define generate_lon_lats (n, lon0, lat0, dlon, dlat) +{ + variable lon, lat; + + lon = dlon * (2.0*urand (n)-1.0); + lat = dlon * (2.0*urand (n)-1.0); + + variable m = maplib_new ("sphere"); + m.lon0 = 0; + m.lat0 = 0; + m.lon1 = lon0; + m.lat1 = lat0; + + (lon, lat) = maplib_project (m, lat, lon); + + variable i, j; + i = where (lon > 180.0); + lon[i] -= 360.0; + j = where (lon < -180); + lon[j] += 360.0; + if (length (i) or length (j)) + () = fprintf (stderr, "*** maplib_project sphere returned unnormalized lons\n"); + + i = where (lat > 90.0); + lat[i] = 180.0 - lat[i]; + j = where (lat < -90.0); + lat[j] = -180.0 - lat[j]; + if (length (i) or length (j)) + () = fprintf (stderr, "*** maplib_project sphere returned unnormalized lats\n"); + + return lon, lat; +} + +static define check_a_diff (x, x1, tol, lon, lat, axis, name, fun) +{ + % FIXME!! I need to device a better check here. The absolute difference + % is not meaningful for large numbers. + variable dx = abs(x-x1); + variable i = where (isnan(x) != isnan(x1)); + if (length (i)) + { + () = fprintf (stderr, "*** WARNING: NaN issue seen in by %s %s %d/%d times\n", + fun, name, length(i), length(x)); + i = i[0]; + () = fprintf (stderr, " first at (%g,%g)\n", lon[i], lat[i]); + } + i = (where (dx > tol)); + + if (0 == length(i)) + return; + + () = fprintf (stderr, "*** WARNING: %s tolerance for %s %s exceeded (%e>%g) %d/%d times\n", + axis, fun, name, max(dx), tol, length(i), length(x)); + i = wherefirst (max(dx) == dx); + () = fprintf (stderr, " %g vs %g at (%g,%g)\n", x[i], x1[i], lon[i], lat[i]); +} + +static define check_diffs (x, y, x1, y1, tol_x, tol_y, lon, lat, name, fun) +{ + check_a_diff (x, x1, tol_x, lon, lat, "X", name, fun); + check_a_diff (y, y1, tol_y, lon, lat, "Y", name, fun); +} + + +static define test_gnomic () +{ + variable g = maplib_new ("gnomic"); + variable p = maplib_new ("plane"); + p.lon0 = g.lon0; + p.lat0 = g.lat0; + p.p_lon = 0.0; + p.p_lat = 0.0; + p.p_len = 0.0; + + variable lat, lon; + (lon,lat) = generate_lon_lats (10000, p.lon0, p.lat0, 45, 45); + variable x,y,x1,y1; + + variable tol_x = 1e-12; + variable tol_y = 1e-12; + + loop (2) + { + (x,y) = maplib_project (p, lon, lat); + (x1,y1) = maplib_project (g, lon, lat); + check_diffs (x,y,x1,y1,tol_x,tol_y,lon,lat, "gnomic", "maplib_project"); + + lon = typecast(lon,Float_Type); + lat = typecast(lat,Float_Type); + } +} + +static define test_ortho () +{ + variable g = maplib_new ("ortho"); + variable p = maplib_new ("plane"); + + g.lon0 = 0; + g.lat0 = 0; + p.lon0 = g.lon0; + p.lat0 = g.lat0; + p.p_lat = p.lat0; + p.p_lon = p.lon0; +#iffalse + p.p_lon = 180 - p.lat0; + if (p.p_lon > 180.0) + p.p_lon -= 360.0; +#endif + p.p_len = 1e30; % Inf + + variable lat, lon; + (lon,lat) = generate_lon_lats (10000, p.lon0, p.lat0, 89, 89); + variable x,y,x1,y1; + + variable tol_x = 1e-12; + variable tol_y = 1e-12; + + % Note: tests involving floats instead of doubles will give errors + % because floats lack the necessary precision at larger angles. + loop (2) + { + (x,y) = maplib_project (g, lon, lat); + (x1,y1) = maplib_project (p, lon, lat); + check_diffs (x,y,x1,y1,tol_x,tol_y,lon,lat, "ortho", "maplib_project"); + + (x1, y1) = maplib_deproject (g, x, y); + check_diffs (lon, lat, x1, y1, tol_x, tol_y, lon, lat, "ortho", "maplib_deproject"); + +% (x1, y1) = maplib_project (g, typecast(lon,Float_Type), typecast(lat,Float_Type)); +% check_diffs (x, y, x1, y1, tol_x, tol_y, lon, lat, "ortho float vs double", "maplib_project"); + break; + + lon = typecast(lon,Float_Type); + lat = typecast(lat,Float_Type); + tol_x = 1e-5; + tol_y = 1e-5; + } +} + +static define test_stereo () +{ + variable g = maplib_new ("stereo"); + variable p = maplib_new ("plane"); + p.lon0 = g.lon0; + p.lat0 = g.lat0; + p.p_lat = -p.lat0; + p.p_lon = 180 - p.lon0; + if (p.p_lon > 180.0) + p.p_lon -= 360.0; + p.p_len = 1.0; + + variable lat, lon; + (lon,lat) = generate_lon_lats (10000, p.lon0, p.lat0, 45, 45); + variable x,y,x1,y1; + + variable tol_x = 1e-12; + variable tol_y = 1e-12; + + loop (2) + { + (x,y) = maplib_project (p, lon, lat); + (x1,y1) = maplib_project (g, lon, lat); + check_diffs (x,y,x1,y1,tol_x,tol_y,lon, lat, "stereo", "maplib_project"); + + lon = typecast(lon,Float_Type); + lat = typecast(lat,Float_Type); + } +} + +private define test_sphere () +{ + variable m = maplib_new ("sphere"); + variable lon0, lat0, lon1, lat1, lon, lat; + + (lon,lat) = generate_lon_lats (10000, 0, 0, 180, 90); + % Check unit transformation + foreach lon0 ([0, 90, 180, -180, -90]) + { + foreach lat0 ([90, 0, -90]) + { + m.lon0 = lon0; m.lat0 = lat0; + m.beta = 31; + m.lon1 = 45; m.lat1 = 45; + loop (2) + { + variable tol = 1e-12; + (lon1, lat1) = maplib_reproject (m, m, lon, lat); + check_diffs (lon,lat,lon1,lat1,tol,tol,lon,lat, "sphere", "maplib_reproject"); + lon = typecast (lon, Float_Type); + lat = typecast (lat, Float_Type); + tol = 1e-5; + } + } + } + + m.lon0 = 0; m.lat0 = 90; + m.lon1 = 90; m.lat1 = 90; + m.beta = 45; + (lon1, lat1) = maplib_project (m, 0, 90); + check_diffs (90+m.beta, 90, lon1, lat1, 1e-12, 1e-12, 0, 90, "sphere", "maplib_project"); +} + +static define test_plane () +{ + variable p = maplib_new ("plane"); + p.lon0 = 20; + p.lat0 = 30; + p.p_lon = 0; + p.p_lat = 0; + + variable lat, lon; + (lon,lat) = generate_lon_lats (10000, p.lon0, p.lat0, 19, 31); + foreach ([0, 0.5, 1, 100]) + { + p.p_len = (); + variable x,y,lon1,lat1; + + variable tol_x = 1e-12; + variable tol_y = 1e-12; + + (x,y) = maplib_project (p, lon, lat); + (lon1, lat1) = maplib_deproject (p, x, y); + check_diffs (lon,lat,lon1,lat1,tol_x,tol_y,lon,lat, "plane", + sprintf ("maplib_project/deproject@plen=%g",p.p_len)); + } +} + +define test_generic (name, lon0, lat0, dlon, dlat) +{ + variable m = maplib_new (name); + m.lon0 = lon0; + m.lat0 = lat0; + + variable lat, lon; + (lon,lat) = generate_lon_lats (10000, lon0, lat0, 180, 90); + + variable tol_x = 1e-12; + variable tol_y = 1e-12; + + variable lon1, lat1; + (lon1, lat1) = maplib_deproject (m, maplib_project (m, lon, lat)); + + check_diffs (lon,lat,lon1,lat1,tol_x,tol_y,lon,lat, m.name, + "maplib_project/deproject"); +} + +test_generic ("sinusoidal", 20, 0, 180, 90); +test_generic ("bonne", 20, 45, 180, 90); +test_generic ("mercator", 20, 45, 180, 89); + +test_plane (); +test_gnomic (); +test_ortho (); +test_stereo (); +test_sphere (); + +% End of regression tests +message ("Ok\n"); +exit (0); diff --git a/modules/maplib/src/version.h b/modules/maplib/src/version.h new file mode 100644 index 0000000..72b1b80 --- /dev/null +++ b/modules/maplib/src/version.h @@ -0,0 +1,10 @@ +#define MODULE_MAJOR_VERSION 0 +#define MODULE_MINOR_VERSION 3 +#define MODULE_PATCH_LEVEL 0 +#define MKSTR1(x) #x +#define MKSTR(x) MKSTR1(x) +static char *Module_Version_String = MKSTR(MODULE_MAJOR_VERSION) "." \ + MKSTR(MODULE_MINOR_VERSION) "." MKSTR(MODULE_PATCH_LEVEL); + +#define MODULE_VERSION_NUMBER \ + (MODULE_MAJOR_VERSION*10000+MODULE_MINOR_VERSION*100+MODULE_PATCH_LEVEL) diff --git a/modules/maplib/src/wcsfuns.sl b/modules/maplib/src/wcsfuns.sl new file mode 100644 index 0000000..50d5443 --- /dev/null +++ b/modules/maplib/src/wcsfuns.sl @@ -0,0 +1,429 @@ +% These routines perform FITS WCS transformations using maplib. +% Public routines: +% +% (x',y') = wcsfuns_project (wcs, x, y); % From WCS to image +% (x',y') = wcsfuns_deproject (wcs, x, y); % From image to WCS +% (x',y') = wcsfuns_reproject (wcs', wcs, x, y); % From image to image +% +% The wcs structure is assumed to be the same as given by the fitswcs. +% +% Author: John E. Davis +%--------------------------------------------------------------------------- + +$0 = 0; % Major +$1 = 2; % Minor +$2 = 1; % Patch-level + +public variable _wcsfuns_version = $0*10000 + $1*100 + $2; +public variable _wcsfuns_version_string = sprintf ("%d.%d.%d", $0, $1, $2); + +require ("maplib"); +require ("fitswcs"); +% Note: the fitswcs structure may not include the equinox and radsys +% fields. For this reason, check the version number of the fitswcs +% file. + +private define parse_ctype (ctype) +{ + ctype = strlow (ctype); + + variable sys, proj; + if (strlen (ctype) < 6) + return NULL, "linear"; + + if (ctype[4] != '-') + return NULL, "linear"; + + sys = strtrim_end (substr (ctype, 1, 4), "-"); + proj = strtrim_end (substr (ctype, 6, -1), "- "); + + return sys, proj; +} + +private define get_lon_lat_indices (sys_0, sys_1) +{ + variable lons = ["ra", "glon", "elon", "slon"]; + variable lats = ["dec", "glat", "elat", "slat"]; + % These correspond to + % RA/DEC: Equatorial + % ELON/ELAT: Ecliptic + % GLON/GLAT: Galactic + % SLON/SLAT: Supergalactic + _for (0, length (lons)-1, 1) + { + variable i = (); + variable lon_i = lons[i], lat_i = lats[i]; + if ((sys_0 == lon_i) and (sys_1 == lat_i)) + return 0, 1; + if ((sys_0 == lat_i) and (sys_1 == lon_i)) + return 1, 0; + } + vmessage ("*** Warning: Assuming %s and %s specify lon and lat coordinates, resp", + strup(sys_0), strup(sys_1)); + return 0, 1; +} + +% The FITSWCS-II paper defines the following conventions: +% +% The native system is the system where the coordinate mappings are +% defined. For example, the FITS azimuthal projections use a native +% system in which the (native) pole is located at the center of the +% projection. The native coordinates are denoted by (phi,theta) and +% the celestial ones by (alpha,delta). The location of the celestial +% pole is give by (phi_p,theta_p) in native coordinates. LATPOLEa and +% LONPOLEa keywords encode these values. The location of the native +% pole is given by (alpha_p, delta_p) in celestial coordinates. +% +% A fiducial point is defined with coordinates (phi_0,theta_0) and +% (alpha_0,delta_0) in the native and celestial systems, resp. The +% pair (alpha_0,delta_0) is given by CRVALia. And (PVi_1a,PVi_2a) +% give the corresponding native coordinates. +% +% For azimuthal projections, (alpha_0, theta_0) correspond to maplib's +% lon0 and lat0 parameters. +% +% In FITS parlance, (lon0,lat0) specifies the celestial coordinate of the +% native pole, assumed to be located at the center of the map (given by crpix). +% The FITSWCS-II paper denotes the native coordinate by (phi,theta), and the +% celestial coordinate by (alpha,delta). +% +% The CRVAL keywords give the fiducial celestial coordinates +% (alpha0,delta0). The associated native coordinate is given by +% (phi0,theta0). The azimuthal projections use (phi0,theta0)=(0,90). +% This means that for azimuthal projections, CRVAL provides the +% celestial coordinates of the native pole. +% +% The LONPOLEa keyword gives the native longitude of the celestial +% pole. It corresponds to beta in the "sphere" projection. Its +% default value is 0 for delta0>=theta0, and -180 otherwise. Recall +% that we can always rotate about the native pole. Specifying the +% longitude of the celestial pole fixes the rotation angle. For the +% azimuthal projections, maplib automatically chooses the correct +% implicit value for beta by the constraint that (xhat,yhat) have the +% same directions as (lonhat,lathat) at the fiducial point. +% +% FIXME!!! +% Non-default values of LONPOLEa will require a rotation of the +% tangent plane. +% +% +% +private define init_simple_azimuthal_proj (proj, wcs) +{ + variable m = maplib_new (proj); + m.lon0 = wcs.crval[0]; + m.lat0 = wcs.crval[1]; + m.x0 = wcs.crpix[0]; + m.y0 = wcs.crpix[1]; + m.xscale = wcs.cdelt[0]; + m.yscale = wcs.cdelt[1]; + + return m; +} + +% Fits-Name Maplib-Name Description Keywords +% AIT hammer Hammer-Aitoff +% STG stereo Stereographic +% TAN gnomic Gnomic +% ZEA lambert Lambert EA +% BON bonne Bonne EA PVi_1a +% SFL sinusoidal Sanson-Flamsteed +% MER mercator Mercator +% CAR linear Plate-Carree +% AZP plane* Zenithal PVi_1a, PVi_2a +% SZP plane* Slant Zenithal PVi_1a, PVi_2a, PVi_3a +% SIN plane* Slant Orthographic PVi_1a, PVi_2a +% ARC azeqdist Zenith EqDist +% ZPN Zenith Polynomial PVi_0a,...,PVi_20a +% AIR Airy PVi_1a +% CYP Cylinder Perspective PVi_1a +% CEA Cylinder EqArea PVi_1a +% PAR Parabolic +% MOL Mollweide +% COP Conic (Colles) +% COE Conic EqArea +% COD Conic EqDist +% COO Conic (Lambert) +% PCO Polyconic +% TSC Tang Sphr Cube +% CSC COBE Quad-Sphr Cube +% QSC Quad-Sphr Cube +% *Note: These are special cases of the "plane" projection. +% Note: PVi_0a, PVi_1a, and PVi_2a specify (theta0,phi0) +% PVi_3a = LONPOLEa, PVi_4a = LATPOLEa +% +private define init_tan_proj (proj, wcs) +{ + return init_simple_azimuthal_proj ("gnomic", wcs); +} +private define init_sin_proj (proj, wcs) +{ + return init_simple_azimuthal_proj ("ortho", wcs); +} + +private define init_stg_proj (proj, wcs) +{ + return init_simple_azimuthal_proj ("stereo", wcs); +} + +private define inverse_2x2 (a) +{ + variable a_00 = a[0,0], a_01 = a[0,1], a_10 = a[1,0], a_11 = a[1,1]; + variable det = (a_00*a_11 - a_01*a_10); + if (det == 0.0) + verror ("FITS wcs matrix has no inverse"); + a = Double_Type[2,2]; + a[0,0] = a_11; + a[0,1] = -a_01; + a[1,0] = -a_10; + a[1,1] = a_00; + return a/det; +} + +private define init_linear_proj (proj, wcs) +{ + variable m = maplib_new ("linear"); + + % In FITS parlance, projections take place from image planes to + % the WCS system, which is the reverse of how maplib defines the + % projections. Hence, use the inverse matrix here, and reverse x0<->x1. + m.x0 = wcs.crval[0]; + m.y0 = wcs.crval[1]; + m.x1 = wcs.crpix[0]; + m.y1 = wcs.crpix[1]; + + if (wcs.pc != NULL) + m.A = inverse_2x2 (wcs.pc); + + variable A = m.A; + variable cdelt = wcs.cdelt; + variable factor = 1.0/cdelt[0]; + A[0,0] *= factor; + A[0,1] *= factor; + factor = 1.0/cdelt[1]; + A[1,0] *= factor; + A[1,1] *= factor; + return m; +} + +private define init_unsupported_proj (proj, wcs) +{ + verror ("FITS WCS map %s is not supported\n", proj); +} + +static variable Fits_To_Maplib_Funs = Assoc_Type[Ref_Type, &init_unsupported_proj]; +Fits_To_Maplib_Funs["tan"] = &init_tan_proj; +Fits_To_Maplib_Funs["sin"] = &init_sin_proj; +Fits_To_Maplib_Funs["stg"] = &init_stg_proj; +Fits_To_Maplib_Funs["linear"] = &init_linear_proj; + +% This routine converts a FITS WCS specification to a maplib specification. +% FITS WCS defines a transformation from "image" coordinates X_j to, e.g., +% celestial coordinates, W_i via: +% +% Q_i = \sum_j D_i PC_ij (X_j - X0_j) +% W_i = F_i(Q_1, Q_2) +% +% where, generally speaking F_i are non-linear functions. The precise meaning +% of the FITS crval keywords depend upon the function F_i. Generally it appears +% that CRVAL_1 = F_1(0,0) and CRVAL_2 = F_2(0,0). In other words, the CRVALs +% may be regarded as the WCS value of the reference pixel. However, the FITS +% WCS documents do not force this interpretation. For this reason, the last +% step will be written as +% +% W_i = F_i(Q_1, Q_2; W0_1, W0_2) +% +% where the CRVALs have been represented by W0_i. +% +% The maplib projections from the tangent plane to the sphere are of the form +% +% U_i = D_i (X_i - X0_i) +% W_i = M_i(U_1, U_2, W0_1, W0_2) +% +% The maplib linear transformation is: +% +% W_i = W0_i + \sum_j R_ij (X_j-X0_j) +% +% Hence, the FITS WCS transformation will have to be written as two maplib +% transformations: A linear transformation followed by a maplib projection. +% The linear transformation is required only when PC_ij is not diagonal. +% +% Case 1: +% +% 1. F_i correspond to a linear transformation (ctypes are linear). +% +% Want: W_i = W0_i + D_i \sum_j PC_ij (X_j - X0_j) +% Use maplib linear: +% +% W_i = W0_i + \sum_j R_ij (X_j - X0_j) +% R_ij = D_i PC_ij +% +% 2. F_i correspond to a celestial mapping. +% 2a. PC_ij is present +% +% Want: +% Q_i = \sum_j D_i PC_ij (X_j - X0_j) +% W_i = F_i(Q_1, Q_2; W0_1, W0_2) +% +% Use: Maplib linear followed by Maplib projection +% +% Linear: U_i = 0 + \sum_j R_ij (X_j - X0_j) ; R_ij = D_i PC_ij +% Projection: W_i = M_i(U_1, U_2, W0_1, W0_2) +% +% 2b. PC_ij is not present +% +% Want: Q_i = D_i (X_i - X0_i) +% W_i = F_i(Q_1, Q_2, W0_1, W0_2) +% +% Use single maplib projection. +% +% Finally note that the matrix for linear transformations should be specified +% as the inverse of PC_ij. This is because FITS defines "projection" as being +% from the tangent plane to the WCS, whereas maplib treats it the other way. +define wcsfuns_fitswcs_to_maplib () +{ + variable wcs, flipped_ref; + + if (_NARGS != 2) + usage ("(m1, m2)=%s(wcs_struct, flipped_ref); %% if m2 is non-NULL apply it after m1 for maplib_project", _function_name()); + + (wcs, flipped_ref) = (); + @flipped_ref = 0; + + if (wcs.naxis != 2) + verror ("%s: This interface currently supports only 2d maps", _function_name()); + + variable m1, m2; + + % First use the FITS ctype to determine the projection. + % The convention regarding the fits ctype is as follows: + % + % If the ctypes are not in the so-called 4-3 format, then the projection + % is linear. Otherwise, the name contains the coordinate system and + % projection + variable sys_x, proj_x, sys_y, proj_y; + variable ctype_x = wcs.ctype[0]; + variable ctype_y = wcs.ctype[1]; + + (sys_x, proj_x) = parse_ctype (ctype_x); + (sys_y, proj_y) = parse_ctype (ctype_y); + + if (proj_x != proj_y) + verror ("%s: ctypes %s and %s are not compatible", _function_name(), ctype_x, ctype_y); + + if (proj_x != "linear") + { + variable lon_index = 0, lat_index = 1; + (lon_index, lat_index) = get_lon_lat_indices (sys_x, sys_y); + if (lon_index == 1) + { + % Flip the wcs + wcs = fitswcs_slice (wcs, [lon_index, lat_index]); + (sys_x, sys_y) = (sys_y, sys_x); + (proj_x, proj_y) = (proj_y, proj_x); + @flipped_ref = 1; + } + } + + m2 = NULL; + if ((proj_x != "linear") + and (wcs.pc != NULL)) + { + m2 = maplib_new ("linear"); + m2.x1 = wcs.crpix[0]; + m2.y1 = wcs.crpix[1]; + m2.x0 = 0.0; + m2.y0 = 0.0; + m2.A = inverse_2x2 (wcs.pc); + %m2.A = @wcs.pc; + + % Adjust the WCS to conform to m2. + wcs = @wcs; + wcs.crpix = @wcs.crpix; + wcs.crpix[0] = 0; + wcs.crpix[1] = 0; + wcs.pc = NULL; + } + + m1 = (@Fits_To_Maplib_Funs[proj_x])(proj_x, wcs); + + return m1, m2; +} + +private define maplib_xxxproject_helper (calling_func_name, nargs) +{ + variable wcs, x, y; + + if (nargs != 3) + usage ("(x1,y1)=%s(wcs_struct,x,y)", calling_func_name); + + (wcs, x, y) = (); + + if (wcs.naxis != 2) + verror ("%s: This interface currently supports only 2d maps", calling_func_name); + + variable m1, m2, flipped; + (m1, m2) = wcsfuns_fitswcs_to_maplib (wcs, &flipped); + return m1, m2, x, y, flipped; +} + +define wcsfuns_project () +{ + variable m1, m2, x, y, flipped; + + (m1, m2, x, y, flipped) = maplib_xxxproject_helper (_function_name(), _NARGS); + + (x,y) = maplib_project (m1, __tmp(x), __tmp(y)); + if (m2 != NULL) + (x,y) = maplib_project (m2, __tmp(x), __tmp(y)); + + if (flipped) + return y, x; + + return x, y; +} + +define wcsfuns_deproject () +{ + variable m1, m2, x, y, flipped; + (m1, m2, x, y, flipped) = maplib_xxxproject_helper (_function_name(), _NARGS); + + if (flipped) + (x,y) = (y,x); + + if (m2 != NULL) + (x,y) = maplib_deproject (m2, __tmp(x), __tmp(y)); + + (x,y) = maplib_deproject (m1, __tmp(x), __tmp(y)); + return x, y; +} + +define wcsfuns_reproject () +{ + variable wcs_from, wcs_to, x, y; + + if (_NARGS != 4) + usage ("(x1,y1)=%s(wcs_to, wcs_from, x, y)", _function_name()); + + (wcs_to, wcs_from, x, y) = (); + + variable m1_from, m2_from, m1_to, m2_to, flipped_from, flipped_to; + + (m1_from, m2_from) = wcsfuns_fitswcs_to_maplib (wcs_from, &flipped_from); + (m1_to, m2_to) = wcsfuns_fitswcs_to_maplib (wcs_to, &flipped_to); + + if (flipped_from) (x,y) = (y,x); + + if (m2_from != NULL) + (x,y) = maplib_deproject (m2_from, __tmp(x), __tmp(y)); + + (x, y) = maplib_reproject (m1_to, m1_from, __tmp(x), __tmp(y)); + + if (m2_to != NULL) + (x, y) = maplib_project (m2_to, __tmp(x), __tmp(y)); + + if (flipped_to) return y,x; + return x, y; +} + +provide ("wcsfuns"); diff --git a/modules/pgplot/COPYRIGHT b/modules/pgplot/COPYRIGHT new file mode 100644 index 0000000..3efe62b --- /dev/null +++ b/modules/pgplot/COPYRIGHT @@ -0,0 +1,24 @@ + Copyright (c) 2003 Massachusetts Institute of Technology + + This software was developed by the MIT Center for Space Research + under contract SV1-61010 from the Smithsonian Institution. + + Permission to use, copy, modify, distribute, and sell this software + and its documentation for any purpose is hereby granted without fee, + provided that the above copyright notice appear in all copies and + that both that copyright notice and this permission notice appear in + the supporting documentation, and that the name of the Massachusetts + Institute of Technology not be used in advertising or publicity + pertaining to distribution of the software without specific, written + prior permission. The Massachusetts Institute of Technology makes + no representations about the suitability of this software for any + purpose. It is provided "as is" without express or implied warranty. + + THE MASSACHUSETTS INSTITUTE OF TECHNOLOGY DISCLAIMS ALL WARRANTIES + WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE MASSACHUSETTS + INSTITUTE OF TECHNOLOGY BE LIABLE FOR ANY SPECIAL, INDIRECT OR + CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS + OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, + NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION + WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. diff --git a/modules/pgplot/INSTALL.txt b/modules/pgplot/INSTALL.txt new file mode 100644 index 0000000..a2c8722 --- /dev/null +++ b/modules/pgplot/INSTALL.txt @@ -0,0 +1,181 @@ +Basic Installation +================== + + These are generic installation instructions. + + 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, a file +`config.cache' that saves the results of its tests to speed up +reconfiguring, and a file `config.log' containing compiler output +(useful mainly for debugging `configure'). + + 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 at some point `config.cache' +contains results you don't want to keep, you may remove or edit it. + + The file `configure.in' is used to create `configure' by a program +called `autoconf'. You only need `configure.in' 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. If you're + using `csh' on an old version of System V, you might need to type + `sh ./configure' instead to prevent `csh' from trying to execute + `configure' itself. + + Running `configure' takes awhile. 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. + + 4. Type `make install' to install the programs and any data files and + documentation. + + 5. 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. + +Compilers and Options +===================== + + Some systems require unusual options for compilation or linking that +the `configure' script does not know about. You can give `configure' +initial values for variables by setting them in the environment. Using +a Bourne-compatible shell, you can do that on the command line like +this: + CC=c89 CFLAGS=-O2 LIBS=-lposix ./configure + +Or on systems that have the `env' program, you can do it like this: + env CPPFLAGS=-I/usr/local/include LDFLAGS=-s ./configure + +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 must use a version of `make' that +supports the `VPATH' variable, such as 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 `..'. + + If you have to use a `make' that does not supports the `VPATH' +variable, you have 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. + +Installation Names +================== + + By default, `make install' will install the package's files in +`/usr/local/bin', `/usr/local/man', etc. You can specify an +installation prefix other than `/usr/local' by giving `configure' the +option `--prefix=PATH'. + + You can specify separate installation prefixes for +architecture-specific files and architecture-independent files. If you +give `configure' the option `--exec-prefix=PATH', the package will use +PATH as the prefix for installing programs and libraries. +Documentation and other data files will still use the regular prefix. + + In addition, if you use an unusual directory layout you can give +options like `--bindir=PATH' 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. + + 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'. + +Optional Features +================= + + 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. + +Specifying the System Type +========================== + + There may be some features `configure' can not figure out +automatically, but needs to determine by the type of host the package +will run on. Usually `configure' can figure that out, but if it prints +a message saying it can not guess the host type, give it the +`--host=TYPE' option. TYPE can either be a short name for the system +type, such as `sun4', or a canonical name with three fields: + CPU-COMPANY-SYSTEM + +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 host type. + + If you are building compiler tools for cross-compiling, you can also +use the `--target=TYPE' option to select the type of system they will +produce code for and the `--build=TYPE' option to select the type of +system on which you are compiling the package. + +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. + +Operation Controls +================== + + `configure' recognizes the following options to control how it +operates. + +`--cache-file=FILE' + Use and save the results of the tests in FILE instead of + `./config.cache'. Set FILE to `/dev/null' to disable caching, for + debugging `configure'. + +`--help' + Print a summary of the options to `configure', and exit. + +`--quiet' +`--silent' +`-q' + Do not print messages saying which checks are being made. + +`--srcdir=DIR' + Look for the package's source code in directory DIR. Usually + `configure' can determine that directory automatically. + +`--version' + Print the version of Autoconf used to generate the `configure' + script, and exit. + +`configure' also accepts some other, not widely useful, options. + diff --git a/modules/pgplot/README b/modules/pgplot/README new file mode 100644 index 0000000..5abc61d --- /dev/null +++ b/modules/pgplot/README @@ -0,0 +1,58 @@ +!!!! Replace