00001 /*************************************************************************** 00002 * GCTAOnOffObservations.cpp - ON/OFF Observation container class * 00003 * ----------------------------------------------------------------------- * 00004 * copyright (C) 2013-2015 by Pierrick Martin * 00005 * ----------------------------------------------------------------------- * 00006 * * 00007 * This program is free software: you can redistribute it and/or modify * 00008 * it under the terms of the GNU General Public License as published by * 00009 * the Free Software Foundation, either version 3 of the License, or * 00010 * (at your option) any later version. * 00011 * * 00012 * This program is distributed in the hope that it will be useful, * 00013 * but WITHOUT ANY WARRANTY; without even the implied warranty of * 00014 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * 00015 * GNU General Public License for more details. * 00016 * * 00017 * You should have received a copy of the GNU General Public License * 00018 * along with this program. If not, see <http://www.gnu.org/licenses/>. * 00019 * * 00020 ***************************************************************************/ 00021 /** 00022 * @file GCTAOnOffObservations.cpp 00023 * @brief ON/OFF Observations container class implementation 00024 * @author Pierrick Martin 00025 */ 00026 00027 /* __ Includes ___________________________________________________________ */ 00028 #ifdef HAVE_CONFIG_H 00029 #include <config.h> 00030 #endif 00031 #include "GTools.hpp" 00032 #include "GFilename.hpp" 00033 #include "GException.hpp" 00034 #include "GCTAOnOffObservations.hpp" 00035 00036 /* __ Method name definitions ____________________________________________ */ 00037 #define G_AT "GCTAOnOffObservations::at(int&)" 00038 #define G_SET "GCTAOnOffObservations::set(int&, GCTAOnOffObservation&)" 00039 #define G_APPEND "GCTAOnOffObservations::append(GCTAOnOffObservation&)" 00040 #define G_INSERT "GCTAOnOffObservations::insert(int&, GCTAOnOffObservation&)" 00041 #define G_REMOVE "GCTAOnOffObservations::remove(int&)" 00042 #define G_EXTEND "GCTAOnOffObservations::extend(GCTAOnOffObservations&)" 00043 #define G_READ "GCTAOnOffObservations::read(GXml&)" 00044 00045 /* __ Macros _____________________________________________________________ */ 00046 00047 /* __ Coding definitions _________________________________________________ */ 00048 00049 /* __ Debug definitions __________________________________________________ */ 00050 00051 00052 /*========================================================================== 00053 = = 00054 = Constructors/destructors = 00055 = = 00056 ==========================================================================*/ 00057 00058 /***********************************************************************//** 00059 * @brief Void constructor 00060 ***************************************************************************/ 00061 GCTAOnOffObservations::GCTAOnOffObservations(void) 00062 { 00063 // Initialise members 00064 init_members(); 00065 00066 // Return 00067 return; 00068 } 00069 00070 00071 /***********************************************************************//** 00072 * @brief Copy constructor 00073 * 00074 * @param obs Observation container. 00075 ***************************************************************************/ 00076 GCTAOnOffObservations::GCTAOnOffObservations(const GCTAOnOffObservations& obs) 00077 { 00078 // Initialise members 00079 init_members(); 00080 00081 // Copy members 00082 copy_members(obs); 00083 00084 // Return 00085 return; 00086 } 00087 00088 00089 /***********************************************************************//** 00090 * @brief Load constructor 00091 * 00092 * @param[in] filename XML filename. 00093 * 00094 * Construct the observation container by loading all relevant information 00095 * from a XML file. Please refer to the read() method for more information 00096 * about the structure of the XML file. 00097 ***************************************************************************/ 00098 GCTAOnOffObservations::GCTAOnOffObservations(const GFilename& filename) 00099 { 00100 // Initialise members 00101 init_members(); 00102 00103 // Load XML file 00104 load(filename); 00105 00106 // Return 00107 return; 00108 } 00109 00110 00111 /***********************************************************************//** 00112 * @brief Destructor 00113 ***************************************************************************/ 00114 GCTAOnOffObservations::~GCTAOnOffObservations(void) 00115 { 00116 // Free members 00117 free_members(); 00118 00119 // Return 00120 return; 00121 } 00122 00123 00124 /*========================================================================== 00125 = = 00126 = Operators = 00127 = = 00128 ==========================================================================*/ 00129 00130 /***********************************************************************//** 00131 * @brief Assignment operator 00132 * 00133 * @param[in] obs Observation container. 00134 * @return Observation container. 00135 ***************************************************************************/ 00136 GCTAOnOffObservations& GCTAOnOffObservations::operator=(const GCTAOnOffObservations& obs) 00137 { 00138 // Execute only if object is not identical 00139 if (this != &obs) { 00140 00141 // Free members 00142 free_members(); 00143 00144 // Initialise members 00145 init_members(); 00146 00147 // Copy members 00148 copy_members(obs); 00149 00150 } // endif: object was not identical 00151 00152 // Return this object 00153 return *this; 00154 } 00155 00156 00157 /*========================================================================== 00158 = = 00159 = Public methods = 00160 = = 00161 ==========================================================================*/ 00162 00163 /***********************************************************************//** 00164 * @brief Clear observations 00165 ***************************************************************************/ 00166 void GCTAOnOffObservations::clear(void) 00167 { 00168 // Free members 00169 free_members(); 00170 00171 // Initialise members 00172 init_members(); 00173 00174 // Return 00175 return; 00176 } 00177 00178 00179 /***********************************************************************//** 00180 * @brief Clone observations 00181 * 00182 * @return Pointer to deep copy of observation container. 00183 ***************************************************************************/ 00184 GCTAOnOffObservations* GCTAOnOffObservations::clone(void) const 00185 { 00186 // Clone observations 00187 return new GCTAOnOffObservations(*this); 00188 } 00189 00190 00191 /***********************************************************************//** 00192 * @brief Return pointer to observation 00193 * 00194 * @param[in] index Observation index [0,...,size()-1]. 00195 * @return Observation. 00196 * 00197 * @exception GException::out_of_range 00198 * Operation index is out of range. 00199 * 00200 * Returns a pointer to the observation with specified @p index. 00201 ***************************************************************************/ 00202 GCTAOnOffObservation* GCTAOnOffObservations::at(const int& index) 00203 { 00204 // Raise exception if index is out of range 00205 if (index < 0 || index >= size()) { 00206 throw GException::out_of_range(G_AT, index, 0, size()-1); 00207 } 00208 00209 // Return pointer 00210 return m_obs[index]; 00211 } 00212 00213 00214 /***********************************************************************//** 00215 * @brief Return pointer to observation (const version) 00216 * 00217 * @param[in] index Observation index [0,...,size()-1]. 00218 * 00219 * @exception GException::out_of_range 00220 * Operation index is out of range. 00221 * 00222 * Returns a const pointer to the observation with specified @p index. 00223 ***************************************************************************/ 00224 const GCTAOnOffObservation* GCTAOnOffObservations::at(const int& index) const 00225 { 00226 // Raise exception if index is out of range 00227 if (index < 0 || index >= size()) { 00228 throw GException::out_of_range(G_AT, index, 0, size()-1); 00229 } 00230 00231 // Return pointer 00232 return m_obs[index]; 00233 } 00234 00235 00236 /***********************************************************************//** 00237 * @brief Set observation in container 00238 * 00239 * @param[in] index Observation index [0,...,size()-1]. 00240 * @param[in] obs Observation. 00241 * @return Pointer to deep copy of observation. 00242 * 00243 * @exception GException::out_of_range 00244 * Observation index is out of range. 00245 * @exception GException::invalid_value 00246 * Observation with same instrument and identifier already 00247 * exists in container. 00248 * 00249 * Set a deep copy and observation @p obs at the specified @p index in the 00250 * container. 00251 ***************************************************************************/ 00252 GCTAOnOffObservation* GCTAOnOffObservations::set(const int& index, const GCTAOnOffObservation& obs) 00253 { 00254 // Compile option: raise exception if index is out of range 00255 #if defined(G_RANGE_CHECK) 00256 if (index < 0 || index >= size()) { 00257 throw GException::out_of_range(G_SET, index, 0, size()-1); 00258 } 00259 #endif 00260 00261 // Raise an exception if an observation with specified instrument and 00262 // identifier already exists 00263 int inx = get_index(obs.instrument(), obs.id()); 00264 if (inx != -1 && inx != index) { 00265 std::string msg = 00266 "Attempt to set \""+obs.instrument()+"\" observation with" 00267 " identifier \""+obs.id()+"\" in observation container at" 00268 " index "+gammalib::str(index)+", but an observation with the" 00269 " same attributes exists already at index "+gammalib::str(inx)+ 00270 " in the container.\n" 00271 "Every observation for a given instrument in the observation" 00272 " container needs a unique identifier."; 00273 throw GException::invalid_value(G_SET, msg); 00274 } 00275 00276 // Delete existing observation 00277 if (m_obs[index] != NULL) delete m_obs[index]; 00278 00279 // Store pointer to a deep copy of the observation 00280 m_obs[index] = obs.clone(); 00281 00282 // Return pointer 00283 return m_obs[index]; 00284 } 00285 00286 00287 /***********************************************************************//** 00288 * @brief Append observation to container 00289 * 00290 * @param[in] obs Observation. 00291 * @return Pointer to deep copy of observation. 00292 * 00293 * @exception GException::invalid_value 00294 * Observation with same instrument and identifier already 00295 * exists in container. 00296 * 00297 * Appends a deep copy of an observation to the container. 00298 ***************************************************************************/ 00299 GCTAOnOffObservation* GCTAOnOffObservations::append(const GCTAOnOffObservation& obs) 00300 { 00301 // Raise an exception if an observation with specified instrument and 00302 // identifier already exists 00303 int inx = get_index(obs.instrument(), obs.id()); 00304 if (inx != -1) { 00305 std::string msg = 00306 "Attempt to append \""+obs.instrument()+"\" observation with" 00307 " identifier \""+obs.id()+"\" to observation container, but an" 00308 " observation with the same attributes exists already at" 00309 " index "+gammalib::str(inx)+" in the container.\n" 00310 "Every observation for a given instrument in the observation" 00311 " container needs a unique identifier."; 00312 throw GException::invalid_value(G_APPEND, msg); 00313 } 00314 00315 // Clone observation 00316 GCTAOnOffObservation* ptr = obs.clone(); 00317 00318 // Append to list 00319 m_obs.push_back(ptr); 00320 00321 // Return pointer 00322 return ptr; 00323 } 00324 00325 00326 /***********************************************************************//** 00327 * @brief Insert observation into container 00328 * 00329 * @param[in] index Observation index [0,...,size()-1]. 00330 * @param[in] obs Observation. 00331 * @return Pointer to deep copy of observation. 00332 * 00333 * @exception GException::out_of_range 00334 * Observation index is out of range. 00335 * @exception GException::invalid_value 00336 * Observation with same instrument and identifier already 00337 * exists in container. 00338 * 00339 * Inserts a deep copy of an observation into the container before the 00340 * observation with the specified @p index. 00341 ***************************************************************************/ 00342 GCTAOnOffObservation* GCTAOnOffObservations::insert(const int& index, const GCTAOnOffObservation& obs) 00343 { 00344 // Compile option: raise exception if index is out of range 00345 #if defined(G_RANGE_CHECK) 00346 if (is_empty()) { 00347 if (index > 0) { 00348 throw GException::out_of_range(G_INSERT, index, 0, size()-1); 00349 } 00350 } 00351 else { 00352 if (index < 0 || index >= size()) { 00353 throw GException::out_of_range(G_INSERT, index, 0, size()-1); 00354 } 00355 } 00356 #endif 00357 00358 // Raise an exception if an observation with specified instrument and 00359 // identifier already exists 00360 int inx = get_index(obs.instrument(), obs.id()); 00361 if (inx != -1 && inx != index) { 00362 std::string msg = 00363 "Attempt to insert \""+obs.instrument()+"\" observation with" 00364 " identifier \""+obs.id()+"\" in observation container before" 00365 " index "+gammalib::str(index)+", but an observation with the" 00366 " same attributes exists already at index "+gammalib::str(inx)+ 00367 " in the container.\n" 00368 "Every observation for a given instrument in the observation" 00369 " container needs a unique identifier."; 00370 throw GException::invalid_value(G_INSERT, msg); 00371 } 00372 00373 // Clone observation 00374 GCTAOnOffObservation* ptr = obs.clone(); 00375 00376 // Clone observation and insert into list 00377 m_obs.insert(m_obs.begin()+index, ptr); 00378 00379 // Return pointer 00380 return ptr; 00381 } 00382 00383 00384 /***********************************************************************//** 00385 * @brief Remove observation from container 00386 * 00387 * @param[in] index Observation index [0,...,size()-1]. 00388 * 00389 * @exception GException::out_of_range 00390 * Observation index is out of range. 00391 * 00392 * Removes observation of specified @p index from the container. 00393 ***************************************************************************/ 00394 void GCTAOnOffObservations::remove(const int& index) 00395 { 00396 // Compile option: If index is outside boundary then raise exception 00397 #if defined(G_RANGE_CHECK) 00398 if (index < 0 || index >= size()) { 00399 throw GException::out_of_range(G_REMOVE, index, 0, size()-1); 00400 } 00401 #endif 00402 00403 // Erase observation component from container 00404 m_obs.erase(m_obs.begin() + index); 00405 00406 // Return 00407 return; 00408 } 00409 00410 00411 /***********************************************************************//** 00412 * @brief Append observations from observation container 00413 * 00414 * @param[in] obs Observations. 00415 * 00416 * @exception GException::invalid_value 00417 * Observation with same instrument and identifier already 00418 * exists in container. 00419 * 00420 * Appends deep copies of observations to the container. 00421 ***************************************************************************/ 00422 void GCTAOnOffObservations::extend(const GCTAOnOffObservations& obs) 00423 { 00424 // Do nothing if observation container is empty 00425 if (!obs.is_empty()) { 00426 00427 // Get size. Note that we extract the size first to avoid an 00428 // endless loop that arises when a container is appended to 00429 // itself. 00430 int num = obs.size(); 00431 00432 // Reserve enough space 00433 reserve(size() + num); 00434 00435 // Loop over all observations, clone them and append them to the 00436 // list 00437 for (int i = 0; i < num; ++i) { 00438 00439 // Raise an exception if an observation with specified 00440 // instrument and identifier already exists 00441 int inx = get_index(obs[i]->instrument(), obs[i]->id()); 00442 if (inx != -1) { 00443 std::string msg = 00444 "Attempt to append \""+obs[i]->instrument()+"\"" 00445 " observation with identifier \""+obs[i]->id()+"\"" 00446 " to observation container, but an observation with the" 00447 " same attributes exists already at index "+ 00448 gammalib::str(inx)+" in the container.\n" 00449 "Every observation for a given instrument in the" 00450 " observation container needs a unique identifier."; 00451 throw GException::invalid_value(G_EXTEND, msg); 00452 } 00453 00454 // Append observation to container 00455 m_obs.push_back(obs[i]->clone()); 00456 } 00457 00458 } // endif: observation container was not empty 00459 00460 // Return 00461 return; 00462 } 00463 00464 00465 /***********************************************************************//** 00466 * @brief Signals if observation exists 00467 * 00468 * @param[in] instrument Instrument. 00469 * @param[in] id Observation identifier. 00470 * @return True if observation with specified @p instrument and identifier 00471 * @p id exists. 00472 * 00473 * Searches all observations for a match with the specified @p instrument 00474 * and @p identifier. If the specified attributes have been found, true is 00475 * returned. 00476 ***************************************************************************/ 00477 bool GCTAOnOffObservations::contains(const std::string& instrument, 00478 const std::string& id) const 00479 { 00480 // Get observation index 00481 int index = get_index(instrument, id); 00482 00483 // Return 00484 return (index != -1); 00485 } 00486 00487 00488 /***********************************************************************//** 00489 * @brief Load observations from XML file 00490 * 00491 * @param[in] filename XML filename. 00492 * 00493 * Loads observation from a XML file into the container. Please refer to the 00494 * read() method for more information about the structure of the XML file. 00495 ***************************************************************************/ 00496 void GCTAOnOffObservations::load(const GFilename& filename) 00497 { 00498 // Clear any existing observations 00499 clear(); 00500 00501 // Load XML document 00502 GXml xml(filename.url()); 00503 00504 // Read observations from XML document 00505 read(xml); 00506 00507 // Return 00508 return; 00509 } 00510 00511 00512 /***********************************************************************//** 00513 * @brief Save observations into XML file 00514 * 00515 * @param[in] filename XML filename. 00516 * 00517 * Saves observations into a XML file. Please refer to the read() method for 00518 * more information about the structure of the XML file. 00519 ***************************************************************************/ 00520 void GCTAOnOffObservations::save(const GFilename& filename) const 00521 { 00522 // Declare empty XML document 00523 GXml xml; 00524 00525 // Write observations into XML file 00526 write(xml); 00527 00528 // Save XML document 00529 xml.save(filename); 00530 00531 // Return 00532 return; 00533 } 00534 00535 00536 /***********************************************************************//** 00537 * @brief Read observations from XML document 00538 * 00539 * @param[in] xml XML document. 00540 * 00541 * @exception GException::invalid_instrument 00542 * Invalid instrument encountered in XML file. 00543 * 00544 * Reads observations from the first observation list that is found in the 00545 * XML document. The decoding of the instrument specific observation 00546 * definition is done within the observation's GCTAOnOffObservation::read() method. 00547 * The following file structure is expected: 00548 * 00549 * <observation_list title="observation library"> 00550 * <observation name="..." id="..." instrument="..."> 00551 * ... 00552 * </observation> 00553 * <observation name="..." id="..." instrument="..."> 00554 * ... 00555 * </observation> 00556 * ... 00557 * </observation_list> 00558 * 00559 * The @p name and @p id attributes allow for a unique identification of an 00560 * observation within the observation container. The @p instrument 00561 * attributes specifies the instrument to which the observation applies. 00562 * At the moment there is only CTA but more instruments may be implemented 00563 * later and require the need for a registry (see GObservations.cpp). 00564 * 00565 * The structure within the @p observation tag is defined by the instrument 00566 * specific GCTAOnOffObservation class. 00567 * 00568 ***************************************************************************/ 00569 void GCTAOnOffObservations::read(const GXml& xml) 00570 { 00571 // Get pointer on observation library 00572 const GXmlElement* lib = xml.element("observation_list", 0); 00573 00574 // Loop over all observations 00575 int n = lib->elements("observation"); 00576 for (int i = 0; i < n; ++i) { 00577 00578 // Get pointer on observation 00579 const GXmlElement* obs = lib->element("observation", i); 00580 00581 // Get attributes 00582 std::string name = obs->attribute("name"); 00583 std::string id = obs->attribute("id"); 00584 //std::string instrument = obs->attribute("instrument"); 00585 00586 // Allocate observation 00587 // (only CTA at the moment, implement registry if more) 00588 GCTAOnOffObservation* ptr = new GCTAOnOffObservation; 00589 00590 // If observation is valid then read its definition from XML file 00591 if (ptr != NULL) { 00592 00593 // Read definition 00594 ptr->read(*obs); 00595 00596 // Set attributes 00597 ptr->name(name); 00598 ptr->id(id); 00599 00600 } // endif: observation was valid 00601 00602 // ... otherwise throw an exception 00603 else { 00604 std::string msg = "Problem allocating GCTAOnOffObservation object."; 00605 throw GException::invalid_instrument(G_READ, msg); 00606 } 00607 00608 // Append observation to container 00609 append(*ptr); 00610 00611 // Free observation (the append method made a deep copy) 00612 delete ptr; 00613 00614 } // endfor: looped over all observations 00615 00616 // Return 00617 return; 00618 } 00619 00620 00621 /***********************************************************************//** 00622 * @brief Write observations into XML document 00623 * 00624 * @param[in] xml XML document. 00625 * 00626 * Write observations into the first observation library that is found in the 00627 * XML document. In case that no observation library exists, one is added to 00628 * the document. Please refer to the read() method for more information 00629 * about the structure of the XML document. 00630 ***************************************************************************/ 00631 void GCTAOnOffObservations::write(GXml& xml) const 00632 { 00633 // If there is no observation library then append one 00634 if (xml.elements("observation_list") == 0) { 00635 xml.append(GXmlElement("observation_list title=\"observation list\"")); 00636 } 00637 00638 // Get pointer on observation library 00639 GXmlElement* lib = xml.element("observation_list", 0); 00640 00641 // Write all observations into library 00642 for (int i = 0; i < size(); ++i) { 00643 00644 // Initialise pointer on observation 00645 GXmlElement* obs = NULL; 00646 00647 // Search corresponding observation 00648 int n = xml.elements("observation"); 00649 for (int k = 0; k < n; ++k) { 00650 GXmlElement* element = xml.element("observation", k); 00651 if (element->attribute("name") == m_obs[i]->name() && 00652 element->attribute("id") == m_obs[i]->id() && 00653 element->attribute("instrument") == m_obs[i]->instrument()) { 00654 obs = element; 00655 break; 00656 } 00657 } 00658 00659 // If no observation with corresponding name, ID and instrument was 00660 // found then append one now 00661 if (obs == NULL) { 00662 obs = lib->append("observation"); 00663 obs->attribute("name", m_obs[i]->name()); 00664 obs->attribute("id", m_obs[i]->id()); 00665 obs->attribute("instrument", m_obs[i]->instrument()); 00666 } 00667 00668 // Write now observation 00669 m_obs[i]->write(*obs); 00670 00671 } // endfor: looped over all observaitons 00672 00673 // Return 00674 return; 00675 } 00676 00677 00678 /***********************************************************************//** 00679 * @brief Load models from XML file 00680 * 00681 * @param[in] filename XML filename. 00682 * 00683 * Loads the models from a XML file. Please refer to the GModels::read() 00684 * method for more information about the expected structure of the XML 00685 * file. 00686 ***************************************************************************/ 00687 void GCTAOnOffObservations::models(const GFilename& filename) 00688 { 00689 // Load models 00690 m_models.load(filename); 00691 00692 // Return 00693 return; 00694 } 00695 00696 00697 /***********************************************************************//** 00698 * @brief Print observation list information 00699 * 00700 * @param[in] chatter Chattiness (defaults to NORMAL). 00701 * @return String containing observation list information 00702 ***************************************************************************/ 00703 std::string GCTAOnOffObservations::print(const GChatter& chatter) const 00704 { 00705 // Initialise result string 00706 std::string result; 00707 00708 // Continue only if chatter is not silent 00709 if (chatter != SILENT) { 00710 00711 // Append header 00712 result.append("=== GCTAOnOffObservations ==="); 00713 00714 // Append information 00715 result.append("\n"+gammalib::parformat("Number of observations")); 00716 result.append(gammalib::str(size())); 00717 00718 // NORMAL: Append observations 00719 if (chatter >= NORMAL) { 00720 for (int i = 0; i < size(); ++i) { 00721 result.append("\n"); 00722 result.append((*this)[i]->print()); 00723 } 00724 } // endif: chatter was normal 00725 00726 // EXPLICIT: Append models 00727 if (chatter >= EXPLICIT) { 00728 result.append("\n"+m_models.print()); 00729 } // endif: chatter was explicit 00730 00731 } // endif: chatter was not silent 00732 00733 // Return result 00734 return result; 00735 } 00736 00737 00738 /*========================================================================== 00739 = = 00740 = Private methods = 00741 = = 00742 ==========================================================================*/ 00743 00744 /***********************************************************************//** 00745 * @brief Initialise class members 00746 ***************************************************************************/ 00747 void GCTAOnOffObservations::init_members(void) 00748 { 00749 // Initialise members 00750 m_obs.clear(); 00751 m_models.clear(); 00752 00753 // Return 00754 return; 00755 } 00756 00757 00758 /***********************************************************************//** 00759 * @brief Copy class members 00760 * 00761 * @param[in] obs Observation container. 00762 * 00763 * Copies all class members. Deep copies are created for the observations, 00764 * which is what is needed to have a real physical copy of the members. 00765 ***************************************************************************/ 00766 void GCTAOnOffObservations::copy_members(const GCTAOnOffObservations& obs) 00767 { 00768 // Copy attributes 00769 m_models = obs.m_models; 00770 00771 // Copy observations 00772 m_obs.clear(); 00773 for (int i = 0; i < obs.m_obs.size(); ++i) { 00774 m_obs.push_back((obs.m_obs[i]->clone())); 00775 } 00776 00777 // Return 00778 return; 00779 } 00780 00781 00782 /***********************************************************************//** 00783 * @brief Delete class members 00784 * 00785 * Deallocates all observations. Since container classes that hold pointers 00786 * need to handle the proper deallocation of memory, we loop here over all 00787 * pointers and make sure that we deallocate all observations in the 00788 * container. 00789 ***************************************************************************/ 00790 void GCTAOnOffObservations::free_members(void) 00791 { 00792 // Free observations 00793 for (int i = 0; i < m_obs.size(); ++i) { 00794 delete m_obs[i]; 00795 m_obs[i] = NULL; 00796 } 00797 00798 // Return 00799 return; 00800 } 00801 00802 00803 /***********************************************************************//** 00804 * @brief Return observation index by instrument and identifier 00805 * 00806 * @param[in] instrument Instrument. 00807 * @param[in] id Observation identifier. 00808 * @return Observation index (-1 of instrument and observation identifier 00809 * has not been found) 00810 * 00811 * Returns observation index based on the specified @p instrument and 00812 * observation identifier @p id. If no observation with the specified 00813 * attributes has been found, the method returns -1. 00814 ***************************************************************************/ 00815 int GCTAOnOffObservations::get_index(const std::string& instrument, 00816 const std::string& id) const 00817 { 00818 // Initialise index 00819 int index = -1; 00820 00821 // Search observation with specified instrument and id 00822 for (int i = 0; i < size(); ++i) { 00823 if ((m_obs[i]->instrument() == instrument) && 00824 (m_obs[i]->id() == id)) { 00825 index = i; 00826 break; 00827 } 00828 } 00829 00830 // Return index 00831 return index; 00832 }