Commit b6b50dc00463c2ae4f00ba9da68a9f8f687aa7bb

Authored by Jürgen Knödlseder
2 parents 89317305 bc79a4f9

Merge branch 'devel' into release

# Conflicts:
#	ChangeLog
#	NEWS
#	README
#	inst/cta/src/GCTAEdisp2D.cpp
ChangeLog
1 -2015-12-17 Juergen Knoedlseder <jurgen.knodlseder@irap.omp.eu> 1 +2015-12-18 Juergen Knoedlseder <jurgen.knodlseder@irap.omp.eu>
2 2
3 * Version 1.0.0 released 3 * Version 1.0.0 released
4 ========================= 4 =========================
5 5
6 Ignore errors for El Capitan post processing (#1605) 6 Ignore errors for El Capitan post processing (#1605)
  7 + Read only mandatary columns in GCTAEventList (#1600)
  8 + Add GModel::has_ts() method (#1578)
7 Remove extname arguments from classes (#1601) 9 Remove extname arguments from classes (#1601)
8 Add GFilename class (#1599) 10 Add GFilename class (#1599)
9 Check existence of files in CTA response loading (#1586) 11 Check existence of files in CTA response loading (#1586)
10 GSkyMap::__getitem__ throw exception if out of bound (#1581) 12 GSkyMap::__getitem__ throw exception if out of bound (#1581)
11 Handle ~ in filenames (#1580) 13 Handle ~ in filenames (#1580)
  14 + Add GModel::has_ts() method (#1578)
12 Perform __init__.py creation only in build step (#1569) 15 Perform __init__.py creation only in build step (#1569)
13 Remove access by name methods from GSkyRegions (#1564) 16 Remove access by name methods from GSkyRegions (#1564)
14 Resolve Python test problem on El Capitan (#1563) 17 Resolve Python test problem on El Capitan (#1563)
@@ -58,7 +58,8 @@ None @@ -58,7 +58,8 @@ None
58 58
59 8. Model module 59 8. Model module
60 --------------- 60 ---------------
61 -None 61 +Added GModel::has_ts() method that signals if a TS value has been computed
  62 +for a given model.
62 63
63 64
64 9. Numerics module 65 9. Numerics module
@@ -134,9 +135,12 @@ None @@ -134,9 +135,12 @@ None
134 135
135 20. CTA interface 136 20. CTA interface
136 ----------------- 137 -----------------
137 -The IRF loaders now check the existence of the file before loading, and now throw 138 +The IRF loaders now check the existence of the file before loading, and now throws
138 appropriate error messages in case that the files do not exist (#1586). 139 appropriate error messages in case that the files do not exist (#1586).
139 140
  141 +Only manadatory columns are read by GCTAEventsList, while any other columns will only
  142 +be stored for back writing in a FITS file.
  143 +
140 144
141 21. COMPTEL interface 145 21. COMPTEL interface
142 --------------------- 146 ---------------------
configure.ac
@@ -29,7 +29,7 @@ @@ -29,7 +29,7 @@
29 ############################################################################# 29 #############################################################################
30 # Initialisation # 30 # Initialisation #
31 ############################################################################# 31 #############################################################################
32 -AC_INIT([gammalib], [1.0.0], [jurgen.knodlseder@irap.omp.eu], [gammalib]) 32 +AC_INIT([gammalib], [1.1.0.dev], [jurgen.knodlseder@irap.omp.eu], [gammalib])
33 AC_CONFIG_SRCDIR([src/support/GTools.cpp]) 33 AC_CONFIG_SRCDIR([src/support/GTools.cpp])
34 AC_CONFIG_MACRO_DIR([m4]) 34 AC_CONFIG_MACRO_DIR([m4])
35 AM_INIT_AUTOMAKE([gnu no-dependencies -Wno-portability subdir-objects]) 35 AM_INIT_AUTOMAKE([gnu no-dependencies -Wno-portability subdir-objects])
doc/Doxyfile
@@ -32,7 +32,7 @@ PROJECT_NAME = GammaLib @@ -32,7 +32,7 @@ PROJECT_NAME = GammaLib
32 # This could be handy for archiving the generated documentation or 32 # This could be handy for archiving the generated documentation or
33 # if some version control system is used. 33 # if some version control system is used.
34 34
35 -PROJECT_NUMBER = 1.0.0 35 +PROJECT_NUMBER = 1.1.0.dev
36 36
37 # Using the PROJECT_BRIEF tag one can provide an optional one line description 37 # Using the PROJECT_BRIEF tag one can provide an optional one line description
38 # for a project that appears at the top of each page and should give viewer 38 # for a project that appears at the top of each page and should give viewer
doc/source/conf.py
@@ -55,9 +55,10 @@ copyright = u&#39;2006-2015, GammaLib developers&#39; @@ -55,9 +55,10 @@ copyright = u&#39;2006-2015, GammaLib developers&#39;
55 # built documents. 55 # built documents.
56 # 56 #
57 # The short X.Y version. 57 # The short X.Y version.
58 -version = '1.0' 58 +version = '1.1'
  59 +
59 # The full version, including alpha/beta/rc tags. 60 # The full version, including alpha/beta/rc tags.
60 -release = '1.0.0' 61 +release = '1.1.0.dev'
61 62
62 # The language for content autogenerated by Sphinx. Refer to documentation 63 # The language for content autogenerated by Sphinx. Refer to documentation
63 # for a list of supported languages. 64 # for a list of supported languages.
include/GModel.hpp
@@ -139,6 +139,7 @@ public: @@ -139,6 +139,7 @@ public:
139 void ts(const double& ts); 139 void ts(const double& ts);
140 const bool& tscalc(void) const; 140 const bool& tscalc(void) const;
141 void tscalc(const bool& tscalc); 141 void tscalc(const bool& tscalc);
  142 + const bool& has_ts(void) const;
142 std::string instruments(void) const; 143 std::string instruments(void) const;
143 void instruments(const std::string& instruments); 144 void instruments(const std::string& instruments);
144 GModelPar scale(const std::string& instrument) const; 145 GModelPar scale(const std::string& instrument) const;
@@ -314,7 +315,7 @@ void GModel::tscalc(const bool&amp; tscalc) @@ -314,7 +315,7 @@ void GModel::tscalc(const bool&amp; tscalc)
314 /***********************************************************************//** 315 /***********************************************************************//**
315 * @brief Signals that model has scales 316 * @brief Signals that model has scales
316 * 317 *
317 - * @return True is model has scale factors. 318 + * @return True if model has scale factors.
318 ***************************************************************************/ 319 ***************************************************************************/
319 inline 320 inline
320 bool GModel::has_scales(void) const 321 bool GModel::has_scales(void) const
@@ -322,4 +323,16 @@ bool GModel::has_scales(void) const @@ -322,4 +323,16 @@ bool GModel::has_scales(void) const
322 return (!m_scales.empty()); 323 return (!m_scales.empty());
323 } 324 }
324 325
  326 +
  327 +/***********************************************************************//**
  328 + * @brief Signals that model has Test Statistics value
  329 + *
  330 + * @return True if model has TS value.
  331 + ***************************************************************************/
  332 +inline
  333 +const bool& GModel::has_ts(void) const
  334 +{
  335 + return m_has_ts;
  336 +}
  337 +
325 #endif /* GMODEL_HPP */ 338 #endif /* GMODEL_HPP */
include/GVOHub.hpp
@@ -108,11 +108,14 @@ protected: @@ -108,11 +108,14 @@ protected:
108 108
109 // Low-level methods 109 // Low-level methods
110 void create_samp_file(void) const; 110 void create_samp_file(void) const;
  111 + void delete_samp_file(void) const;
  112 + int get_socket(void);
111 void post_samp_ok(const socklen_t& sock) const; 113 void post_samp_ok(const socklen_t& sock) const;
112 void post_samp_void(const socklen_t& sock) const; 114 void post_samp_void(const socklen_t& sock) const;
113 void post_string(const std::string& content, const socklen_t& sock) const; 115 void post_string(const std::string& content, const socklen_t& sock) const;
114 void notify(const std::string& url, const std::string& notification) const; 116 void notify(const std::string& url, const std::string& notification) const;
115 std::string random_string(const size_t& length) const; 117 std::string random_string(const size_t& length) const;
  118 + std::string hub_url(void) const;
116 119
117 // Protected structure 120 // Protected structure
118 struct client { 121 struct client {
@@ -132,7 +135,6 @@ protected: @@ -132,7 +135,6 @@ protected:
132 135
133 // Protected members 136 // Protected members
134 std::string m_secret; //!< Secret Hub key 137 std::string m_secret; //!< Secret Hub key
135 - std::string m_hub_url; //!< The XML-RPC endpoint for communication with the hub  
136 std::string m_hub_host; //!< Hub host 138 std::string m_hub_host; //!< Hub host
137 std::string m_hub_port; //!< Hub port 139 std::string m_hub_port; //!< Hub port
138 std::string m_hub_path; //!< Hub path 140 std::string m_hub_path; //!< Hub path
inst/cta/include/GCTAEventAtom.hpp
@@ -72,10 +72,8 @@ public: @@ -72,10 +72,8 @@ public:
72 // Other methods 72 // Other methods
73 const int& index(void) const; 73 const int& index(void) const;
74 const unsigned long& event_id(void) const; 74 const unsigned long& event_id(void) const;
75 - const unsigned long& obs_id(void) const;  
76 const float& phase(void) const; 75 const float& phase(void) const;
77 void event_id(const unsigned long& id); 76 void event_id(const unsigned long& id);
78 - void obs_id(const unsigned long& id);  
79 void phase(const float& phase); 77 void phase(const float& phase);
80 78
81 protected: 79 protected:
@@ -90,24 +88,6 @@ protected: @@ -90,24 +88,6 @@ protected:
90 GEnergy m_energy; //!< Event energy 88 GEnergy m_energy; //!< Event energy
91 GTime m_time; //!< Event time 89 GTime m_time; //!< Event time
92 unsigned long m_event_id; //!< Event identifier 90 unsigned long m_event_id; //!< Event identifier
93 - unsigned long m_obs_id; //!< Observation identifier  
94 - int m_multip; //!< Multiplicity  
95 - char m_telmask; //!< Telescope mask  
96 - float m_dir_err; //!< Error on event direction  
97 - float m_alt; //!< Event altitude  
98 - float m_az; //!< Event azimuth  
99 - float m_corex; //!< Position on ground (m)  
100 - float m_corey; //!< Position on ground (m)  
101 - float m_core_err; //!< Error on core reconstruction  
102 - float m_xmax; //!< Position of shower max (g/cm2)  
103 - float m_xmax_err; //!< Error on shower max (g/cm2)  
104 - float m_shwidth; //!< Shower width (m)  
105 - float m_shlength; //!< Shower length (m)  
106 - float m_energy_err; //!< Error on event energy (MeV)  
107 - float m_hil_msw; //!< Hillas MSW  
108 - float m_hil_msw_err; //!< Hillas MSW error  
109 - float m_hil_msl; //!< Hillas MSL  
110 - float m_hil_msl_err; //!< Hillas MSL error  
111 float m_phase; //!< Optional phase 91 float m_phase; //!< Optional phase
112 }; 92 };
113 93
@@ -226,18 +206,6 @@ const unsigned long&amp; GCTAEventAtom::event_id(void) const @@ -226,18 +206,6 @@ const unsigned long&amp; GCTAEventAtom::event_id(void) const
226 206
227 207
228 /***********************************************************************//** 208 /***********************************************************************//**
229 - * @brief Return observation identifier  
230 - *  
231 - * @return Observation identifier.  
232 - ***************************************************************************/  
233 -inline  
234 -const unsigned long& GCTAEventAtom::obs_id(void) const  
235 -{  
236 - return (m_obs_id);  
237 -}  
238 -  
239 -  
240 -/***********************************************************************//**  
241 * @brief Return event phase 209 * @brief Return event phase
242 * 210 *
243 * @return Event phase. 211 * @return Event phase.
@@ -263,19 +231,6 @@ void GCTAEventAtom::event_id(const unsigned long&amp; id) @@ -263,19 +231,6 @@ void GCTAEventAtom::event_id(const unsigned long&amp; id)
263 231
264 232
265 /***********************************************************************//** 233 /***********************************************************************//**
266 - * @brief Set observation identifier  
267 - *  
268 - * @param[in] id Observation identifier.  
269 - ***************************************************************************/  
270 -inline  
271 -void GCTAEventAtom::obs_id(const unsigned long& id)  
272 -{  
273 - m_obs_id = id;  
274 - return;  
275 -}  
276 -  
277 -  
278 -/***********************************************************************//**  
279 * @brief Set event phase 234 * @brief Set event phase
280 * 235 *
281 * @param[in] phase Event phase. 236 * @param[in] phase Event phase.
inst/cta/include/GCTAEventList.hpp
@@ -88,19 +88,18 @@ protected: @@ -88,19 +88,18 @@ protected:
88 void free_members(void); 88 void free_members(void);
89 virtual void set_energies(void) { return; } 89 virtual void set_energies(void) { return; }
90 virtual void set_times(void) { return; } 90 virtual void set_times(void) { return; }
91 - void read_events(const GFitsTable& hdu);  
92 - void read_events_v0(const GFitsTable& hdu);  
93 - void read_events_v1(const GFitsTable& hdu);  
94 - void read_events_hillas(const GFitsTable& hdu);  
95 - void write_events(GFitsBinTable& hdu) const; 91 + void read_events(const GFitsTable& table);
  92 + void write_events(GFitsBinTable& table) const;
96 void write_ds_keys(GFitsHDU& hdu) const; 93 void write_ds_keys(GFitsHDU& hdu) const;
97 int irf_cache_init(const std::string& name) const; 94 int irf_cache_init(const std::string& name) const;
98 int irf_cache_index(const std::string& name) const; 95 int irf_cache_index(const std::string& name) const;
99 96
100 // Protected members 97 // Protected members
101 - GCTARoi m_roi; //!< Region of interest  
102 - std::vector<GCTAEventAtom> m_events; //!< Events  
103 - bool m_has_phase; //!< Signal presence of phase 98 + GCTARoi m_roi; //!< Region of interest
  99 + std::vector<GCTAEventAtom> m_events; //!< Events
  100 + std::vector<GFitsTableCol*> m_columns; //!< Pointers to optional columns
  101 + bool m_has_phase; //!< Signal presence of phase
  102 + bool m_has_detxy; //!< Signal presence of detector coordinates
104 103
105 // IRF cache for diffuse models 104 // IRF cache for diffuse models
106 mutable std::vector<std::string> m_irf_names; //!< Model names 105 mutable std::vector<std::string> m_irf_names; //!< Model names
inst/cta/pyext/GCTAEventAtom.i
@@ -55,10 +55,8 @@ public: @@ -55,10 +55,8 @@ public:
55 // Other methods 55 // Other methods
56 const int& index(void) const; 56 const int& index(void) const;
57 const unsigned long& event_id(void) const; 57 const unsigned long& event_id(void) const;
58 - const unsigned long& obs_id(void) const;  
59 const float& phase(void) const; 58 const float& phase(void) const;
60 void event_id(const unsigned long& id); 59 void event_id(const unsigned long& id);
61 - void obs_id(const unsigned long& id);  
62 void phase(const float& phase); 60 void phase(const float& phase);
63 }; 61 };
64 62
inst/cta/src/GCTAEventAtom.cpp
@@ -207,27 +207,9 @@ void GCTAEventAtom::init_members(void) @@ -207,27 +207,9 @@ void GCTAEventAtom::init_members(void)
207 m_dir.clear(); 207 m_dir.clear();
208 m_time.clear(); 208 m_time.clear();
209 m_energy.clear(); 209 m_energy.clear();
210 - m_index = 0;  
211 - m_event_id = 0;  
212 - m_obs_id = 0;  
213 - m_multip = 0;  
214 - m_telmask = 0;  
215 - m_dir_err = 0.0;  
216 - m_alt = 0.0;  
217 - m_az = 0.0;  
218 - m_corex = 0.0;  
219 - m_corey = 0.0;  
220 - m_core_err = 0.0;  
221 - m_xmax = 0.0;  
222 - m_xmax_err = 0.0;  
223 - m_shwidth = 0.0;  
224 - m_shlength = 0.0;  
225 - m_energy_err = 0.0;  
226 - m_hil_msw = 0.0;  
227 - m_hil_msw_err = 0.0;  
228 - m_hil_msl = 0.0;  
229 - m_hil_msl_err = 0.0;  
230 - m_phase = 0.0; 210 + m_index = 0;
  211 + m_event_id = 0;
  212 + m_phase = 0.0;
231 213
232 // Return 214 // Return
233 return; 215 return;
@@ -242,30 +224,12 @@ void GCTAEventAtom::init_members(void) @@ -242,30 +224,12 @@ void GCTAEventAtom::init_members(void)
242 void GCTAEventAtom::copy_members(const GCTAEventAtom& atom) 224 void GCTAEventAtom::copy_members(const GCTAEventAtom& atom)
243 { 225 {
244 // Copy members 226 // Copy members
245 - m_dir = atom.m_dir;  
246 - m_time = atom.m_time;  
247 - m_energy = atom.m_energy;  
248 - m_index = atom.m_index;  
249 - m_event_id = atom.m_event_id;  
250 - m_obs_id = atom.m_obs_id;  
251 - m_multip = atom.m_multip;  
252 - m_telmask = atom.m_telmask;  
253 - m_dir_err = atom.m_dir_err;  
254 - m_alt = atom.m_alt;  
255 - m_az = atom.m_az;  
256 - m_corex = atom.m_corex;  
257 - m_corey = atom.m_corey;  
258 - m_core_err = atom.m_core_err;  
259 - m_xmax = atom.m_xmax;  
260 - m_xmax_err = atom.m_xmax_err;  
261 - m_shwidth = atom.m_shwidth;  
262 - m_shlength = atom.m_shlength;  
263 - m_energy_err = atom.m_energy_err;  
264 - m_hil_msw = atom.m_hil_msw;  
265 - m_hil_msw_err = atom.m_hil_msw_err;  
266 - m_hil_msl = atom.m_hil_msl;  
267 - m_hil_msl_err = atom.m_hil_msl_err;  
268 - m_phase = atom.m_phase; 227 + m_dir = atom.m_dir;
  228 + m_time = atom.m_time;
  229 + m_energy = atom.m_energy;
  230 + m_index = atom.m_index;
  231 + m_event_id = atom.m_event_id;
  232 + m_phase = atom.m_phase;
269 233
270 // Return 234 // Return
271 return; 235 return;
inst/cta/src/GCTAEventList.cpp
@@ -572,7 +572,9 @@ void GCTAEventList::init_members(void) @@ -572,7 +572,9 @@ void GCTAEventList::init_members(void)
572 // Initialise members 572 // Initialise members
573 m_roi.clear(); 573 m_roi.clear();
574 m_events.clear(); 574 m_events.clear();
  575 + m_columns.clear();
575 m_has_phase = false; 576 m_has_phase = false;
  577 + m_has_detxy = true;
576 578
577 // Initialise cache 579 // Initialise cache
578 m_irf_names.clear(); 580 m_irf_names.clear();
@@ -594,11 +596,18 @@ void GCTAEventList::copy_members(const GCTAEventList&amp; list) @@ -594,11 +596,18 @@ void GCTAEventList::copy_members(const GCTAEventList&amp; list)
594 m_roi = list.m_roi; 596 m_roi = list.m_roi;
595 m_events = list.m_events; 597 m_events = list.m_events;
596 m_has_phase = list.m_has_phase; 598 m_has_phase = list.m_has_phase;
  599 + m_has_detxy = list.m_has_detxy;
597 600
598 // Copy cache 601 // Copy cache
599 m_irf_names = list.m_irf_names; 602 m_irf_names = list.m_irf_names;
600 m_irf_values = list.m_irf_values; 603 m_irf_values = list.m_irf_values;
601 604
  605 + // Copy column pointers
  606 + m_columns.clear();
  607 + for (int i = 0; i < list.m_columns.size(); ++i) {
  608 + m_columns.push_back((list.m_columns[i]->clone()));
  609 + }
  610 +
602 // Return 611 // Return
603 return; 612 return;
604 } 613 }
@@ -609,6 +618,12 @@ void GCTAEventList::copy_members(const GCTAEventList&amp; list) @@ -609,6 +618,12 @@ void GCTAEventList::copy_members(const GCTAEventList&amp; list)
609 ***************************************************************************/ 618 ***************************************************************************/
610 void GCTAEventList::free_members(void) 619 void GCTAEventList::free_members(void)
611 { 620 {
  621 + // Free columns
  622 + for (int i = 0; i < m_columns.size(); ++i) {
  623 + delete m_columns[i];
  624 + m_columns[i] = NULL;
  625 + }
  626 +
612 // Return 627 // Return
613 return; 628 return;
614 } 629 }
@@ -619,52 +634,26 @@ void GCTAEventList::free_members(void) @@ -619,52 +634,26 @@ void GCTAEventList::free_members(void)
619 * 634 *
620 * @param[in] table FITS table. 635 * @param[in] table FITS table.
621 * 636 *
622 - * This method reads the CTA event list from a FITS table HDU into memory.  
623 - * Depending on the columns existing in the file, it either selects v0 or  
624 - * v1 of the event list reader.  
625 - ***************************************************************************/  
626 -void GCTAEventList::read_events(const GFitsTable& table)  
627 -{  
628 - // Clear existing events  
629 - m_events.clear();  
630 -  
631 - // Extract number of events in FITS file  
632 - int num = table.integer("NAXIS2");  
633 -  
634 - // Continue only if there are events  
635 - if (num > 0) {  
636 -  
637 - // Read events for v1  
638 - if (table.contains("SHWIDTH") && table.contains("SHLENGTH")) {  
639 - read_events_v1(table);  
640 - }  
641 -  
642 - // ... otherwise read events for v0  
643 - else {  
644 - read_events_v0(table);  
645 - }  
646 -  
647 - // Read (optional) Hillas parameters  
648 - read_events_hillas(table);  
649 -  
650 - } // endif: there were events  
651 -  
652 - // Return  
653 - return;  
654 -}  
655 -  
656 -  
657 -/***********************************************************************//**  
658 - * @brief Read CTA events from FITS table (version 0) 637 + * This method reads the CTA event list from a FITS table into memory.
  638 + * The following columns are mandatory in the FITS table:
659 * 639 *
660 - * @param[in] table FITS table. 640 + * - EVENT_ID
  641 + * - TIME
  642 + * - RA
  643 + * - DEC
  644 + * - ENERGY
  645 + *
  646 + * Optionally, the
661 * 647 *
662 - * This method reads the CTA event list from a FITS table HDU into memory.  
663 - * It is a minimal event reader that is compliant with the initial data  
664 - * format distributed by Karl Kosack. Information that is not present in  
665 - * that format is set to 0. 648 + * - DETX
  649 + * - DETY
  650 + * - PHASE
  651 + *
  652 + * columns are read. Any other columns present in the FITS table will also be
  653 + * read, and written into the FITS table when the write_events() method is
  654 + * called.
666 ***************************************************************************/ 655 ***************************************************************************/
667 -void GCTAEventList::read_events_v0(const GFitsTable& table) 656 +void GCTAEventList::read_events(const GFitsTable& table)
668 { 657 {
669 // Clear existing events 658 // Clear existing events
670 m_events.clear(); 659 m_events.clear();
@@ -679,120 +668,25 @@ void GCTAEventList::read_events_v0(const GFitsTable&amp; table) @@ -679,120 +668,25 @@ void GCTAEventList::read_events_v0(const GFitsTable&amp; table)
679 m_events.reserve(num); 668 m_events.reserve(num);
680 669
681 // Get column pointers 670 // Get column pointers
682 - const GFitsTableCol* ptr_eid = table["EVENT_ID"];  
683 - const GFitsTableCol* ptr_time = table["TIME"];  
684 - const GFitsTableCol* ptr_multip = table["MULTIP"];  
685 - const GFitsTableCol* ptr_ra = table["RA"];  
686 - const GFitsTableCol* ptr_dec = table["DEC"];  
687 - const GFitsTableCol* ptr_dir_err = table["DIR_ERR"];  
688 - const GFitsTableCol* ptr_detx = table["DETX"];  
689 - const GFitsTableCol* ptr_dety = table["DETY"];  
690 - const GFitsTableCol* ptr_alt = table["ALT"];  
691 - const GFitsTableCol* ptr_az = table["AZ"];  
692 - const GFitsTableCol* ptr_corex = table["COREX"];  
693 - const GFitsTableCol* ptr_corey = table["COREY"];  
694 - const GFitsTableCol* ptr_core_err = table["CORE_ERR"];  
695 - const GFitsTableCol* ptr_xmax = table["XMAX"];  
696 - const GFitsTableCol* ptr_xmax_err = table["XMAX_ERR"];  
697 - const GFitsTableCol* ptr_energy = table["ENERGY"];  
698 - const GFitsTableCol* ptr_energy_err = table["ENERGY_ERR"];  
699 -  
700 - // Check for phase column  
701 - const GFitsTableCol* ptr_phase;  
702 - if (table.contains("PHASE")) {  
703 - m_has_phase = true;  
704 - ptr_phase = table["PHASE"]; 671 + const GFitsTableCol* ptr_eid = table["EVENT_ID"];
  672 + const GFitsTableCol* ptr_time = table["TIME"];
  673 + const GFitsTableCol* ptr_ra = table["RA"];
  674 + const GFitsTableCol* ptr_dec = table["DEC"];
  675 + const GFitsTableCol* ptr_energy = table["ENERGY"];
  676 +
  677 + // Check for DETX and DETY columns
  678 + const GFitsTableCol* ptr_detx;
  679 + const GFitsTableCol* ptr_dety;
  680 + if (table.contains("DETX") && table.contains("DETY")) {
  681 + m_has_detxy = true;
  682 + ptr_detx = table["DETX"];
  683 + ptr_dety = table["DETY"];
705 } 684 }
706 else { 685 else {
707 - m_has_phase = false;  
708 - }  
709 -  
710 - // Copy data from columns into GCTAEventAtom objects  
711 - GCTAEventAtom event;  
712 - for (int i = 0; i < num; ++i) {  
713 - event.m_index = i;  
714 - event.m_time.set(ptr_time->real(i), m_gti.reference());  
715 - event.m_dir.dir().radec_deg(ptr_ra->real(i), ptr_dec->real(i));  
716 - event.m_dir.detx(ptr_detx->real(i)*gammalib::deg2rad);  
717 - event.m_dir.dety(ptr_dety->real(i)*gammalib::deg2rad);  
718 - event.m_energy.TeV(ptr_energy->real(i));  
719 - event.m_event_id = ptr_eid->integer(i);  
720 - event.m_obs_id = 0;  
721 - event.m_multip = ptr_multip->integer(i);  
722 - event.m_telmask = 0;  
723 - event.m_dir_err = ptr_dir_err->real(i);  
724 - event.m_alt = ptr_alt->real(i);  
725 - event.m_az = ptr_az->real(i);  
726 - event.m_corex = ptr_corex->real(i);  
727 - event.m_corey = ptr_corey->real(i);  
728 - event.m_core_err = ptr_core_err->real(i);  
729 - event.m_xmax = ptr_xmax->real(i);  
730 - event.m_xmax_err = ptr_xmax_err->real(i);  
731 - event.m_shwidth = 0.0;  
732 - event.m_shlength = 0.0;  
733 - event.m_energy_err = ptr_energy_err->real(i);  
734 -  
735 - // Set pulse phase if available  
736 - if (m_has_phase) {  
737 - event.m_phase = ptr_phase->real(i);  
738 - }  
739 -  
740 - m_events.push_back(event); 686 + m_has_detxy = false;
741 } 687 }
742 688
743 - } // endif: there were events  
744 -  
745 - // Return  
746 - return;  
747 -}  
748 -  
749 -  
750 -/***********************************************************************//**  
751 - * @brief Read CTA events from FITS table (version 1)  
752 - *  
753 - * @param[in] table FITS table.  
754 - *  
755 - * This method reads the CTA event list from a FITS table HDU into memory.  
756 - *  
757 - * @todo Implement agreed column format  
758 - ***************************************************************************/  
759 -void GCTAEventList::read_events_v1(const GFitsTable& table)  
760 -{  
761 - // Clear existing events  
762 - m_events.clear();  
763 -  
764 - // Extract number of events in FITS file  
765 - int num = table.nrows();  
766 -  
767 - // If there are events then load them  
768 - if (num > 0) {  
769 -  
770 - // Reserve data  
771 - m_events.reserve(num);  
772 -  
773 - // Get column pointers  
774 - const GFitsTableCol* ptr_eid = table["EVENT_ID"];  
775 - const GFitsTableCol* ptr_oid = table["OBS_ID"];  
776 - const GFitsTableCol* ptr_time = table["TIME"];  
777 - const GFitsTableCol* ptr_multip = table["MULTIP"];  
778 - const GFitsTableCol* ptr_ra = table["RA"];  
779 - const GFitsTableCol* ptr_dec = table["DEC"];  
780 - const GFitsTableCol* ptr_dir_err = table["DIR_ERR"];  
781 - const GFitsTableCol* ptr_detx = table["DETX"];  
782 - const GFitsTableCol* ptr_dety = table["DETY"];  
783 - const GFitsTableCol* ptr_alt = table["ALT"];  
784 - const GFitsTableCol* ptr_az = table["AZ"];  
785 - const GFitsTableCol* ptr_corex = table["COREX"];  
786 - const GFitsTableCol* ptr_corey = table["COREY"];  
787 - const GFitsTableCol* ptr_core_err = table["CORE_ERR"];  
788 - const GFitsTableCol* ptr_xmax = table["XMAX"];  
789 - const GFitsTableCol* ptr_xmax_err = table["XMAX_ERR"];  
790 - const GFitsTableCol* ptr_shw = table["SHWIDTH"];  
791 - const GFitsTableCol* ptr_shl = table["SHLENGTH"];  
792 - const GFitsTableCol* ptr_energy = table["ENERGY"];  
793 - const GFitsTableCol* ptr_energy_err = table["ENERGY_ERR"];  
794 -  
795 - // Check for phase column 689 + // Check for PHASE column
796 const GFitsTableCol* ptr_phase; 690 const GFitsTableCol* ptr_phase;
797 if (table.contains("PHASE")) { 691 if (table.contains("PHASE")) {
798 m_has_phase = true; 692 m_has_phase = true;
@@ -805,98 +699,57 @@ void GCTAEventList::read_events_v1(const GFitsTable&amp; table) @@ -805,98 +699,57 @@ void GCTAEventList::read_events_v1(const GFitsTable&amp; table)
805 // Copy data from columns into GCTAEventAtom objects 699 // Copy data from columns into GCTAEventAtom objects
806 GCTAEventAtom event; 700 GCTAEventAtom event;
807 for (int i = 0; i < num; ++i) { 701 for (int i = 0; i < num; ++i) {
808 - event.m_index = i; 702 +
  703 + // Set mandatory information
809 event.m_time.set(ptr_time->real(i), m_gti.reference()); 704 event.m_time.set(ptr_time->real(i), m_gti.reference());
810 event.m_dir.dir().radec_deg(ptr_ra->real(i), ptr_dec->real(i)); 705 event.m_dir.dir().radec_deg(ptr_ra->real(i), ptr_dec->real(i));
811 - event.m_dir.detx(ptr_detx->real(i)*gammalib::deg2rad);  
812 - event.m_dir.dety(ptr_dety->real(i)*gammalib::deg2rad);  
813 event.m_energy.TeV(ptr_energy->real(i)); 706 event.m_energy.TeV(ptr_energy->real(i));
814 - event.m_event_id = ptr_eid->integer(i);  
815 - event.m_obs_id = ptr_oid->integer(i);  
816 - event.m_multip = ptr_multip->integer(i);  
817 - event.m_telmask = 0;  
818 - event.m_dir_err = ptr_dir_err->real(i);  
819 - event.m_alt = ptr_alt->real(i);  
820 - event.m_az = ptr_az->real(i);  
821 - event.m_corex = ptr_corex->real(i);  
822 - event.m_corey = ptr_corey->real(i);  
823 - event.m_core_err = ptr_core_err->real(i);  
824 - event.m_xmax = ptr_xmax->real(i);  
825 - event.m_xmax_err = ptr_xmax_err->real(i);  
826 - event.m_shwidth = ptr_shw->real(i);  
827 - event.m_shlength = ptr_shl->real(i);  
828 - event.m_energy_err = ptr_energy_err->real(i);  
829 -  
830 - // Set phase if available 707 + event.m_event_id = ptr_eid->integer(i);
  708 + event.m_index = i;
  709 +
  710 + // If available, set detector coordinates in radians
  711 + if (m_has_detxy) {
  712 + event.m_dir.detx(ptr_detx->real(i)*gammalib::deg2rad);
  713 + event.m_dir.dety(ptr_dety->real(i)*gammalib::deg2rad);
  714 + }
  715 +
  716 + // If available, set pulse phase
831 if (m_has_phase) { 717 if (m_has_phase) {
832 event.m_phase = ptr_phase->real(i); 718 event.m_phase = ptr_phase->real(i);
833 } 719 }
834 720
  721 + // Append event
835 m_events.push_back(event); 722 m_events.push_back(event);
836 - }  
837 723
838 - } // endif: there were events 724 + } // endfor: looped over all events
839 725
840 - // Return  
841 - return;  
842 -} 726 + // Loop over table and find optional columns
  727 + for (int i = 0; i < table.ncols(); ++i) {
843 728
  729 + // Get column pointer
  730 + const GFitsTableCol* col = table[i];
844 731
845 -/***********************************************************************//**  
846 - * @brief Read Hillas information for CTA events from FITS table  
847 - *  
848 - * @param[in] table FITS table.  
849 - *  
850 - * This method reads the Hillas reconstruction information for CTA events  
851 - * from an EVENTS file. It searches for the columns HIL_MSW, HIL_MSW_ERR,  
852 - * HIL_MSL, and HIL_MSL_ERR in the FITS table and extracts the relevant  
853 - * columns from the FITS file. If a column is not found, no action is  
854 - * performed.  
855 - *  
856 - * @todo Verify consistency of event list size  
857 - ***************************************************************************/  
858 -void GCTAEventList::read_events_hillas(const GFitsTable& table)  
859 -{  
860 - // Extract number of events in FITS file  
861 - int num = table.nrows(); 732 + // Get column name
  733 + const std::string name = col->name();
862 734
863 - //TODO: Make sure that dimension is consistent with existing event  
864 - // list  
865 -  
866 - // Continue only if there are events  
867 - if (num > 0) {  
868 -  
869 - // HIL_MSW  
870 - if (table.contains("HIL_MSW")) {  
871 - const GFitsTableCol* ptr = table["HIL_MSW"];  
872 - for (int i = 0; i < num; ++i) {  
873 - m_events[i].m_hil_msw = ptr->real(i);  
874 - }  
875 - }  
876 -  
877 - // HIL_MSW_ERR  
878 - if (table.contains("HIL_MSW_ERR")) {  
879 - const GFitsTableCol* ptr = table["HIL_MSW_ERR"];  
880 - for (int i = 0; i < num; ++i) {  
881 - m_events[i].m_hil_msw_err = ptr->real(i); 735 + // If column was mandatory or optional then skip it ...
  736 + if (name == "EVENT_ID" ||
  737 + name == "TIME" ||
  738 + name == "RA" ||
  739 + name == "DEC" ||
  740 + name == "ENERGY" ||
  741 + name == "DETX" ||
  742 + name == "DETY" ||
  743 + name == "PHASE") {
  744 + continue;
882 } 745 }
883 - }  
884 746
885 - // HIL_MSL  
886 - if (table.contains("HIL_MSL")) {  
887 - const GFitsTableCol* ptr = table["HIL_MSL"];  
888 - for (int i = 0; i < num; ++i) {  
889 - m_events[i].m_hil_msl = ptr->real(i); 747 + // ... otherwise keep a copy
  748 + else {
  749 + m_columns.push_back(col->clone());
890 } 750 }
891 - }  
892 751
893 - // HIL_MSL_ERR  
894 - if (table.contains("HIL_MSL_ERR")) {  
895 - const GFitsTableCol* ptr = table["HIL_MSL_ERR"];  
896 - for (int i = 0; i < num; ++i) {  
897 - m_events[i].m_hil_msl_err = ptr->real(i);  
898 - }  
899 - } 752 + } // endfor: loop over optional columns
900 753
901 } // endif: there were events 754 } // endif: there were events
902 755
@@ -908,12 +761,26 @@ void GCTAEventList::read_events_hillas(const GFitsTable&amp; table) @@ -908,12 +761,26 @@ void GCTAEventList::read_events_hillas(const GFitsTable&amp; table)
908 /***********************************************************************//** 761 /***********************************************************************//**
909 * @brief Write CTA events into FITS table 762 * @brief Write CTA events into FITS table
910 * 763 *
911 - * @param[in] hdu FITS table HDU. 764 + * @param[in] table FITS binary table.
912 * 765 *
913 - * Write the CTA event list into FITS table. 766 + * Write the CTA event list into a FITS binary table.
914 * 767 *
915 - * @todo The TELMASK column is allocated with a dummy length of 100.  
916 - * @todo Implement agreed column format 768 + * The following mandatory columns will be written into the FITS table:
  769 + *
  770 + * - EVENT_ID
  771 + * - TIME
  772 + * - RA
  773 + * - DEC
  774 + * - ENERGY
  775 + *
  776 + * If available, also the
  777 + *
  778 + * - DETX
  779 + * - DETY
  780 + * - PHASE
  781 + *
  782 + * columns are written. Any other columns that were read by the read_events()
  783 + * method will be also written into the table.
917 ***************************************************************************/ 784 ***************************************************************************/
918 void GCTAEventList::write_events(GFitsBinTable& hdu) const 785 void GCTAEventList::write_events(GFitsBinTable& hdu) const
919 { 786 {
@@ -923,109 +790,55 @@ void GCTAEventList::write_events(GFitsBinTable&amp; hdu) const @@ -923,109 +790,55 @@ void GCTAEventList::write_events(GFitsBinTable&amp; hdu) const
923 // If there are events then write them now 790 // If there are events then write them now
924 if (size() > 0) { 791 if (size() > 0) {
925 792
926 - // Allocate columns  
927 - GFitsTableULongCol col_eid = GFitsTableULongCol("EVENT_ID", size());  
928 - GFitsTableULongCol col_oid = GFitsTableULongCol("OBS_ID", size());  
929 - GFitsTableDoubleCol col_time = GFitsTableDoubleCol("TIME", size());  
930 - GFitsTableDoubleCol col_live = GFitsTableDoubleCol("TLIVE", size());  
931 - GFitsTableShortCol col_multip = GFitsTableShortCol("MULTIP", size());  
932 - GFitsTableBitCol col_telmask = GFitsTableBitCol("TELMASK", size(), 100);  
933 - GFitsTableFloatCol col_ra = GFitsTableFloatCol("RA", size());  
934 - GFitsTableFloatCol col_dec = GFitsTableFloatCol("DEC", size());  
935 - GFitsTableFloatCol col_direrr = GFitsTableFloatCol("DIR_ERR", size());  
936 - GFitsTableFloatCol col_detx = GFitsTableFloatCol("DETX", size());  
937 - GFitsTableFloatCol col_dety = GFitsTableFloatCol("DETY", size());  
938 - GFitsTableFloatCol col_alt = GFitsTableFloatCol("ALT", size());  
939 - GFitsTableFloatCol col_az = GFitsTableFloatCol("AZ", size());  
940 - GFitsTableFloatCol col_corex = GFitsTableFloatCol("COREX", size());  
941 - GFitsTableFloatCol col_corey = GFitsTableFloatCol("COREY", size());  
942 - GFitsTableFloatCol col_core_err = GFitsTableFloatCol("CORE_ERR", size());  
943 - GFitsTableFloatCol col_xmax = GFitsTableFloatCol("XMAX", size());  
944 - GFitsTableFloatCol col_xmax_err = GFitsTableFloatCol("XMAX_ERR", size());  
945 - GFitsTableFloatCol col_shw = GFitsTableFloatCol("SHWIDTH", size());  
946 - GFitsTableFloatCol col_shl = GFitsTableFloatCol("SHLENGTH", size());  
947 - GFitsTableFloatCol col_energy = GFitsTableFloatCol("ENERGY", size());  
948 - GFitsTableFloatCol col_energy_err = GFitsTableFloatCol("ENERGY_ERR", size());  
949 - GFitsTableFloatCol col_hil_msw = GFitsTableFloatCol("HIL_MSW", size());  
950 - GFitsTableFloatCol col_hil_msw_err = GFitsTableFloatCol("HIL_MSW_ERR", size());  
951 - GFitsTableFloatCol col_hil_msl = GFitsTableFloatCol("HIL_MSL", size());  
952 - GFitsTableFloatCol col_hil_msl_err = GFitsTableFloatCol("HIL_MSL_ERR", size());  
953 -  
954 - // Create phase column if required  
955 - GFitsTableFloatCol col_phase;  
956 - if (m_has_phase) {  
957 - col_phase = GFitsTableFloatCol("PHASE", size());  
958 - } 793 + // Allocate mandatory columns
  794 + GFitsTableULongCol col_eid = GFitsTableULongCol("EVENT_ID", size());
  795 + GFitsTableDoubleCol col_time = GFitsTableDoubleCol("TIME", size());
  796 + GFitsTableFloatCol col_ra = GFitsTableFloatCol("RA", size());
  797 + GFitsTableFloatCol col_dec = GFitsTableFloatCol("DEC", size());
  798 + GFitsTableFloatCol col_energy = GFitsTableFloatCol("ENERGY", size());
959 799
960 - // Fill columns 800 + // Fill mandatory columns
961 for (int i = 0; i < size(); ++i) { 801 for (int i = 0; i < size(); ++i) {
962 - col_eid(i) = m_events[i].m_event_id;  
963 - col_oid(i) = m_events[i].m_obs_id;  
964 - col_time(i) = m_events[i].time().convert(m_gti.reference());  
965 - col_live(i) = 0.0;  
966 - col_multip(i) = 0;  
967 - //col_telmask  
968 - col_ra(i) = m_events[i].dir().dir().ra_deg();  
969 - col_dec(i) = m_events[i].dir().dir().dec_deg();  
970 - col_direrr(i) = m_events[i].m_dir_err;  
971 - col_detx(i) = m_events[i].dir().detx() * gammalib::rad2deg;  
972 - col_dety(i) = m_events[i].dir().dety() * gammalib::rad2deg;  
973 - col_alt(i) = m_events[i].m_alt;  
974 - col_az(i) = m_events[i].m_az;  
975 - col_corex(i) = m_events[i].m_corex;  
976 - col_corey(i) = m_events[i].m_corey;  
977 - col_core_err(i) = m_events[i].m_core_err;  
978 - col_xmax(i) = m_events[i].m_xmax;  
979 - col_xmax_err(i) = m_events[i].m_xmax_err;  
980 - col_shw(i) = m_events[i].m_shwidth;  
981 - col_shl(i) = m_events[i].m_shlength;  
982 - col_energy(i) = m_events[i].energy().TeV();  
983 - col_energy_err(i) = m_events[i].m_energy_err;  
984 - col_hil_msw(i) = m_events[i].m_hil_msw;  
985 - col_hil_msw_err(i) = m_events[i].m_hil_msw_err;  
986 - col_hil_msl(i) = m_events[i].m_hil_msl;  
987 - col_hil_msl_err(i) = m_events[i].m_hil_msl_err;  
988 -  
989 - // Optionally fill pulse phase column  
990 - if (m_has_phase) {  
991 - col_phase(i) = m_events[i].m_phase;  
992 - }  
993 -  
994 - } // endfor: looped over rows 802 + col_eid(i) = m_events[i].m_event_id;
  803 + col_time(i) = m_events[i].time().convert(m_gti.reference());
  804 + col_ra(i) = m_events[i].dir().dir().ra_deg();
  805 + col_dec(i) = m_events[i].dir().dir().dec_deg();
  806 + col_energy(i) = m_events[i].energy().TeV();
  807 + }
995 808
996 - // Append columns to table 809 + // Append mandatory columns to table
997 hdu.append(col_eid); 810 hdu.append(col_eid);
998 - hdu.append(col_oid);  
999 hdu.append(col_time); 811 hdu.append(col_time);
1000 - hdu.append(col_live);  
1001 - hdu.append(col_multip);  
1002 - hdu.append(col_telmask);  
1003 hdu.append(col_ra); 812 hdu.append(col_ra);
1004 hdu.append(col_dec); 813 hdu.append(col_dec);
1005 - hdu.append(col_direrr);  
1006 - hdu.append(col_detx);  
1007 - hdu.append(col_dety);  
1008 - hdu.append(col_alt);  
1009 - hdu.append(col_az);  
1010 - hdu.append(col_corex);  
1011 - hdu.append(col_corey);  
1012 - hdu.append(col_core_err);  
1013 - hdu.append(col_xmax);  
1014 - hdu.append(col_xmax_err);  
1015 - hdu.append(col_shw);  
1016 - hdu.append(col_shl);  
1017 hdu.append(col_energy); 814 hdu.append(col_energy);
1018 - hdu.append(col_energy_err);  
1019 - hdu.append(col_hil_msw);  
1020 - hdu.append(col_hil_msw_err);  
1021 - hdu.append(col_hil_msl);  
1022 - hdu.append(col_hil_msl_err);  
1023 815
1024 - // Optionally write phase column 816 + // If available, add detector coordinates in degrees
  817 + if (m_has_detxy) {
  818 + GFitsTableFloatCol col_detx = GFitsTableFloatCol("DETX", size());
  819 + GFitsTableFloatCol col_dety = GFitsTableFloatCol("DETY", size());
  820 + for (int i = 0; i < size(); ++i) {
  821 + col_detx(i) = m_events[i].dir().detx() * gammalib::rad2deg;
  822 + col_dety(i) = m_events[i].dir().dety() * gammalib::rad2deg;
  823 + }
  824 + hdu.append(col_detx);
  825 + hdu.append(col_dety);
  826 + }
  827 +
  828 + // If available, add event phase
1025 if (m_has_phase) { 829 if (m_has_phase) {
  830 + GFitsTableFloatCol col_phase = GFitsTableFloatCol("PHASE", size());
  831 + for (int i = 0; i < size(); ++i) {
  832 + col_phase(i) = m_events[i].m_phase;
  833 + }
1026 hdu.append(col_phase); 834 hdu.append(col_phase);
1027 } 835 }
1028 836
  837 + // Append other columns to table
  838 + for (int i = 0; i < m_columns.size(); ++i) {
  839 + hdu.append(*m_columns[i]);
  840 + }
  841 +
1029 } // endif: there were events to write 842 } // endif: there were events to write
1030 843
1031 // Return 844 // Return
pyext/GModel.i
@@ -72,6 +72,7 @@ public: @@ -72,6 +72,7 @@ public:
72 void ts(const double& ts); 72 void ts(const double& ts);
73 const bool& tscalc(void) const; 73 const bool& tscalc(void) const;
74 void tscalc(const bool& tscalc); 74 void tscalc(const bool& tscalc);
  75 + const bool& has_ts(void) const;
75 GModelPar scale(const std::string& instrument) const; 76 GModelPar scale(const std::string& instrument) const;
76 void scale(const GModelPar& par); 77 void scale(const GModelPar& par);
77 std::string ids(void) const; 78 std::string ids(void) const;
src/vo/GVOClient.cpp
@@ -517,7 +517,7 @@ bool GVOClient::find_hub(void) @@ -517,7 +517,7 @@ bool GVOClient::find_hub(void)
517 if (!lockurl.empty()) { 517 if (!lockurl.empty()) {
518 518
519 // If we have a file:// prefix then strip it now. This is a kluge 519 // If we have a file:// prefix then strip it now. This is a kluge
520 - // and should be remplaced by a method that allows opening any kind 520 + // and should be replaced by a method that allows opening any kind
521 // of URL 521 // of URL
522 if (lockurl.compare(0, 7, "file://") == 0) { 522 if (lockurl.compare(0, 7, "file://") == 0) {
523 lockurl = lockurl.substr(7, std::string::npos); 523 lockurl = lockurl.substr(7, std::string::npos);
@@ -955,7 +955,6 @@ std::string GVOClient::receive_string(void) const @@ -955,7 +955,6 @@ std::string GVOClient::receive_string(void) const
955 int n = 0; 955 int n = 0;
956 do { 956 do {
957 n = gammalib::recv(m_socket, buffer, 1000, 0, timeout); 957 n = gammalib::recv(m_socket, buffer, 1000, 0, timeout);
958 - //n = recv(m_socket, buffer, 1000, 0);  
959 if (n > 0) { 958 if (n > 0) {
960 buffer[n] = '\0'; 959 buffer[n] = '\0';
961 result.append(std::string(buffer)); 960 result.append(std::string(buffer));
@@ -1074,7 +1073,7 @@ std::string GVOClient::get_hub_lockfile(void) const @@ -1074,7 +1073,7 @@ std::string GVOClient::get_hub_lockfile(void) const
1074 char* hub_ptr = std::getenv("SAMP_HUB"); 1073 char* hub_ptr = std::getenv("SAMP_HUB");
1075 if (hub_ptr != NULL) { 1074 if (hub_ptr != NULL) {
1076 1075
1077 - // Check for mandatory std-lockurl: prefix (no other prefixe is 1076 + // Check for mandatory std-lockurl: prefix (no other prefix is
1078 // supported so far) 1077 // supported so far)
1079 std::string lockurl = std::string(hub_ptr); 1078 std::string lockurl = std::string(hub_ptr);
1080 if (lockurl.compare(0, 12, "std-lockurl:") == 0) { 1079 if (lockurl.compare(0, 12, "std-lockurl:") == 0) {
@@ -1084,7 +1083,7 @@ std::string GVOClient::get_hub_lockfile(void) const @@ -1084,7 +1083,7 @@ std::string GVOClient::get_hub_lockfile(void) const
1084 1083
1085 } // endif: std-lockurl: prefix found 1084 } // endif: std-lockurl: prefix found
1086 1085
1087 - } 1086 + } // endif: SAMP_HUB environment variable found
1088 1087
1089 // ... otherwise the lockfile should be $HOME/.samp 1088 // ... otherwise the lockfile should be $HOME/.samp
1090 else { 1089 else {
src/vo/GVOHub.cpp
@@ -47,6 +47,7 @@ @@ -47,6 +47,7 @@
47 47
48 /* __ Method name definitions ____________________________________________ */ 48 /* __ Method name definitions ____________________________________________ */
49 #define G_START_HUB "GVOHub::start_hub()" 49 #define G_START_HUB "GVOHub::start_hub()"
  50 +#define G_START_SOCKET "GVOHub::start_socket()"
50 51
51 /* __ Macros _____________________________________________________________ */ 52 /* __ Macros _____________________________________________________________ */
52 53
@@ -179,9 +180,6 @@ GVOHub* GVOHub::clone(void) const @@ -179,9 +180,6 @@ GVOHub* GVOHub::clone(void) const
179 ***************************************************************************/ 180 ***************************************************************************/
180 void GVOHub::start(void) 181 void GVOHub::start(void)
181 { 182 {
182 - // Create SAMP file  
183 - create_samp_file();  
184 -  
185 // Start Hub 183 // Start Hub
186 start_hub(); 184 start_hub();
187 185
@@ -210,7 +208,7 @@ std::string GVOHub::print(const GChatter&amp; chatter) const @@ -210,7 +208,7 @@ std::string GVOHub::print(const GChatter&amp; chatter) const
210 // Append Hub information 208 // Append Hub information
211 result.append("\n"+gammalib::parformat("Hub identifier")+m_hub_id); 209 result.append("\n"+gammalib::parformat("Hub identifier")+m_hub_id);
212 result.append("\n"+gammalib::parformat("Hub key")+m_secret); 210 result.append("\n"+gammalib::parformat("Hub key")+m_secret);
213 - result.append("\n"+gammalib::parformat("Hub URL")+m_hub_url); 211 + result.append("\n"+gammalib::parformat("Hub URL")+hub_url());
214 result.append("\n"+gammalib::parformat("Hub host")+m_hub_host); 212 result.append("\n"+gammalib::parformat("Hub host")+m_hub_host);
215 result.append("\n"+gammalib::parformat("Hub port")+m_hub_port); 213 result.append("\n"+gammalib::parformat("Hub port")+m_hub_port);
216 result.append("\n"+gammalib::parformat("Hub path")+m_hub_path); 214 result.append("\n"+gammalib::parformat("Hub path")+m_hub_path);
@@ -240,7 +238,6 @@ void GVOHub::init_members(void) @@ -240,7 +238,6 @@ void GVOHub::init_members(void)
240 m_hub_host = "127.0.0.1"; 238 m_hub_host = "127.0.0.1";
241 m_hub_port = "2526"; 239 m_hub_port = "2526";
242 m_hub_path = "xmlrpc"; 240 m_hub_path = "xmlrpc";
243 - m_hub_url = "http://"+m_hub_host+":"+m_hub_port+"/"+m_hub_path;  
244 m_version = "1.3"; 241 m_version = "1.3";
245 m_hub_id = "gammalib_hub"; 242 m_hub_id = "gammalib_hub";
246 m_socket = -1; // Signals no socket 243 m_socket = -1; // Signals no socket
@@ -261,7 +258,6 @@ void GVOHub::copy_members(const GVOHub&amp; hub) @@ -261,7 +258,6 @@ void GVOHub::copy_members(const GVOHub&amp; hub)
261 { 258 {
262 // Copy members 259 // Copy members
263 m_secret = hub.m_secret; 260 m_secret = hub.m_secret;
264 - m_hub_url = hub.m_hub_url;  
265 m_hub_host = hub.m_hub_host; 261 m_hub_host = hub.m_hub_host;
266 m_hub_port = hub.m_hub_port; 262 m_hub_port = hub.m_hub_port;
267 m_hub_path = hub.m_hub_path; 263 m_hub_path = hub.m_hub_path;
@@ -288,8 +284,7 @@ void GVOHub::free_members(void) @@ -288,8 +284,7 @@ void GVOHub::free_members(void)
288 } 284 }
289 285
290 // Remove lockfile 286 // Remove lockfile
291 - std::string lockurl = get_hub_lockfile();  
292 - std::remove(lockurl.c_str()); 287 + delete_samp_file();
293 288
294 // Return 289 // Return
295 return; 290 return;
@@ -306,46 +301,13 @@ void GVOHub::free_members(void) @@ -306,46 +301,13 @@ void GVOHub::free_members(void)
306 ***************************************************************************/ 301 ***************************************************************************/
307 void GVOHub::start_hub(void) 302 void GVOHub::start_hub(void)
308 { 303 {
309 - // Prepare TCP/IP structure  
310 - struct sockaddr_in serv_addr;  
311 - std::memset(&serv_addr, 0, sizeof(serv_addr));  
312 - serv_addr.sin_family = AF_INET;  
313 - serv_addr.sin_addr.s_addr = inet_addr(m_hub_host.c_str());  
314 - serv_addr.sin_port = htons(gammalib::toint(m_hub_port));  
315 -  
316 - // Create Hub socket  
317 - m_socket = socket(AF_INET, SOCK_STREAM, 0);  
318 -  
319 - // Creation of hub main socket  
320 - if (m_socket < 0) {  
321 - std::string msg = "Unable to create Hub socket. Errno="+  
322 - gammalib::str(errno);  
323 - throw GException::runtime_error(G_START_HUB, msg);  
324 - }  
325 -  
326 - // Set hub main socket to allow multiple connections  
327 - int opt = 1;  
328 - if (setsockopt(m_socket, SOL_SOCKET, SO_REUSEADDR, (char*)&opt, sizeof(opt)) < 0) {  
329 - std::string msg = "Unable to set Hub socket to multiple connections."  
330 - " Errno="+gammalib::str(errno);  
331 - throw GException::runtime_error(G_START_HUB, msg);  
332 - }  
333 - #ifdef SO_REUSEPORT  
334 - if (setsockopt(m_socket, SOL_SOCKET, SO_REUSEPORT, (char*)&opt, sizeof(opt)) < 0) {  
335 - std::string msg = "Unable to set Hub socket to multiple connections."  
336 - " Errno="+gammalib::str(errno);  
337 - throw GException::runtime_error(G_START_HUB, msg);  
338 - }  
339 - #endif  
340 -  
341 - // Server socket is opened. Now, bind it to the port, with family etc.  
342 - if (bind(m_socket, (struct sockaddr*)&serv_addr, sizeof(serv_addr)) < 0) {  
343 - std::string msg = "Unable to bind Hub socket to server socket. Errno="+  
344 - gammalib::str(errno);  
345 - throw GException::runtime_error(G_START_HUB, msg);  
346 - } 304 + // Get socket
  305 + m_socket = get_socket();
  306 +
  307 + // Create SAMP file
  308 + create_samp_file();
347 309
348 - // Now start listening for the clients: 5 requests simultaneously pending 310 + // Start listening for the clients: 5 requests simultaneously pending
349 // at maximum 311 // at maximum
350 if (listen(m_socket, 5) < 0) { 312 if (listen(m_socket, 5) < 0) {
351 std::string msg = "Unable to start listening on Hub socket. Errno="+ 313 std::string msg = "Unable to start listening on Hub socket. Errno="+
@@ -385,6 +347,9 @@ void GVOHub::start_hub(void) @@ -385,6 +347,9 @@ void GVOHub::start_hub(void)
385 close(m_socket); 347 close(m_socket);
386 m_socket = -1; 348 m_socket = -1;
387 349
  350 + // Delete SAMP file
  351 + delete_samp_file();
  352 +
388 // Return 353 // Return
389 return; 354 return;
390 } 355 }
@@ -596,7 +561,7 @@ void GVOHub::request_register(const GXml&amp; xml, const socklen_t&amp; sock) @@ -596,7 +561,7 @@ void GVOHub::request_register(const GXml&amp; xml, const socklen_t&amp; sock)
596 response.append(" </member>\n"); 561 response.append(" </member>\n");
597 response.append(" <member>\n"); 562 response.append(" <member>\n");
598 response.append(" <name>samp.url-translator</name>\n"); 563 response.append(" <name>samp.url-translator</name>\n");
599 - response.append(" <value>"+m_hub_url+"</value>\n"); 564 + response.append(" <value>"+hub_url()+"</value>\n");
600 response.append(" </member>\n"); 565 response.append(" </member>\n");
601 response.append(" </struct></value></param>\n"); 566 response.append(" </struct></value></param>\n");
602 response.append("</params>\n"); 567 response.append("</params>\n");
@@ -1628,9 +1593,10 @@ void GVOHub::send_notifications(const std::string&amp; method, @@ -1628,9 +1593,10 @@ void GVOHub::send_notifications(const std::string&amp; method,
1628 1593
1629 1594
1630 /***********************************************************************//** 1595 /***********************************************************************//**
1631 - * @brief Creates the lockfile, fill it 1596 + * @brief Create the lockfile
1632 * 1597 *
1633 - * Implements IVOA standard REC-SAMP-1.3-20120411. 1598 + * Creates the SAMP lockfile and fill it with information. Implements IVOA
  1599 + * standard REC-SAMP-1.3-20120411.
1634 ***************************************************************************/ 1600 ***************************************************************************/
1635 void GVOHub::create_samp_file(void) const 1601 void GVOHub::create_samp_file(void) const
1636 { 1602 {
@@ -1647,7 +1613,7 @@ void GVOHub::create_samp_file(void) const @@ -1647,7 +1613,7 @@ void GVOHub::create_samp_file(void) const
1647 fprintf(fptr, "# SAMP lockfile\n"); 1613 fprintf(fptr, "# SAMP lockfile\n");
1648 fprintf(fptr, "# Required keys:\n"); 1614 fprintf(fptr, "# Required keys:\n");
1649 fprintf(fptr, "samp.secret=%s\n", m_secret.c_str()); 1615 fprintf(fptr, "samp.secret=%s\n", m_secret.c_str());
1650 - fprintf(fptr, "samp.hub.xmlrpc.url=%s\n", m_hub_url.c_str()); 1616 + fprintf(fptr, "samp.hub.xmlrpc.url=%s\n", hub_url().c_str());
1651 fprintf(fptr, "samp.profile.version=%s\n", m_version.c_str()); 1617 fprintf(fptr, "samp.profile.version=%s\n", m_version.c_str());
1652 fprintf(fptr, "# Info stored by hub for some private reason:\n"); 1618 fprintf(fptr, "# Info stored by hub for some private reason:\n");
1653 fprintf(fptr, "gammalib.hubid=%s\n", m_hub_id.c_str()); 1619 fprintf(fptr, "gammalib.hubid=%s\n", m_hub_id.c_str());
@@ -1663,6 +1629,87 @@ void GVOHub::create_samp_file(void) const @@ -1663,6 +1629,87 @@ void GVOHub::create_samp_file(void) const
1663 1629
1664 1630
1665 /***********************************************************************//** 1631 /***********************************************************************//**
  1632 + * @brief Delete the lockfile
  1633 + *
  1634 + * Deletes the SAMP lockfile on disk.
  1635 + ***************************************************************************/
  1636 +void GVOHub::delete_samp_file(void) const
  1637 +{
  1638 + // Get lockfile URL
  1639 + std::string lockurl = get_hub_lockfile();
  1640 +
  1641 + // Delete lockfile
  1642 + std::remove(lockurl.c_str());
  1643 +
  1644 + // Return
  1645 + return;
  1646 +}
  1647 +
  1648 +
  1649 +/***********************************************************************//**
  1650 + * @brief Get Hub socket
  1651 + *
  1652 + * @return Hub socket (-1 if no socket was found).
  1653 + *
  1654 + * Returns Hub socket. Starting from an initial port of 2526 the method
  1655 + * searches for the next free port and binds it to a socket.
  1656 + ***************************************************************************/
  1657 +int GVOHub::get_socket(void)
  1658 +{
  1659 + // Initialise socket, port and socket address structure
  1660 + int sock = -1;
  1661 + int port = 2526;
  1662 + struct sockaddr_in serv_addr;
  1663 +
  1664 + // Loop over 100 ports at most
  1665 + for (int i = 0; i < 100; ++i) {
  1666 +
  1667 + // Clean TCP/IP structure
  1668 + std::memset(&serv_addr, 0, sizeof(serv_addr));
  1669 +
  1670 + // Set TCP/IP structure
  1671 + serv_addr.sin_family = AF_INET;
  1672 + serv_addr.sin_addr.s_addr = inet_addr(m_hub_host.c_str());
  1673 + serv_addr.sin_port = htons(port);
  1674 +
  1675 + // Create Hub socket
  1676 + sock = socket(AF_INET, SOCK_STREAM, 0);
  1677 +
  1678 + // Creation of hub main socket
  1679 + if (sock < 0) {
  1680 + std::string msg = "Unable to create Hub socket. Errno="+
  1681 + gammalib::str(errno);
  1682 + throw GException::runtime_error(G_START_SOCKET, msg);
  1683 + }
  1684 +
  1685 + // Now bind socket to the address and port
  1686 + if (bind(sock, (struct sockaddr*)&serv_addr, sizeof(serv_addr)) < 0) {
  1687 + if (errno == EADDRINUSE) {
  1688 + port++;
  1689 + close(sock);
  1690 + }
  1691 + else {
  1692 + std::string msg = "Unable to bind Hub socket to address "+
  1693 + m_hub_host+":"+gammalib::str(port)+
  1694 + ". Errno="+gammalib::str(errno);
  1695 + throw GException::runtime_error(G_START_HUB, msg);
  1696 + }
  1697 + }
  1698 + else {
  1699 + break;
  1700 + }
  1701 +
  1702 + } // endfor: looped over ports
  1703 +
  1704 + // Store port as string
  1705 + m_hub_port = gammalib::str(port);
  1706 +
  1707 + // Return socket
  1708 + return sock;
  1709 +}
  1710 +
  1711 +
  1712 +/***********************************************************************//**
1666 * @brief Post string content to client 1713 * @brief Post string content to client
1667 * 1714 *
1668 * @param[in] content String content to post. 1715 * @param[in] content String content to post.
@@ -1948,3 +1995,20 @@ std::string GVOHub::random_string(const size_t&amp; length) const @@ -1948,3 +1995,20 @@ std::string GVOHub::random_string(const size_t&amp; length) const
1948 return str; 1995 return str;
1949 } 1996 }
1950 1997
  1998 +
  1999 +/***********************************************************************//**
  2000 + * @brief Return Hub URL
  2001 + *
  2002 + * @return Hub URL.
  2003 + *
  2004 + * Returns the XML-RPC endpoint for communication with the hub.
  2005 + ***************************************************************************/
  2006 +std::string GVOHub::hub_url(void) const
  2007 +{
  2008 + // Set Hub URL
  2009 + std::string hub_url = "http://"+m_hub_host+":"+m_hub_port+"/"+m_hub_path;
  2010 +
  2011 + // Return Hub URL
  2012 + return (hub_url);
  2013 +}
  2014 +
test/test_GVO.cpp
@@ -175,6 +175,10 @@ int main(void) @@ -175,6 +175,10 @@ int main(void)
175 // Allocate test suit container 175 // Allocate test suit container
176 GTestSuites testsuites("VO module"); 176 GTestSuites testsuites("VO module");
177 177
  178 + // Unset HOME environment variable (so that the .samp file is written
  179 + // into the test directory)
  180 + unsetenv("HOME");
  181 +
178 // Initially assume that we pass all tests 182 // Initially assume that we pass all tests
179 bool success = true; 183 bool success = true;
180 184