Commit b2388ce8e1c08abe3aec886799270abe2b3b5915
Merge branch 'integration' into devel
Showing
6 changed files
with
240 additions
and
142 deletions
ChangeLog
| ... | ... | @@ -4,6 +4,14 @@ |
| 4 | 4 | ======================== |
| 5 | 5 | |
| 6 | 6 | |
| 7 | +2019-06-25 | |
| 8 | + | |
| 9 | + * Bug fix version 1.6.2 released | |
| 10 | + ================================ | |
| 11 | + | |
| 12 | + Fix OpenMP issue in ctbin when using energy bounds from file (#2912) | |
| 13 | + | |
| 14 | + | |
| 7 | 15 | 2019-06-05 |
| 8 | 16 | |
| 9 | 17 | * Bug fix version 1.6.1 released | ... | ... |
README.md
| 1 | 1 | ctools information |
| 2 | 2 | ================== |
| 3 | 3 | * Version: 1.7.0.dev (29 May 2019) |
| 4 | -* Author: Juergen Knoedlseder (jurgen.knodlseder@irap.omp.eu) | |
| 5 | 4 | * GammaLib dependency: 1.7.0.dev |
| 6 | 5 | |
| 7 | 6 | [](https://cta-jenkins.irap.omp.eu/job/ctools-integrate-os/) | ... | ... |
configure.ac
| 1 | 1 | ############################################################################# |
| 2 | 2 | # Configuration for ctools - tools for science analysis of CTA data # |
| 3 | 3 | # ------------------------------------------------------------------------- # |
| 4 | -# Copyright (C) 2011-2018 Juergen Knoedlseder # | |
| 4 | +# Copyright (C) 2011-2019 Juergen Knoedlseder # | |
| 5 | 5 | # ------------------------------------------------------------------------- # |
| 6 | 6 | # # |
| 7 | 7 | # This program is free software: you can redistribute it and/or modify # | ... | ... |
doc/source/admin/release_history/1.6.2.rst
0 → 100644
| 1 | +.. _1.6.2: | |
| 2 | + | |
| 3 | +ctools 1.6.2 release (25 June 2019) | |
| 4 | +=================================== | |
| 5 | + | |
| 6 | +Overview | |
| 7 | +-------- | |
| 8 | + | |
| 9 | +ctools 1.6.2 is a bug fix release for ctools release 1.6. | |
| 10 | + | |
| 11 | +The following bugs were fixed: | |
| 12 | + | |
| 13 | +* [`2912 <https://cta-redmine.irap.omp.eu/issues/2912>`_] - | |
| 14 | + Fix OpenMP issue in ctbin when using energy bounds from file | ... | ... |
doc/source/admin/release_history/index.rst
src/support/ctool.cpp
| ... | ... | @@ -586,70 +586,105 @@ GEbounds ctool::create_ebounds(void) |
| 586 | 586 | // Get filename |
| 587 | 587 | GFilename ebinfile = (*this)["ebinfile"].filename(); |
| 588 | 588 | |
| 589 | - // If no extension name was provided then use default extension names | |
| 590 | - if (!ebinfile.has_extname()) { | |
| 591 | - | |
| 592 | - // Open energy boundary file using the EBOUNDS or ENERGYBINS | |
| 593 | - // extension or energy values using the ENERGIES extension. | |
| 594 | - // Throw an exception if opening fails. | |
| 595 | - GFits file(ebinfile.url()); | |
| 596 | - if (file.contains(gammalib::extname_ebounds)) { | |
| 597 | - file.close(); | |
| 598 | - ebounds.load(ebinfile); | |
| 599 | - } | |
| 600 | - else if (file.contains("ENERGYBINS")) { | |
| 601 | - file.close(); | |
| 602 | - ebinfile = ebinfile.url() + "[ENERGYBINS]"; | |
| 603 | - ebounds.load(ebinfile); | |
| 604 | - } | |
| 605 | - else if (file.contains(gammalib::extname_energies)) { | |
| 606 | - file.close(); | |
| 607 | - ebounds.set(GEnergies(ebinfile)); | |
| 608 | - } | |
| 609 | - else { | |
| 610 | - file.close(); | |
| 611 | - std::string msg = "No extension with name \""+ | |
| 612 | - gammalib::extname_ebounds+"\", " | |
| 613 | - "\"ENERGYBINS\" or \""+ | |
| 614 | - gammalib::extname_energies+"\" found in FITS " | |
| 615 | - "file \""+ebinfile+"\". Please specify a " | |
| 616 | - "valid energy binning file."; | |
| 617 | - throw GException::invalid_value(G_CREATE_EBOUNDS, msg); | |
| 618 | - } | |
| 619 | - } | |
| 589 | + // Initialise exception message string | |
| 590 | + std::string msg; | |
| 591 | + | |
| 592 | + // Make loading of energy boundaries OpenMP thread save. The critical | |
| 593 | + // region is put into an exception block to prevent throwing exceptions | |
| 594 | + // within the critical block | |
| 595 | + #pragma omp critical(ctool_create_ebounds) | |
| 596 | + { | |
| 597 | + try { | |
| 620 | 598 | |
| 621 | - // ... otherwise load energy boundaries from filename including | |
| 622 | - // extension | |
| 623 | - else { | |
| 599 | + // If no extension name was provided then use default extension | |
| 600 | + // names | |
| 601 | + if (!ebinfile.has_extname()) { | |
| 602 | + | |
| 603 | + // Open energy boundary file using the EBOUNDS or ENERGYBINS | |
| 604 | + // extension or energy values using the ENERGIES extension. | |
| 605 | + // If opening fails then set exception message. The | |
| 606 | + // exception is thrown later outside the critical OpenMP | |
| 607 | + // block. | |
| 608 | + GFits file(ebinfile.url()); | |
| 609 | + if (file.contains(gammalib::extname_ebounds)) { | |
| 610 | + file.close(); | |
| 611 | + ebounds.load(ebinfile); | |
| 612 | + } | |
| 613 | + else if (file.contains("ENERGYBINS")) { | |
| 614 | + file.close(); | |
| 615 | + ebinfile = ebinfile.url() + "[ENERGYBINS]"; | |
| 616 | + ebounds.load(ebinfile); | |
| 617 | + } | |
| 618 | + else if (file.contains(gammalib::extname_energies)) { | |
| 619 | + file.close(); | |
| 620 | + ebounds.set(GEnergies(ebinfile)); | |
| 621 | + } | |
| 622 | + else { | |
| 623 | + file.close(); | |
| 624 | + msg = "No extension with name \""+ | |
| 625 | + gammalib::extname_ebounds+"\", " | |
| 626 | + "\"ENERGYBINS\" or \""+ | |
| 627 | + gammalib::extname_energies+"\" found in FITS " | |
| 628 | + "file \""+ebinfile+"\". Please specify a " | |
| 629 | + "valid energy binning file."; | |
| 630 | + } | |
| 624 | 631 | |
| 625 | - // Open energy boundary file | |
| 626 | - GFits file(ebinfile.url()); | |
| 627 | - | |
| 628 | - // If FITS file does not contain requested extension then throw | |
| 629 | - // an exception | |
| 630 | - if (!file.contains(ebinfile.extname())) { | |
| 631 | - std::string msg = "No extension \""+ebinfile.extname()+"\" " | |
| 632 | - "found in energy binning file \""+ | |
| 633 | - ebinfile.url()+"\". Please provide a valid " | |
| 634 | - "extension name."; | |
| 635 | - throw GException::invalid_value(G_CREATE_EBOUNDS, msg); | |
| 636 | - } | |
| 632 | + } // endif: no extension name specified | |
| 637 | 633 | |
| 638 | - // Get table extension | |
| 639 | - GFitsTable& table = *file.table(ebinfile.extname()); | |
| 634 | + // ... otherwise load energy boundaries from filename including | |
| 635 | + // extension | |
| 636 | + else { | |
| 640 | 637 | |
| 641 | - // If table contains one column then load energies, otherwise load | |
| 642 | - // energy boundaries. | |
| 643 | - if (table.ncols() == 1) { | |
| 644 | - file.close(); | |
| 645 | - ebounds.set(GEnergies(ebinfile)); | |
| 646 | - } | |
| 647 | - else { | |
| 648 | - file.close(); | |
| 649 | - ebounds.load(ebinfile); | |
| 638 | + // Open energy boundary file | |
| 639 | + GFits file(ebinfile.url()); | |
| 640 | + | |
| 641 | + // If FITS file does not contain requested extension then | |
| 642 | + // set exception message. The exception is thrown later | |
| 643 | + // outside the critical OpenMP zone | |
| 644 | + if (!file.contains(ebinfile.extname())) { | |
| 645 | + msg = "No extension \""+ebinfile.extname()+"\" " | |
| 646 | + "found in energy binning file \""+ | |
| 647 | + ebinfile.url()+"\". Please provide a valid " | |
| 648 | + "extension name."; | |
| 649 | + } | |
| 650 | + | |
| 651 | + // ... otherwise load energy boundaries | |
| 652 | + else { | |
| 653 | + | |
| 654 | + // Get table extension | |
| 655 | + GFitsTable& table = *file.table(ebinfile.extname()); | |
| 656 | + | |
| 657 | + // If table contains one column then load energies, | |
| 658 | + // otherwise load energy boundaries. | |
| 659 | + if (table.ncols() == 1) { | |
| 660 | + file.close(); | |
| 661 | + ebounds.set(GEnergies(ebinfile)); | |
| 662 | + } | |
| 663 | + else { | |
| 664 | + file.close(); | |
| 665 | + ebounds.load(ebinfile); | |
| 666 | + } | |
| 667 | + | |
| 668 | + } // endelse: extension name was present in FITS file | |
| 669 | + | |
| 670 | + } // endelse: loaded energy boundaries from table extension | |
| 671 | + | |
| 672 | + } // endtry | |
| 673 | + | |
| 674 | + // Catch any exceptions that occured in OpenMP critical block | |
| 675 | + // and recover the error message | |
| 676 | + catch (const std::exception& e) { | |
| 677 | + msg = e.what(); | |
| 650 | 678 | } |
| 651 | 679 | |
| 652 | - } // endelse: loaded energy boundaries from table extension | |
| 680 | + } // end critical OpenMP block | |
| 681 | + | |
| 682 | + // If we have an exception message then throw an exception now. We | |
| 683 | + // have to do this since we should not throw exceptions inside OpenMP | |
| 684 | + // critical blocks | |
| 685 | + if (!msg.empty()) { | |
| 686 | + throw GException::invalid_value(G_CREATE_EBOUNDS, msg); | |
| 687 | + } | |
| 653 | 688 | |
| 654 | 689 | } // endif: ebinalg was "FILE" |
| 655 | 690 | |
| ... | ... | @@ -717,70 +752,105 @@ GEnergies ctool::create_energies(void) |
| 717 | 752 | // Get filename |
| 718 | 753 | GFilename ebinfile = (*this)["ebinfile"].filename(); |
| 719 | 754 | |
| 720 | - // If no extension name was provided then use default extension names | |
| 721 | - if (!ebinfile.has_extname()) { | |
| 755 | + // Initialise exception message string | |
| 756 | + std::string msg; | |
| 722 | 757 | |
| 723 | - // Open energy boundary file using the EBOUNDS or ENERGYBINS | |
| 724 | - // extension or energy values using the ENERGIES extension. | |
| 725 | - // Throw an exception if opening fails. | |
| 726 | - GFits file(ebinfile.url()); | |
| 727 | - if (file.contains(gammalib::extname_energies)) { | |
| 728 | - file.close(); | |
| 729 | - energies.load(ebinfile); | |
| 730 | - } | |
| 731 | - else if (file.contains(gammalib::extname_ebounds)) { | |
| 732 | - file.close(); | |
| 733 | - energies.set(GEbounds(ebinfile)); | |
| 734 | - } | |
| 735 | - else if (file.contains("ENERGYBINS")) { | |
| 736 | - file.close(); | |
| 737 | - ebinfile = ebinfile.url() + "[ENERGYBINS]"; | |
| 738 | - energies.set(GEbounds(ebinfile)); | |
| 739 | - } | |
| 740 | - else { | |
| 741 | - file.close(); | |
| 742 | - std::string msg = "No extension with name \""+ | |
| 743 | - gammalib::extname_energies+"\", " | |
| 744 | - "\"ENERGYBINS\" or \""+ | |
| 745 | - gammalib::extname_ebounds+"\" found in FITS " | |
| 746 | - "file \""+ebinfile+"\". Please specify a " | |
| 747 | - "valid energy binning file."; | |
| 748 | - throw GException::invalid_value(G_CREATE_ENERGIES, msg); | |
| 749 | - } | |
| 750 | - } | |
| 758 | + // Make loading of energies OpenMP thread save. The critical region is | |
| 759 | + // put into an exception block to prevent throwing exceptions within | |
| 760 | + // the critical block | |
| 761 | + #pragma omp critical(ctool_create_energies) | |
| 762 | + { | |
| 763 | + try { | |
| 751 | 764 | |
| 752 | - // ... otherwise load energy boundaries from filename including | |
| 753 | - // extension | |
| 754 | - else { | |
| 765 | + // If no extension name was provided then use default extension | |
| 766 | + // names | |
| 767 | + if (!ebinfile.has_extname()) { | |
| 768 | + | |
| 769 | + // Open energy boundary file using the EBOUNDS or ENERGYBINS | |
| 770 | + // extension or energy values using the ENERGIES extension. | |
| 771 | + // If opening fails then set exception message. The | |
| 772 | + // exception is thrown later outside the critical OpenMP | |
| 773 | + // block. | |
| 774 | + GFits file(ebinfile.url()); | |
| 775 | + if (file.contains(gammalib::extname_energies)) { | |
| 776 | + file.close(); | |
| 777 | + energies.load(ebinfile); | |
| 778 | + } | |
| 779 | + else if (file.contains(gammalib::extname_ebounds)) { | |
| 780 | + file.close(); | |
| 781 | + energies.set(GEbounds(ebinfile)); | |
| 782 | + } | |
| 783 | + else if (file.contains("ENERGYBINS")) { | |
| 784 | + file.close(); | |
| 785 | + ebinfile = ebinfile.url() + "[ENERGYBINS]"; | |
| 786 | + energies.set(GEbounds(ebinfile)); | |
| 787 | + } | |
| 788 | + else { | |
| 789 | + file.close(); | |
| 790 | + msg = "No extension with name \""+ | |
| 791 | + gammalib::extname_energies+"\", " | |
| 792 | + "\"ENERGYBINS\" or \""+ | |
| 793 | + gammalib::extname_ebounds+"\" found in FITS " | |
| 794 | + "file \""+ebinfile+"\". Please specify a " | |
| 795 | + "valid energy binning file."; | |
| 796 | + } | |
| 755 | 797 | |
| 756 | - // Open energy boundary file | |
| 757 | - GFits file(ebinfile.url()); | |
| 758 | - | |
| 759 | - // If FITS file does not contain requested extension then throw | |
| 760 | - // an exception | |
| 761 | - if (!file.contains(ebinfile.extname())) { | |
| 762 | - std::string msg = "No extension \""+ebinfile.extname()+"\" " | |
| 763 | - "found in energy node file \""+ | |
| 764 | - ebinfile.url()+"\". Please provide a valid " | |
| 765 | - "extension name."; | |
| 766 | - throw GException::invalid_value(G_CREATE_ENERGIES, msg); | |
| 767 | - } | |
| 798 | + } | |
| 768 | 799 | |
| 769 | - // Get table extension | |
| 770 | - GFitsTable& table = *file.table(ebinfile.extname()); | |
| 800 | + // ... otherwise load energy boundaries from filename including | |
| 801 | + // extension | |
| 802 | + else { | |
| 771 | 803 | |
| 772 | - // If table contains one column then load energies, otherwise | |
| 773 | - // load energy boundaries. | |
| 774 | - if (table.ncols() == 1) { | |
| 775 | - file.close(); | |
| 776 | - energies.load(ebinfile); | |
| 777 | - } | |
| 778 | - else { | |
| 779 | - file.close(); | |
| 780 | - energies.set(GEbounds(ebinfile)); | |
| 804 | + // Open energy boundary file | |
| 805 | + GFits file(ebinfile.url()); | |
| 806 | + | |
| 807 | + // If FITS file does not contain requested extension then | |
| 808 | + // set exception message. The exception is thrown later | |
| 809 | + // outside the critical OpenMP zone | |
| 810 | + if (!file.contains(ebinfile.extname())) { | |
| 811 | + msg = "No extension \""+ebinfile.extname()+"\" " | |
| 812 | + "found in energy node file \""+ | |
| 813 | + ebinfile.url()+"\". Please provide a valid " | |
| 814 | + "extension name."; | |
| 815 | + } | |
| 816 | + | |
| 817 | + // ... otherwise load energies | |
| 818 | + else { | |
| 819 | + | |
| 820 | + // Get table extension | |
| 821 | + GFitsTable& table = *file.table(ebinfile.extname()); | |
| 822 | + | |
| 823 | + // If table contains one column then load energies, | |
| 824 | + // otherwise load energy boundaries. | |
| 825 | + if (table.ncols() == 1) { | |
| 826 | + file.close(); | |
| 827 | + energies.load(ebinfile); | |
| 828 | + } | |
| 829 | + else { | |
| 830 | + file.close(); | |
| 831 | + energies.set(GEbounds(ebinfile)); | |
| 832 | + } | |
| 833 | + | |
| 834 | + } // endelse: extension name was present in FITS file | |
| 835 | + | |
| 836 | + } // endelse: loaded energies from table extension | |
| 837 | + | |
| 838 | + } // endtry | |
| 839 | + | |
| 840 | + // Catch any exceptions that occured in OpenMP critical block | |
| 841 | + // and recover the error message | |
| 842 | + catch (const std::exception& e) { | |
| 843 | + msg = e.what(); | |
| 781 | 844 | } |
| 782 | 845 | |
| 783 | - } // endelse: loaded energy boundaries from table extension | |
| 846 | + } // end critical OpenMP block | |
| 847 | + | |
| 848 | + // If we have an exception message then throw an exception now. We | |
| 849 | + // have to do this since we should not throw exceptions inside OpenMP | |
| 850 | + // critical blocks | |
| 851 | + if (!msg.empty()) { | |
| 852 | + throw GException::invalid_value(G_CREATE_ENERGIES, msg); | |
| 853 | + } | |
| 784 | 854 | |
| 785 | 855 | } // endif: ebinalg was "FILE" |
| 786 | 856 | |
| ... | ... | @@ -2203,34 +2273,40 @@ void ctool::save_event_list(const GCTAObservation* obs, |
| 2203 | 2273 | } |
| 2204 | 2274 | } |
| 2205 | 2275 | |
| 2206 | - // Create output FITS file | |
| 2207 | - GFits outfits; | |
| 2208 | - | |
| 2209 | - // Write observation into FITS file | |
| 2210 | - obs->write(outfits, outevt, outgti); | |
| 2211 | - | |
| 2212 | - // Copy all extensions other than evtname and gtiname extensions | |
| 2213 | - // from the input to the output event list. The evtname and | |
| 2214 | - // gtiname extensions are written by the save method, all others | |
| 2215 | - // that may eventually be present have to be copied over | |
| 2216 | - // explicitly. | |
| 2217 | - GFits infits(infile); | |
| 2218 | - for (int extno = 1; extno < infits.size(); ++extno) { | |
| 2219 | - GFitsHDU* hdu = infits.at(extno); | |
| 2220 | - if (hdu->extname() != evtname && | |
| 2221 | - hdu->extname() != gtiname && | |
| 2222 | - hdu->extname() != outevt && | |
| 2223 | - hdu->extname() != outgti) { | |
| 2224 | - outfits.append(*hdu); | |
| 2276 | + // Make writing of FITS file OpenMP thread save | |
| 2277 | + #pragma omp critical(ctool_save_event_list) | |
| 2278 | + { | |
| 2279 | + | |
| 2280 | + // Create output FITS file | |
| 2281 | + GFits outfits; | |
| 2282 | + | |
| 2283 | + // Write observation into FITS file | |
| 2284 | + obs->write(outfits, outevt, outgti); | |
| 2285 | + | |
| 2286 | + // Copy all extensions other than evtname and gtiname extensions | |
| 2287 | + // from the input to the output event list. The evtname and | |
| 2288 | + // gtiname extensions are written by the save method, all others | |
| 2289 | + // that may eventually be present have to be copied over | |
| 2290 | + // explicitly. | |
| 2291 | + GFits infits(infile); | |
| 2292 | + for (int extno = 1; extno < infits.size(); ++extno) { | |
| 2293 | + GFitsHDU* hdu = infits.at(extno); | |
| 2294 | + if (hdu->extname() != evtname && | |
| 2295 | + hdu->extname() != gtiname && | |
| 2296 | + hdu->extname() != outevt && | |
| 2297 | + hdu->extname() != outgti) { | |
| 2298 | + outfits.append(*hdu); | |
| 2299 | + } | |
| 2225 | 2300 | } |
| 2226 | - } | |
| 2227 | 2301 | |
| 2228 | - // Close input file | |
| 2229 | - infits.close(); | |
| 2302 | + // Close input file | |
| 2303 | + infits.close(); | |
| 2304 | + | |
| 2305 | + // Save file to disk and close it (we need both operations) | |
| 2306 | + outfits.saveto(outname.url(), clobber()); | |
| 2307 | + outfits.close(); | |
| 2230 | 2308 | |
| 2231 | - // Save file to disk and close it (we need both operations) | |
| 2232 | - outfits.saveto(outname.url(), clobber()); | |
| 2233 | - outfits.close(); | |
| 2309 | + } // end: omp critical section | |
| 2234 | 2310 | |
| 2235 | 2311 | } // endif: observation was unbinned |
| 2236 | 2312 | ... | ... |