Commit db226c73e7d6915f2f3af074044c4cc978f49f23
1 parent
833ce7f7
ctbin now always merges event lists into a single counts cube.
WARNING: The philosophy behind the ctbin tool changed fundamentally! ctbin now always produces a single counts cube on output. If a single event list is specified on input, the functionnality is basically unchanged. If multiple event lists are specified, however, events are now merged into a single counts cube file. No observation definition XML file is written anymore! So far, ctbin still writes pointing information in the counts cube, although this is not necessarily meaningful if merging event lists with different pointings. In the long run, pointing information will be summarized in a pointings definition file, and will be removed from the counts cube header. The logic is that the pointing definition is set to the map centre. This is only identical to the pointing in case of binning a single event list and using the usepnt=yes option (or specifying the pointing manually as the xref and yref parameters).
Showing
6 changed files
with
397 additions
and
25 deletions
ChangeLog
| 1 | -2014-07-10 Juergen Knoedlseder <jurgen.knodlseder@irap.omp.eu> | 1 | +2014-07-18 Juergen Knoedlseder <jurgen.knodlseder@irap.omp.eu> |
| 2 | 2 | ||
| 3 | * Version 0.8.0 released | 3 | * Version 0.8.0 released |
| 4 | ======================== | 4 | ======================== |
| 5 | 5 | ||
| 6 | + ctbin now always merges event lists into a single counts cube | ||
| 6 | Add ctexpcube tool | 7 | Add ctexpcube tool |
| 7 | Support energy dispersion in ctobssim, ctlike and ctmodel | 8 | Support energy dispersion in ctobssim, ctlike and ctmodel |
| 8 | Correct ctobssim for thread safety | 9 | Correct ctobssim for thread safety |
NEWS
| @@ -2,7 +2,7 @@ New Features and Important Changes in ctools 00-08-00 | @@ -2,7 +2,7 @@ New Features and Important Changes in ctools 00-08-00 | ||
| 2 | 2 | ||
| 3 | Author(s) : Juergen Knoedlseder | 3 | Author(s) : Juergen Knoedlseder |
| 4 | 4 | ||
| 5 | -10 July 2014 | 5 | +18 July 2014 |
| 6 | 6 | ||
| 7 | 7 | ||
| 8 | 1. Introduction | 8 | 1. Introduction |
| @@ -40,7 +40,22 @@ when iterating over ctselect (#1149). | @@ -40,7 +40,22 @@ when iterating over ctselect (#1149). | ||
| 40 | 40 | ||
| 41 | 6. ctbin - CTA event binning | 41 | 6. ctbin - CTA event binning |
| 42 | ---------------------------- | 42 | ---------------------------- |
| 43 | -None | 43 | +WARNING: The philosophy behind the ctbin tool changed fundamentally! |
| 44 | + | ||
| 45 | +ctbin now always produces a single counts cube on output. If a single | ||
| 46 | +event list is specified on input, the functionnality is basically | ||
| 47 | +unchanged. If multiple event lists are specified, however, events are | ||
| 48 | +now merged into a single counts cube file. No observation definition | ||
| 49 | +XML file is written anymore! | ||
| 50 | + | ||
| 51 | +So far, ctbin still writes pointing information in the counts cube, | ||
| 52 | +although this is not necessarily meaningful if merging event lists | ||
| 53 | +with different pointings. In the long run, pointing information will | ||
| 54 | +be summarized in a pointings definition file, and will be removed | ||
| 55 | +from the counts cube header. The logic is that the pointing definition | ||
| 56 | +is set to the map centre. This is only identical to the pointing in | ||
| 57 | +case of binning a single event list and using the usepnt=yes option | ||
| 58 | +(or specifying the pointing manually as the xref and yref parameters). | ||
| 44 | 59 | ||
| 45 | 60 | ||
| 46 | 7. ctlike - CTA maximum likelihood fitting | 61 | 7. ctlike - CTA maximum likelihood fitting |
pyext/ctbin.i
| 1 | /*************************************************************************** | 1 | /*************************************************************************** |
| 2 | * ctbin - CTA data binning tool * | 2 | * ctbin - CTA data binning tool * |
| 3 | * ----------------------------------------------------------------------- * | 3 | * ----------------------------------------------------------------------- * |
| 4 | - * copyright (C) 2010-2013 by Juergen Knoedlseder * | 4 | + * copyright (C) 2010-2014 by Juergen Knoedlseder * |
| 5 | * ----------------------------------------------------------------------- * | 5 | * ----------------------------------------------------------------------- * |
| 6 | * * | 6 | * * |
| 7 | * This program is free software: you can redistribute it and/or modify * | 7 | * This program is free software: you can redistribute it and/or modify * |
| @@ -50,8 +50,11 @@ public: | @@ -50,8 +50,11 @@ public: | ||
| 50 | void run(void); | 50 | void run(void); |
| 51 | void save(void); | 51 | void save(void); |
| 52 | const GObservations& obs(void) const; | 52 | const GObservations& obs(void) const; |
| 53 | + GCTAEventCube cube(void) const; | ||
| 53 | void get_parameters(void); | 54 | void get_parameters(void); |
| 54 | - void bin_events(GCTAObservation* obs); | 55 | + void init_cube(void); |
| 56 | + void fill_cube(GCTAObservation* obs); | ||
| 57 | + void obs_cube(void); | ||
| 55 | }; | 58 | }; |
| 56 | 59 | ||
| 57 | 60 |
src/ctbin/ctbin.cpp
| @@ -34,10 +34,14 @@ | @@ -34,10 +34,14 @@ | ||
| 34 | 34 | ||
| 35 | /* __ Method name definitions ____________________________________________ */ | 35 | /* __ Method name definitions ____________________________________________ */ |
| 36 | #define G_BIN_EVENTS "ctbin::bin_events(GCTAObservation*)" | 36 | #define G_BIN_EVENTS "ctbin::bin_events(GCTAObservation*)" |
| 37 | +#define G_GET_EBOUNDS "ctbin::get_ebounds()" | ||
| 38 | +#define G_INIT_CUBE "ctbin::init_cube()" | ||
| 39 | +#define G_FILL_CUBE "ctbin::fill_cube(GCTAObservation*)" | ||
| 37 | 40 | ||
| 38 | /* __ Debug definitions __________________________________________________ */ | 41 | /* __ Debug definitions __________________________________________________ */ |
| 39 | 42 | ||
| 40 | /* __ Coding definitions _________________________________________________ */ | 43 | /* __ Coding definitions _________________________________________________ */ |
| 44 | +#define G_MERGE_EVENTS | ||
| 41 | 45 | ||
| 42 | 46 | ||
| 43 | /*========================================================================== | 47 | /*========================================================================== |
| @@ -270,6 +274,11 @@ void ctbin::run(void) | @@ -270,6 +274,11 @@ void ctbin::run(void) | ||
| 270 | // Initialise observation counter | 274 | // Initialise observation counter |
| 271 | int n_observations = 0; | 275 | int n_observations = 0; |
| 272 | 276 | ||
| 277 | + // Compile option: if cube merging is requested, initialise the cube | ||
| 278 | + #if defined(G_MERGE_EVENTS) | ||
| 279 | + init_cube(); | ||
| 280 | + #endif | ||
| 281 | + | ||
| 273 | // Loop over all observations in the container | 282 | // Loop over all observations in the container |
| 274 | for (int i = 0; i < m_obs.size(); ++i) { | 283 | for (int i = 0; i < m_obs.size(); ++i) { |
| 275 | 284 | ||
| @@ -298,13 +307,25 @@ void ctbin::run(void) | @@ -298,13 +307,25 @@ void ctbin::run(void) | ||
| 298 | // Save event file name (for possible saving) | 307 | // Save event file name (for possible saving) |
| 299 | m_infiles[i] = obs->eventfile(); | 308 | m_infiles[i] = obs->eventfile(); |
| 300 | 309 | ||
| 301 | - // Bin events into counts map | 310 | + // Compile option: if cube merging is requested, fill the cube; |
| 311 | + // otherwise just bin the events | ||
| 312 | + #if defined(G_MERGE_EVENTS) | ||
| 313 | + fill_cube(obs); | ||
| 314 | + #else | ||
| 302 | bin_events(obs); | 315 | bin_events(obs); |
| 316 | + #endif | ||
| 303 | 317 | ||
| 304 | } // endif: CTA observation found | 318 | } // endif: CTA observation found |
| 305 | 319 | ||
| 306 | } // endfor: looped over observations | 320 | } // endfor: looped over observations |
| 307 | 321 | ||
| 322 | + // Compile option: if cube merging is requested, set a single cube in | ||
| 323 | + // the observation container | ||
| 324 | + #if defined(G_MERGE_EVENTS) | ||
| 325 | + obs_cube(); | ||
| 326 | + n_observations = 1; | ||
| 327 | + #endif | ||
| 328 | + | ||
| 308 | // If more than a single observation has been handled then make sure | 329 | // If more than a single observation has been handled then make sure |
| 309 | // that an XML file will be used for storage | 330 | // that an XML file will be used for storage |
| 310 | if (n_observations > 1) { | 331 | if (n_observations > 1) { |
| @@ -358,6 +379,12 @@ void ctbin::save(void) | @@ -358,6 +379,12 @@ void ctbin::save(void) | ||
| 358 | } | 379 | } |
| 359 | } | 380 | } |
| 360 | 381 | ||
| 382 | + // Compile option: if merging was requested, always save into a single | ||
| 383 | + // FITS file | ||
| 384 | + #if defined(G_MERGE_EVENTS) | ||
| 385 | + save_fits(); | ||
| 386 | + #else | ||
| 387 | + | ||
| 361 | /* | 388 | /* |
| 362 | // Case A: Save counts map(s) and XML metadata information | 389 | // Case A: Save counts map(s) and XML metadata information |
| 363 | if (m_use_xml) { | 390 | if (m_use_xml) { |
| @@ -371,6 +398,7 @@ void ctbin::save(void) | @@ -371,6 +398,7 @@ void ctbin::save(void) | ||
| 371 | 398 | ||
| 372 | // Always save FITS and an XML summary | 399 | // Always save FITS and an XML summary |
| 373 | save_xml(); | 400 | save_xml(); |
| 401 | + #endif | ||
| 374 | 402 | ||
| 375 | // Return | 403 | // Return |
| 376 | return; | 404 | return; |
| @@ -423,11 +451,6 @@ void ctbin::get_parameters(void) | @@ -423,11 +451,6 @@ void ctbin::get_parameters(void) | ||
| 423 | 451 | ||
| 424 | } | 452 | } |
| 425 | 453 | ||
| 426 | - // Use the xref and yref parameters for binning (otherwise the | ||
| 427 | - // pointing direction(s) is/are used) | ||
| 428 | - //m_xref = (*this)["xref"].real(); | ||
| 429 | - //m_yref = (*this)["yref"].real(); | ||
| 430 | - | ||
| 431 | } // endif: there was no observation in the container | 454 | } // endif: there was no observation in the container |
| 432 | 455 | ||
| 433 | // Get parameters | 456 | // Get parameters |
| @@ -436,7 +459,12 @@ void ctbin::get_parameters(void) | @@ -436,7 +459,12 @@ void ctbin::get_parameters(void) | ||
| 436 | m_xref = (*this)["xref"].real(); | 459 | m_xref = (*this)["xref"].real(); |
| 437 | m_yref = (*this)["yref"].real(); | 460 | m_yref = (*this)["yref"].real(); |
| 438 | } | 461 | } |
| 439 | - m_ebinalg = (*this)["ebinalg"].string(); | 462 | + m_proj = (*this)["proj"].string(); |
| 463 | + m_coordsys = (*this)["coordsys"].string(); | ||
| 464 | + m_binsz = (*this)["binsz"].real(); | ||
| 465 | + m_nxpix = (*this)["nxpix"].integer(); | ||
| 466 | + m_nypix = (*this)["nypix"].integer(); | ||
| 467 | + m_ebinalg = (*this)["ebinalg"].string(); | ||
| 440 | 468 | ||
| 441 | // If we have the binning given by a file then read filename | 469 | // If we have the binning given by a file then read filename |
| 442 | if (m_ebinalg == "FILE") { | 470 | if (m_ebinalg == "FILE") { |
| @@ -449,11 +477,6 @@ void ctbin::get_parameters(void) | @@ -449,11 +477,6 @@ void ctbin::get_parameters(void) | ||
| 449 | m_emax = (*this)["emax"].real(); | 477 | m_emax = (*this)["emax"].real(); |
| 450 | m_enumbins = (*this)["enumbins"].integer(); | 478 | m_enumbins = (*this)["enumbins"].integer(); |
| 451 | } | 479 | } |
| 452 | - m_proj = (*this)["proj"].string(); | ||
| 453 | - m_coordsys = (*this)["coordsys"].string(); | ||
| 454 | - m_binsz = (*this)["binsz"].real(); | ||
| 455 | - m_nxpix = (*this)["nxpix"].integer(); | ||
| 456 | - m_nypix = (*this)["nypix"].integer(); | ||
| 457 | 480 | ||
| 458 | // Optionally read ahead parameters so that they get correctly | 481 | // Optionally read ahead parameters so that they get correctly |
| 459 | // dumped into the log file | 482 | // dumped into the log file |
| @@ -664,6 +687,206 @@ void ctbin::bin_events(GCTAObservation* obs) | @@ -664,6 +687,206 @@ void ctbin::bin_events(GCTAObservation* obs) | ||
| 664 | } | 687 | } |
| 665 | 688 | ||
| 666 | 689 | ||
| 690 | +/***********************************************************************//** | ||
| 691 | + * @brief Initialise counts cube information | ||
| 692 | + * | ||
| 693 | + * @exception GException::invalid_value | ||
| 694 | + * No valid CTA observation found to derive the counts cube | ||
| 695 | + * map centre. | ||
| 696 | + * | ||
| 697 | + * Initialises the skymap, energy boundaries and GTI for a counts cube. | ||
| 698 | + ***************************************************************************/ | ||
| 699 | +void ctbin::init_cube(void) | ||
| 700 | +{ | ||
| 701 | + // Initialse cube information | ||
| 702 | + m_ontime = 0.0; | ||
| 703 | + m_livetime = 0.0; | ||
| 704 | + m_cube.clear(); | ||
| 705 | + m_ebounds.clear(); | ||
| 706 | + m_gti.clear(); | ||
| 707 | + | ||
| 708 | + // Set event cube centre, either from the user parameters or from the | ||
| 709 | + // pointing | ||
| 710 | + double xref = m_xref; | ||
| 711 | + double yref = m_yref; | ||
| 712 | + if (m_usepnt) { | ||
| 713 | + | ||
| 714 | + // Dummy: get pointing from first observation. Ultimately, we want | ||
| 715 | + // to get the pointing from a kind of average | ||
| 716 | + bool found = false; | ||
| 717 | + for (int i = 0; i < m_obs.size(); ++i) { | ||
| 718 | + GCTAObservation* obs = dynamic_cast<GCTAObservation*>(m_obs[i]); | ||
| 719 | + if (obs != NULL) { | ||
| 720 | + const GCTAPointing& pnt = obs->pointing(); | ||
| 721 | + if (gammalib::toupper(m_coordsys) == "GAL") { | ||
| 722 | + xref = pnt.dir().l_deg(); | ||
| 723 | + yref = pnt.dir().b_deg(); | ||
| 724 | + } | ||
| 725 | + else { | ||
| 726 | + xref = pnt.dir().ra_deg(); | ||
| 727 | + yref = pnt.dir().dec_deg(); | ||
| 728 | + } | ||
| 729 | + found = true; | ||
| 730 | + break; | ||
| 731 | + } | ||
| 732 | + } | ||
| 733 | + | ||
| 734 | + // Signal if no pointing is found | ||
| 735 | + if (!found) { | ||
| 736 | + std::string msg = "No valid CTA observation has been found in " | ||
| 737 | + "observation list, hence no pointing information " | ||
| 738 | + "could be extracted. Use the \"usepnt=no\" " | ||
| 739 | + "option and specify pointing explicitly when " | ||
| 740 | + "running ctbin."; | ||
| 741 | + throw GException::invalid_value(G_INIT_CUBE, msg); | ||
| 742 | + } | ||
| 743 | + | ||
| 744 | + } // endif: used pointing | ||
| 745 | + | ||
| 746 | + // Create skymap | ||
| 747 | + m_cube = GSkymap(m_proj, m_coordsys, | ||
| 748 | + xref, yref, -m_binsz, m_binsz, | ||
| 749 | + m_nxpix, m_nypix, m_enumbins); | ||
| 750 | + | ||
| 751 | + // Set energy boundaries | ||
| 752 | + get_ebounds(); | ||
| 753 | + | ||
| 754 | + // Return | ||
| 755 | + return; | ||
| 756 | +} | ||
| 757 | + | ||
| 758 | + | ||
| 759 | +/***********************************************************************//** | ||
| 760 | + * @brief Fill events into counts cube | ||
| 761 | + * | ||
| 762 | + * @param[in] obs CTA observation. | ||
| 763 | + * | ||
| 764 | + * @exception GException::no_list | ||
| 765 | + * No event list found in observation. | ||
| 766 | + * | ||
| 767 | + * Fills the events from an event list in the counts cube setup by init_cube. | ||
| 768 | + ***************************************************************************/ | ||
| 769 | +void ctbin::fill_cube(GCTAObservation* obs) | ||
| 770 | +{ | ||
| 771 | + // Continue only if observation pointer is valid | ||
| 772 | + if (obs != NULL) { | ||
| 773 | + | ||
| 774 | + // Make sure that the observation holds a CTA event list. If this | ||
| 775 | + // is not the case then throw an exception. | ||
| 776 | + if (dynamic_cast<const GCTAEventList*>(obs->events()) == NULL) { | ||
| 777 | + throw GException::no_list(G_BIN_EVENTS); | ||
| 778 | + } | ||
| 779 | + | ||
| 780 | + // Initialise binning statistics | ||
| 781 | + int num_outside_map = 0; | ||
| 782 | + int num_outside_ebds = 0; | ||
| 783 | + int num_in_map = 0; | ||
| 784 | + | ||
| 785 | + // Fill sky map | ||
| 786 | + GCTAEventList* events = | ||
| 787 | + static_cast<GCTAEventList*>(const_cast<GEvents*>(obs->events())); | ||
| 788 | + for (int i = 0; i < events->size(); ++i) { | ||
| 789 | + | ||
| 790 | + // Get event | ||
| 791 | + GCTAEventAtom* event = (*events)[i]; | ||
| 792 | + | ||
| 793 | + // Determine sky pixel | ||
| 794 | + GCTAInstDir* inst = (GCTAInstDir*)&(event->dir()); | ||
| 795 | + GSkyDir dir = inst->dir(); | ||
| 796 | + GSkyPixel pixel = m_cube.dir2pix(dir); | ||
| 797 | + | ||
| 798 | + // Skip if pixel is out of range | ||
| 799 | + if (pixel.x() < -0.5 || pixel.x() > (m_nxpix-0.5) || | ||
| 800 | + pixel.y() < -0.5 || pixel.y() > (m_nypix-0.5)) { | ||
| 801 | + num_outside_map++; | ||
| 802 | + continue; | ||
| 803 | + } | ||
| 804 | + | ||
| 805 | + // Determine energy bin. Skip if we are outside the energy range | ||
| 806 | + int index = m_ebounds.index(event->energy()); | ||
| 807 | + if (index == -1) { | ||
| 808 | + num_outside_ebds++; | ||
| 809 | + continue; | ||
| 810 | + } | ||
| 811 | + | ||
| 812 | + // Fill event in skymap | ||
| 813 | + m_cube(pixel, index) += 1.0; | ||
| 814 | + num_in_map++; | ||
| 815 | + | ||
| 816 | + } // endfor: looped over all events | ||
| 817 | + | ||
| 818 | + // Append GTIs | ||
| 819 | + m_gti.extend(events->gti()); | ||
| 820 | + | ||
| 821 | + // Update ontime and livetime | ||
| 822 | + m_ontime += obs->ontime(); | ||
| 823 | + m_livetime += obs->livetime(); | ||
| 824 | + | ||
| 825 | + // Log filling results | ||
| 826 | + if (logTerse()) { | ||
| 827 | + log << gammalib::parformat("Events in list"); | ||
| 828 | + log << obs->events()->size() << std::endl; | ||
| 829 | + log << gammalib::parformat("Events in cube"); | ||
| 830 | + log << num_in_map << std::endl; | ||
| 831 | + log << gammalib::parformat("Events outside cube area"); | ||
| 832 | + log << num_outside_map << std::endl; | ||
| 833 | + log << gammalib::parformat("Events outside energy bins"); | ||
| 834 | + log << num_outside_ebds << std::endl; | ||
| 835 | + } | ||
| 836 | + | ||
| 837 | + // Log cube | ||
| 838 | + if (logExplicit()) { | ||
| 839 | + log.header1("Counts cube"); | ||
| 840 | + log << m_cube << std::endl; | ||
| 841 | + } | ||
| 842 | + | ||
| 843 | + } // endif: observation was valid | ||
| 844 | + | ||
| 845 | + // Return | ||
| 846 | + return; | ||
| 847 | +} | ||
| 848 | + | ||
| 849 | + | ||
| 850 | +/***********************************************************************//** | ||
| 851 | + * @brief Put cube as single element in observation container. | ||
| 852 | + ***************************************************************************/ | ||
| 853 | +void ctbin::obs_cube(void) | ||
| 854 | +{ | ||
| 855 | + // Clear observation container | ||
| 856 | + m_obs.clear(); | ||
| 857 | + | ||
| 858 | + // Allocate CTA observation. We need this to make sure that all | ||
| 859 | + // attributes are set correctly | ||
| 860 | + GCTAObservation obs; | ||
| 861 | + | ||
| 862 | + // Attach event cube to CTA observation | ||
| 863 | + obs.events(this->cube()); | ||
| 864 | + | ||
| 865 | + // Set map centre as pointing | ||
| 866 | + GSkyPixel pixel(0.5*double(m_cube.nx()), 0.5*double(m_cube.ny())); | ||
| 867 | + GSkyDir centre = m_cube.pix2dir(pixel); | ||
| 868 | + GCTAPointing pointing(centre); | ||
| 869 | + | ||
| 870 | + // Compute deadtime correction | ||
| 871 | + double deadc = (m_ontime > 0.0) ? m_livetime / m_ontime : 0.0; | ||
| 872 | + | ||
| 873 | + // Set CTA observation attributes | ||
| 874 | + obs.pointing(pointing); | ||
| 875 | + obs.obs_id(0); | ||
| 876 | + obs.ra_obj(centre.ra_deg()); //!< Dummy | ||
| 877 | + obs.dec_obj(centre.dec_deg()); //!< Dummy | ||
| 878 | + obs.ontime(m_ontime); | ||
| 879 | + obs.livetime(m_livetime); | ||
| 880 | + obs.deadc(deadc); | ||
| 881 | + | ||
| 882 | + // Append observation to container | ||
| 883 | + m_obs.append(obs); | ||
| 884 | + | ||
| 885 | + // Return | ||
| 886 | + return; | ||
| 887 | +} | ||
| 888 | + | ||
| 889 | + | ||
| 667 | /*========================================================================== | 890 | /*========================================================================== |
| 668 | = = | 891 | = = |
| 669 | = Private methods = | 892 | = Private methods = |
| @@ -698,6 +921,11 @@ void ctbin::init_members(void) | @@ -698,6 +921,11 @@ void ctbin::init_members(void) | ||
| 698 | m_infiles.clear(); | 921 | m_infiles.clear(); |
| 699 | m_use_xml = false; | 922 | m_use_xml = false; |
| 700 | m_read_ahead = false; | 923 | m_read_ahead = false; |
| 924 | + m_cube.clear(); | ||
| 925 | + m_ebounds.clear(); | ||
| 926 | + m_gti.clear(); | ||
| 927 | + m_ontime = 0.0; | ||
| 928 | + m_livetime = 0.0; | ||
| 701 | 929 | ||
| 702 | // Set logger properties | 930 | // Set logger properties |
| 703 | log.date(true); | 931 | log.date(true); |
| @@ -737,6 +965,11 @@ void ctbin::copy_members(const ctbin& app) | @@ -737,6 +965,11 @@ void ctbin::copy_members(const ctbin& app) | ||
| 737 | m_infiles = app.m_infiles; | 965 | m_infiles = app.m_infiles; |
| 738 | m_use_xml = app.m_use_xml; | 966 | m_use_xml = app.m_use_xml; |
| 739 | m_read_ahead = app.m_read_ahead; | 967 | m_read_ahead = app.m_read_ahead; |
| 968 | + m_cube = app.m_cube; | ||
| 969 | + m_ebounds = app.m_ebounds; | ||
| 970 | + m_gti = app.m_gti; | ||
| 971 | + m_ontime = app.m_ontime; | ||
| 972 | + m_livetime = app.m_livetime; | ||
| 740 | 973 | ||
| 741 | // Return | 974 | // Return |
| 742 | return; | 975 | return; |
| @@ -759,6 +992,83 @@ void ctbin::free_members(void) | @@ -759,6 +992,83 @@ void ctbin::free_members(void) | ||
| 759 | 992 | ||
| 760 | 993 | ||
| 761 | /***********************************************************************//** | 994 | /***********************************************************************//** |
| 995 | + * @brief Get the energy boundaries | ||
| 996 | + * | ||
| 997 | + * @exception GException::invalid_value | ||
| 998 | + * No valid energy boundary extension found. | ||
| 999 | + * | ||
| 1000 | + * Get the energy boundaries according to the user parameters. The method | ||
| 1001 | + * supports loading of energy boundary information from the EBOUNDS or | ||
| 1002 | + * ENERGYBINS extension, or setting energy boundaries using a linear | ||
| 1003 | + * or logarithmical spacing. | ||
| 1004 | + * | ||
| 1005 | + * @todo Ultimately this method should go in a support library as it is | ||
| 1006 | + * used by several ctools. | ||
| 1007 | + ***************************************************************************/ | ||
| 1008 | +void ctbin::get_ebounds(void) | ||
| 1009 | +{ | ||
| 1010 | + // Initialse energy boundary information | ||
| 1011 | + m_ebounds.clear(); | ||
| 1012 | + | ||
| 1013 | + // Check whether energy binning information should be read from a FITS | ||
| 1014 | + // file ... | ||
| 1015 | + if (m_ebinalg == "FILE") { | ||
| 1016 | + | ||
| 1017 | + // Open energy boundary file using the EBOUNDS or ENERGYBINS | ||
| 1018 | + // extension. Throw an exception if opening fails. | ||
| 1019 | + GFits file(m_ebinfile); | ||
| 1020 | + if (file.contains("EBOUNDS")) { | ||
| 1021 | + file.close(); | ||
| 1022 | + m_ebounds.load(m_ebinfile,"EBOUNDS"); | ||
| 1023 | + } | ||
| 1024 | + else if (file.contains("ENERGYBINS")) { | ||
| 1025 | + file.close(); | ||
| 1026 | + m_ebounds.load(m_ebinfile,"ENERGYBINS"); | ||
| 1027 | + } | ||
| 1028 | + else { | ||
| 1029 | + file.close(); | ||
| 1030 | + std::string msg = "No extension with name \"EBOUNDS\" or" | ||
| 1031 | + " \"ENERGYBINS\" found in FITS file" | ||
| 1032 | + " \""+m_ebinfile+"\".\n" | ||
| 1033 | + "An \"EBOUNDS\" or \"ENERGYBINS\" extension" | ||
| 1034 | + " is required if the parameter \"ebinalg\"" | ||
| 1035 | + " is set to \"FILE\"."; | ||
| 1036 | + throw GException::invalid_value(G_BIN_EVENTS, msg); | ||
| 1037 | + } | ||
| 1038 | + | ||
| 1039 | + // Set enumbins parameter to number of ebounds | ||
| 1040 | + m_enumbins = m_ebounds.size(); | ||
| 1041 | + | ||
| 1042 | + } // endif: ebinalg was "FILE" | ||
| 1043 | + | ||
| 1044 | + // ... otherwise use a linear or a logarithmically-spaced energy binning | ||
| 1045 | + else { | ||
| 1046 | + | ||
| 1047 | + // Initialise log mode for ebinning | ||
| 1048 | + bool log = true; | ||
| 1049 | + | ||
| 1050 | + // check if algorithm is linear | ||
| 1051 | + if (m_ebinalg == "LIN") { | ||
| 1052 | + log = false; | ||
| 1053 | + } | ||
| 1054 | + | ||
| 1055 | + // todo: should we also check if m_ebinalg is "LOG" | ||
| 1056 | + // and throw an exception if neither LIN/LOG/FILE | ||
| 1057 | + // is given? | ||
| 1058 | + | ||
| 1059 | + // Setup energy range covered by data | ||
| 1060 | + GEnergy emin(m_emin, "TeV"); | ||
| 1061 | + GEnergy emax(m_emax, "TeV"); | ||
| 1062 | + m_ebounds = GEbounds(m_enumbins, emin, emax, log); | ||
| 1063 | + | ||
| 1064 | + } //endif: ebinalg was not "FILE" | ||
| 1065 | + | ||
| 1066 | + // Return | ||
| 1067 | + return; | ||
| 1068 | +} | ||
| 1069 | + | ||
| 1070 | + | ||
| 1071 | +/***********************************************************************//** | ||
| 762 | * @brief Set output file name. | 1072 | * @brief Set output file name. |
| 763 | * | 1073 | * |
| 764 | * @param[in] index Index of input file. | 1074 | * @param[in] index Index of input file. |
src/ctbin/ctbin.hpp
| @@ -33,7 +33,7 @@ | @@ -33,7 +33,7 @@ | ||
| 33 | 33 | ||
| 34 | /* __Definitions _________________________________________________________ */ | 34 | /* __Definitions _________________________________________________________ */ |
| 35 | #define CTBIN_NAME "ctbin" | 35 | #define CTBIN_NAME "ctbin" |
| 36 | -#define CTBIN_VERSION "00-04-00" | 36 | +#define CTBIN_VERSION "00-05-00" |
| 37 | 37 | ||
| 38 | 38 | ||
| 39 | /***********************************************************************//** | 39 | /***********************************************************************//** |
| @@ -41,11 +41,24 @@ | @@ -41,11 +41,24 @@ | ||
| 41 | * | 41 | * |
| 42 | * @brief CTA data binning tool interface defintion | 42 | * @brief CTA data binning tool interface defintion |
| 43 | * | 43 | * |
| 44 | - * This class bins CTA event list(s) into a counts map(s). The class can | ||
| 45 | - * operate on predefined observation containers, on individual event list | ||
| 46 | - * FITS files, and on observation definition XML files. Results are stored | ||
| 47 | - * in an observation container that can be written to disk in form of FITS | ||
| 48 | - * files (counts maps) and an updated observation definition file. | 44 | + * This class bins CTA event list(s) into a single counts cube. The class |
| 45 | + * can operate on predefined observation containers, on individual event list | ||
| 46 | + * FITS files, and on observation definition XML files. | ||
| 47 | + * | ||
| 48 | + * If multiple event lists are specified in the observation container or the | ||
| 49 | + * XML definition file, the class will merge these events into a single | ||
| 50 | + * counts cube. | ||
| 51 | + * | ||
| 52 | + * Results are stored in an observation container that can be written to disk | ||
| 53 | + * in form of a single FITS file. | ||
| 54 | + * | ||
| 55 | + * WARNING: Note that the pointing direction of the counts cube will be set | ||
| 56 | + * to the skymap centre used for the counts cube definition. If usepnt=yes | ||
| 57 | + * is used, the pointing direction will be extracted from the first | ||
| 58 | + * observation encountered in the list. Ultimately, pointing direction | ||
| 59 | + * information should not be removed from the counts cube and exposure and | ||
| 60 | + * PSF cubes should be used for response computation. This is however not | ||
| 61 | + * yet fully implemented. | ||
| 49 | ***************************************************************************/ | 62 | ***************************************************************************/ |
| 50 | class ctbin : public GApplication { | 63 | class ctbin : public GApplication { |
| 51 | public: | 64 | public: |
| @@ -65,20 +78,27 @@ public: | @@ -65,20 +78,27 @@ public: | ||
| 65 | void run(void); | 78 | void run(void); |
| 66 | void save(void); | 79 | void save(void); |
| 67 | const GObservations& obs(void) const; | 80 | const GObservations& obs(void) const; |
| 81 | + GCTAEventCube cube(void) const; | ||
| 68 | void get_parameters(void); | 82 | void get_parameters(void); |
| 69 | - void bin_events(GCTAObservation* obs); | 83 | + void init_cube(void); |
| 84 | + void fill_cube(GCTAObservation* obs); | ||
| 85 | + void obs_cube(void); | ||
| 70 | 86 | ||
| 71 | protected: | 87 | protected: |
| 72 | // Protected methods | 88 | // Protected methods |
| 73 | void init_members(void); | 89 | void init_members(void); |
| 74 | void copy_members(const ctbin& app); | 90 | void copy_members(const ctbin& app); |
| 75 | void free_members(void); | 91 | void free_members(void); |
| 92 | + void get_ebounds(void); | ||
| 76 | std::string set_outfile_name(const int index) const; | 93 | std::string set_outfile_name(const int index) const; |
| 77 | void save_fits(void); | 94 | void save_fits(void); |
| 78 | void save_xml(void); | 95 | void save_xml(void); |
| 79 | void save_counts_map(const GCTAObservation* obs, | 96 | void save_counts_map(const GCTAObservation* obs, |
| 80 | const std::string& outfile) const; | 97 | const std::string& outfile) const; |
| 81 | 98 | ||
| 99 | + // Obsolete methods (to be reomved later) | ||
| 100 | + void bin_events(GCTAObservation* obs); | ||
| 101 | + | ||
| 82 | // User parameters | 102 | // User parameters |
| 83 | std::string m_evfile; //!< Input event list or XML file | 103 | std::string m_evfile; //!< Input event list or XML file |
| 84 | std::string m_outfile; //!< Output counts map or XML file | 104 | std::string m_outfile; //!< Output counts map or XML file |
| @@ -102,6 +122,11 @@ protected: | @@ -102,6 +122,11 @@ protected: | ||
| 102 | std::vector<std::string> m_infiles; //!< Input event filenames | 122 | std::vector<std::string> m_infiles; //!< Input event filenames |
| 103 | bool m_use_xml; //!< Use XML file instead of FITS file | 123 | bool m_use_xml; //!< Use XML file instead of FITS file |
| 104 | bool m_read_ahead; //!< Read ahead parameters | 124 | bool m_read_ahead; //!< Read ahead parameters |
| 125 | + GSkymap m_cube; //!< Event cube | ||
| 126 | + GEbounds m_ebounds; //!< Energy boundaries | ||
| 127 | + GGti m_gti; //!< Good time intervals | ||
| 128 | + double m_ontime; //!< Total ontime | ||
| 129 | + double m_livetime; //!< Total livetime | ||
| 105 | }; | 130 | }; |
| 106 | 131 | ||
| 107 | /***********************************************************************//** | 132 | /***********************************************************************//** |
| @@ -115,4 +140,22 @@ const GObservations& ctbin::obs(void) const | @@ -115,4 +140,22 @@ const GObservations& ctbin::obs(void) const | ||
| 115 | return m_obs; | 140 | return m_obs; |
| 116 | } | 141 | } |
| 117 | 142 | ||
| 143 | + | ||
| 144 | +/***********************************************************************//** | ||
| 145 | + * @brief Return event cube | ||
| 146 | + * | ||
| 147 | + * @return Event cube | ||
| 148 | + * | ||
| 149 | + * Returns a CTA event cube built from the ctbin member information. | ||
| 150 | + ***************************************************************************/ | ||
| 151 | +inline | ||
| 152 | +GCTAEventCube ctbin::cube(void) const | ||
| 153 | +{ | ||
| 154 | + // Build event cube | ||
| 155 | + GCTAEventCube cube(m_cube, m_ebounds, m_gti); | ||
| 156 | + | ||
| 157 | + // Return cube | ||
| 158 | + return cube; | ||
| 159 | +} | ||
| 160 | + | ||
| 118 | #endif /* CTBIN_HPP */ | 161 | #endif /* CTBIN_HPP */ |
src/ctbin/ctbin.par
| @@ -5,7 +5,7 @@ | @@ -5,7 +5,7 @@ | ||
| 5 | # ------------------------------------------------------------------------- # | 5 | # ------------------------------------------------------------------------- # |
| 6 | # # | 6 | # # |
| 7 | # File: ctbin.par # | 7 | # File: ctbin.par # |
| 8 | -# Version: 00-04-00 # | 8 | +# Version: 00-05-00 # |
| 9 | # # | 9 | # # |
| 10 | # Author: Jurgen Knodlseder # | 10 | # Author: Jurgen Knodlseder # |
| 11 | # Jurgen.Knodlseder@irap.omp.eu # | 11 | # Jurgen.Knodlseder@irap.omp.eu # |