00001 /*************************************************************************** 00002 * GModels.cpp - Model container class * 00003 * ----------------------------------------------------------------------- * 00004 * copyright (C) 2009-2016 by Juergen Knoedlseder * 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 GModels.cpp 00023 * @brief Model container class implementation 00024 * @author Juergen Knoedlseder 00025 */ 00026 00027 /* __ Includes ___________________________________________________________ */ 00028 #ifdef HAVE_CONFIG_H 00029 #include <config.h> 00030 #endif 00031 #include "GTools.hpp" 00032 #include "GException.hpp" 00033 #include "GFilename.hpp" 00034 #include "GModels.hpp" 00035 #include "GModel.hpp" 00036 #include "GModelRegistry.hpp" 00037 #include "GObservation.hpp" 00038 #include "GXml.hpp" 00039 #include "GXmlElement.hpp" 00040 00041 /* __ Method name definitions ____________________________________________ */ 00042 #define G_ACCESS "GModels::operator[](std::string&)" 00043 #define G_AT "GModels::at(int&)" 00044 #define G_SET1 "GModels::set(int&, GModel&)" 00045 #define G_SET2 "GModels::set(std::string&, GModel&)" 00046 #define G_APPEND "GModels::append(GModel&)" 00047 #define G_INSERT1 "GModels::insert(int&, GModel&)" 00048 #define G_INSERT2 "GModels::insert(std::string&, GModel&)" 00049 #define G_REMOVE1 "GModels::remove(int&)" 00050 #define G_REMOVE2 "GModels::remove(std::string&)" 00051 #define G_EXTEND "GModels::extend(GModels&)" 00052 #define G_READ "GModels::read(GXml&)" 00053 00054 /* __ Macros _____________________________________________________________ */ 00055 00056 /* __ Coding definitions _________________________________________________ */ 00057 00058 /* __ Debug definitions __________________________________________________ */ 00059 00060 00061 /*========================================================================== 00062 = = 00063 = Constructors/destructors = 00064 = = 00065 ==========================================================================*/ 00066 00067 /***********************************************************************//** 00068 * @brief Void constructor 00069 ***************************************************************************/ 00070 GModels::GModels(void) 00071 { 00072 // Initialise members 00073 init_members(); 00074 00075 // Return 00076 return; 00077 } 00078 00079 00080 /***********************************************************************//** 00081 * @brief Copy constructor 00082 * 00083 * @param[in] models Model container. 00084 ***************************************************************************/ 00085 GModels::GModels(const GModels& models) 00086 { 00087 // Initialise members 00088 init_members(); 00089 00090 // Copy members 00091 copy_members(models); 00092 00093 // Return 00094 return; 00095 } 00096 00097 00098 /***********************************************************************//** 00099 * @brief Load constructor 00100 * 00101 * @param[in] filename XML filename. 00102 * 00103 * Constructs model container from an XML file. See the read() method for 00104 * more information about the expected structure of the XML file. 00105 ***************************************************************************/ 00106 GModels::GModels(const GFilename& filename) 00107 { 00108 // Initialise members 00109 init_members(); 00110 00111 // Load XML file 00112 load(filename); 00113 00114 // Return 00115 return; 00116 } 00117 00118 00119 /***********************************************************************//** 00120 * @brief Destructor 00121 ***************************************************************************/ 00122 GModels::~GModels(void) 00123 { 00124 // Free members 00125 free_members(); 00126 00127 // Return 00128 return; 00129 } 00130 00131 00132 /*========================================================================== 00133 = = 00134 = Operators = 00135 = = 00136 ==========================================================================*/ 00137 00138 /***********************************************************************//** 00139 * @brief Assignment operator 00140 * 00141 * @param[in] models Model container. 00142 * @return Model container. 00143 ***************************************************************************/ 00144 GModels& GModels::operator=(const GModels& models) 00145 { 00146 // Execute only if object is not identical 00147 if (this != &models) { 00148 00149 // Free members 00150 free_members(); 00151 00152 // Initialise members 00153 init_members(); 00154 00155 // Copy members 00156 copy_members(models); 00157 00158 } // endif: object was not identical 00159 00160 // Return 00161 return *this; 00162 } 00163 00164 00165 /***********************************************************************//** 00166 * @brief Return pointer to model 00167 * 00168 * @param[in] name Model name. 00169 * 00170 * @exception GException::model_not_found 00171 * Model with specified name not found in container. 00172 * 00173 * Returns a pointer to the model with the specified @p name. 00174 ***************************************************************************/ 00175 GModel* GModels::operator[](const std::string& name) 00176 { 00177 // Get model index 00178 int index = get_index(name); 00179 00180 // Throw exception if model name was not found 00181 if (index == -1) { 00182 throw GException::model_not_found(G_ACCESS, name); 00183 } 00184 00185 // Return pointer 00186 return m_models[index]; 00187 } 00188 00189 00190 /***********************************************************************//** 00191 * @brief Return pointer to model (const version) 00192 * 00193 * @param[in] name Model name. 00194 * 00195 * @exception GException::model_not_found 00196 * Model with specified name not found in container. 00197 * 00198 * Returns a const pointer to the model with the specified @p name. 00199 ***************************************************************************/ 00200 const GModel* GModels::operator[](const std::string& name) const 00201 { 00202 // Get model index 00203 int index = get_index(name); 00204 00205 // Throw exception if model name was not found 00206 if (index == -1) { 00207 throw GException::model_not_found(G_ACCESS, name); 00208 } 00209 00210 // Return pointer 00211 return m_models[index]; 00212 } 00213 00214 00215 /*========================================================================== 00216 = = 00217 = Public methods = 00218 = = 00219 ==========================================================================*/ 00220 00221 /***********************************************************************//** 00222 * @brief Clear object 00223 * 00224 * Removes all models from the container. 00225 ***************************************************************************/ 00226 void GModels::clear(void) 00227 { 00228 // Free class members (base and derived classes, derived class first) 00229 free_members(); 00230 00231 // Initialise members 00232 init_members(); 00233 00234 // Return 00235 return; 00236 } 00237 00238 00239 /***********************************************************************//** 00240 * @brief Clone instance 00241 * 00242 * @return Pointer to deep copy of model container 00243 * 00244 * Makes a deep copy of the model container instance. 00245 ***************************************************************************/ 00246 GModels* GModels::clone(void) const 00247 { 00248 return new GModels(*this); 00249 } 00250 00251 00252 /***********************************************************************//** 00253 * @brief Return pointer to model 00254 * 00255 * @param[in] index Model index [0,...,size()-1]. 00256 * 00257 * @exception GException::out_of_range 00258 * Model index is out of range. 00259 * 00260 * Returns a pointer to the model with the specified @p index. 00261 ***************************************************************************/ 00262 GModel* GModels::at(const int& index) 00263 { 00264 // Compile option: raise an exception if index is out of range 00265 #if defined(G_RANGE_CHECK) 00266 if (index < 0 || index >= size()) { 00267 throw GException::out_of_range(G_AT, "Model index", index, size()); 00268 } 00269 #endif 00270 00271 // Return pointer 00272 return m_models[index]; 00273 } 00274 00275 00276 /***********************************************************************//** 00277 * @brief Return pointer to model (const version) 00278 * 00279 * @param[in] index Model index [0,...,size()-1]. 00280 * 00281 * @exception GException::out_of_range 00282 * Model index is out of range. 00283 * 00284 * Returns a const pointer to the model with the specified @p index. 00285 ***************************************************************************/ 00286 const GModel* GModels::at(const int& index) const 00287 { 00288 // Compile option: raise an exception if index is out of range 00289 #if defined(G_RANGE_CHECK) 00290 if (index < 0 || index >= size()) { 00291 throw GException::out_of_range(G_AT, "Model index", index, size()); 00292 } 00293 #endif 00294 00295 // Return pointer 00296 return m_models[index]; 00297 } 00298 00299 00300 /***********************************************************************//** 00301 * @brief Set model in container 00302 * 00303 * @param[in] index Model index [0,...,size()-1]. 00304 * @param[in] model Model. 00305 * @return Pointer to deep copy of model. 00306 * 00307 * @exception GException::out_of_range 00308 * Model index is out of range. 00309 * @exception GException::invalid_value 00310 * Name of model exists already in container. 00311 * 00312 * Set model in the container. A deep copy of the model will be made. 00313 ***************************************************************************/ 00314 GModel* GModels::set(const int& index, const GModel& model) 00315 { 00316 // Compile option: raise exception if index is out of range 00317 #if defined(G_RANGE_CHECK) 00318 if (index < 0 || index >= size()) { 00319 throw GException::out_of_range(G_SET1, index, 0, size()-1); 00320 } 00321 #endif 00322 00323 // Check if a model with specified name does not yet exist 00324 int inx = get_index(model.name()); 00325 if (inx != -1 && inx != index) { 00326 std::string msg = 00327 "Attempt to set model with name \""+model.name()+"\" in model" 00328 " container at index "+gammalib::str(index)+", but a model with" 00329 " the same name exists already at index "+gammalib::str(inx)+ 00330 " in the container.\n" 00331 "Every model in the model container needs a unique name."; 00332 throw GException::invalid_value(G_SET1, msg); 00333 } 00334 00335 // Delete any existing model 00336 if (m_models[index] != NULL) delete m_models[index]; 00337 00338 // Assign new model by cloning 00339 m_models[index] = model.clone(); 00340 00341 // Return pointer to model 00342 return m_models[index]; 00343 } 00344 00345 00346 /***********************************************************************//** 00347 * @brief Set model in container 00348 * 00349 * @param[in] name Model name. 00350 * @param[in] model Model pointer. 00351 * @return Pointer to deep copy of model. 00352 * 00353 * @exception GException::model_not_found 00354 * Model with specified name not found in container. 00355 * @exception GException::invalid_value 00356 * Name of model exists already in container. 00357 * 00358 * Set model in the container. A deep copy of the model will be made. 00359 ***************************************************************************/ 00360 GModel* GModels::set(const std::string& name, const GModel& model) 00361 { 00362 // Get parameter index 00363 int index = get_index(name); 00364 00365 // Throw exception if parameter name was not found 00366 if (index == -1) { 00367 throw GException::model_not_found(G_SET2, name); 00368 } 00369 00370 // Check if a model with specified name does not yet exist 00371 int inx = get_index(model.name()); 00372 if (inx != -1 && inx != index) { 00373 std::string msg = 00374 "Attempt to set model with name \""+model.name()+"\" in model" 00375 " container at index "+gammalib::str(index)+", but a model with" 00376 " the same name exists already at index "+gammalib::str(inx)+ 00377 " in the container.\n" 00378 "Every model in the model container needs a unique name."; 00379 throw GException::invalid_value(G_SET2, msg); 00380 } 00381 00382 // Delete any existing model 00383 if (m_models[index] != NULL) delete m_models[index]; 00384 00385 // Assign new model by cloning 00386 m_models[index] = model.clone(); 00387 00388 // Return pointer to model 00389 return m_models[index]; 00390 } 00391 00392 00393 /***********************************************************************//** 00394 * @brief Append model to container 00395 * 00396 * @param[in] model Model. 00397 * @return Pointer to deep copy of model. 00398 * 00399 * @exception GException::invalid_value 00400 * Name of model exists already in container. 00401 * 00402 * Appends model to the container by making a deep copy of the model and 00403 * storing its pointer. 00404 ***************************************************************************/ 00405 GModel* GModels::append(const GModel& model) 00406 { 00407 // Check if a model with specified name does not yet exist 00408 int inx = get_index(model.name()); 00409 if (inx != -1) { 00410 std::string msg = 00411 "Attempt to append model with name \""+model.name()+"\" to model" 00412 " container, but a model with the same name exists already at" 00413 " index "+gammalib::str(inx)+" in the container.\n" 00414 "Every model in the model container needs a unique name."; 00415 throw GException::invalid_value(G_APPEND, msg); 00416 } 00417 00418 // Create deep copy of model 00419 GModel* ptr = model.clone(); 00420 00421 // Append deep copy of model 00422 m_models.push_back(ptr); 00423 00424 // Return pointer to model 00425 return ptr; 00426 } 00427 00428 00429 /***********************************************************************//** 00430 * @brief Insert model into container 00431 * 00432 * @param[in] index Model index [0,...,size()-1]. 00433 * @param[in] model Model. 00434 * @return Pointer to deep copy of model. 00435 * 00436 * @exception GException::out_of_range 00437 * Model index is out of range. 00438 * @exception GException::invalid_value 00439 * Name of model exists already in container. 00440 * 00441 * Inserts a @p model into the container before the model with the specified 00442 * @p index. 00443 ***************************************************************************/ 00444 GModel* GModels::insert(const int& index, const GModel& model) 00445 { 00446 // Compile option: raise exception if index is out of range 00447 #if defined(G_RANGE_CHECK) 00448 if (is_empty()) { 00449 if (index > 0) { 00450 throw GException::out_of_range(G_INSERT1, index, 0, size()-1); 00451 } 00452 } 00453 else { 00454 if (index < 0 || index >= size()) { 00455 throw GException::out_of_range(G_INSERT1, index, 0, size()-1); 00456 } 00457 } 00458 #endif 00459 00460 // Check if a model with specified name does not yet exist 00461 int inx = get_index(model.name()); 00462 if (inx != -1) { 00463 std::string msg = 00464 "Attempt to insert model with name \""+model.name()+"\" in model" 00465 " container before index "+gammalib::str(index)+", but a model" 00466 " with the same name exists already at index "+gammalib::str(inx)+ 00467 " in the container.\n" 00468 "Every model in the model container needs a unique name."; 00469 throw GException::invalid_value(G_INSERT1, msg); 00470 } 00471 00472 // Create deep copy of model 00473 GModel* ptr = model.clone(); 00474 00475 // Inserts deep copy of model 00476 m_models.insert(m_models.begin()+index, ptr); 00477 00478 // Return pointer to model 00479 return ptr; 00480 } 00481 00482 00483 /***********************************************************************//** 00484 * @brief Insert model into container 00485 * 00486 * @param[in] name Model name. 00487 * @param[in] model Model. 00488 * @return Pointer to deep copy of model. 00489 * 00490 * @exception GException::model_not_found 00491 * Model with specified name not found in container. 00492 * @exception GException::invalid_value 00493 * Name of model exists already in container. 00494 * 00495 * Inserts a @p model into the container before the model with the specified 00496 * @p name. 00497 ***************************************************************************/ 00498 GModel* GModels::insert(const std::string& name, const GModel& model) 00499 { 00500 // Get parameter index 00501 int index = get_index(name); 00502 00503 // Throw exception if parameter name was not found 00504 if (index == -1) { 00505 throw GException::model_not_found(G_INSERT2, name); 00506 } 00507 00508 // Check if a model with specified name does not yet exist 00509 int inx = get_index(model.name()); 00510 if (inx != -1) { 00511 std::string msg = 00512 "Attempt to insert model with name \""+model.name()+"\" in model" 00513 " container before index "+gammalib::str(index)+", but a model" 00514 " with the same name exists already at index "+gammalib::str(inx)+ 00515 " in the container.\n" 00516 "Every model in the model container needs a unique name."; 00517 throw GException::invalid_value(G_INSERT2, msg); 00518 } 00519 00520 // Create deep copy of model 00521 GModel* ptr = model.clone(); 00522 00523 // Inserts deep copy of model 00524 m_models.insert(m_models.begin()+index, ptr); 00525 00526 // Return pointer to model 00527 return ptr; 00528 } 00529 00530 00531 /***********************************************************************//** 00532 * @brief Remove model from container 00533 * 00534 * @param[in] index Model index [0,...,size()-1]. 00535 * 00536 * @exception GException::out_of_range 00537 * Model index is out of range. 00538 * 00539 * Remove model of specified @p index from container. 00540 ***************************************************************************/ 00541 void GModels::remove(const int& index) 00542 { 00543 // Compile option: raise exception if index is out of range 00544 #if defined(G_RANGE_CHECK) 00545 if (index < 0 || index >= size()) { 00546 throw GException::out_of_range(G_REMOVE1, index, 0, size()-1); 00547 } 00548 #endif 00549 00550 // Delete model 00551 delete m_models[index]; 00552 00553 // Erase model component from container 00554 m_models.erase(m_models.begin() + index); 00555 00556 // Return 00557 return; 00558 } 00559 00560 00561 /***********************************************************************//** 00562 * @brief Remove model from container 00563 * 00564 * @param[in] name Model name. 00565 * 00566 * @exception GException::model_not_found 00567 * Model with specified name not found in container. 00568 * 00569 * Remove model of specified @p name from container. 00570 ***************************************************************************/ 00571 void GModels::remove(const std::string& name) 00572 { 00573 // Get parameter index 00574 int index = get_index(name); 00575 00576 // Throw exception if parameter name was not found 00577 if (index == -1) { 00578 throw GException::model_not_found(G_REMOVE2, name); 00579 } 00580 00581 // Delete model 00582 delete m_models[index]; 00583 00584 // Erase model component from container 00585 m_models.erase(m_models.begin() + index); 00586 00587 // Return 00588 return; 00589 } 00590 00591 00592 /***********************************************************************//** 00593 * @brief Append model container 00594 * 00595 * @param[in] models Model container. 00596 * 00597 * Append model container to the container. 00598 ***************************************************************************/ 00599 void GModels::extend(const GModels& models) 00600 { 00601 // Do nothing if model container is empty 00602 if (!models.is_empty()) { 00603 00604 // Get size. Note that we extract the size first to avoid an 00605 // endless loop that arises when a container is appended to 00606 // itself. 00607 int num = models.size(); 00608 00609 // Reserve enough space 00610 reserve(size() + num); 00611 00612 // Loop over all model components and append pointers to deep copies 00613 for (int i = 0; i < num; ++i) { 00614 00615 // Check if model name does not yet exist 00616 int inx = get_index(models[i]->name()); 00617 if (inx != -1) { 00618 std::string msg = 00619 "Attempt to append model with name \""+models[i]->name()+ 00620 "\" to model container, but a model with the same name" 00621 " exists already at index "+gammalib::str(inx)+" in the" 00622 " container.\n" 00623 "Every model in the model container needs a unique name."; 00624 throw GException::invalid_value(G_EXTEND, msg); 00625 } 00626 00627 // Append model to container 00628 m_models.push_back(models[i]->clone()); 00629 00630 } // endfor: looped over all models 00631 00632 } // endif: model container was not empty 00633 00634 // Return 00635 return; 00636 } 00637 00638 00639 /***********************************************************************//** 00640 * @brief Signals if model name exists 00641 * 00642 * @param[in] name Model name. 00643 * @return True if model with specified @p name exists. 00644 * 00645 * Searches all model names for a match with the specified @p name. If the 00646 * specified name has been found, true is returned. 00647 ***************************************************************************/ 00648 bool GModels::contains(const std::string& name) const 00649 { 00650 // Get model index 00651 int index = get_index(name); 00652 00653 // Return 00654 return (index != -1); 00655 } 00656 00657 00658 /***********************************************************************//** 00659 * @brief Load models from XML file 00660 * 00661 * @param[in] filename XML filename. 00662 * 00663 * Loads all models from an XML file. See the read() method for more 00664 * information about the expected structure of the XML file. 00665 ***************************************************************************/ 00666 void GModels::load(const GFilename& filename) 00667 { 00668 // Clear any existing models 00669 clear(); 00670 00671 // Load XML document 00672 GXml xml(filename.url()); 00673 00674 // Read models from XML document 00675 read(xml); 00676 00677 // Return 00678 return; 00679 } 00680 00681 00682 /***********************************************************************//** 00683 * @brief Save models into XML file 00684 * 00685 * @param[in] filename XML filename. 00686 * 00687 * Saves all models in the container into an XML file. 00688 ***************************************************************************/ 00689 void GModels::save(const GFilename& filename) const 00690 { 00691 // Declare empty XML document 00692 GXml xml; 00693 00694 // Write models into XML file 00695 write(xml); 00696 00697 // Save XML document 00698 xml.save(filename); 00699 00700 // Return 00701 return; 00702 } 00703 00704 00705 /***********************************************************************//** 00706 * @brief Read models from XML document 00707 * 00708 * @param[in] xml XML document. 00709 * 00710 * @exception GException::model_invalid 00711 * Invalid model type encountered. 00712 * 00713 * Read models from the first source library found in the XML document. The 00714 * XML document is expected to have the following structure 00715 * 00716 * <source_library title="source library"> 00717 * <source name="Source1" type="PointSource"> 00718 * ... 00719 * </source> 00720 * <source name="Source2" type="DiffuseSource"> 00721 * ... 00722 * </source> 00723 * </source_library> 00724 * 00725 * Each @p source tag will be interpreted as a model component. 00726 * 00727 * @todo Sources names are not verified so far for uniqueness. This would be 00728 * required to achieve an unambiguous update of parameters in an already 00729 * existing XML file when using the write method. 00730 ***************************************************************************/ 00731 void GModels::read(const GXml& xml) 00732 { 00733 // Get pointer on source library 00734 const GXmlElement* lib = xml.element("source_library", 0); 00735 00736 // Loop over all sources 00737 int n = lib->elements("source"); 00738 for (int i = 0; i < n; ++i) { 00739 00740 // Get pointer on source 00741 const GXmlElement* src = lib->element("source", i); 00742 00743 // Get model type 00744 std::string type = src->attribute("type"); 00745 00746 // Get model 00747 GModelRegistry registry; 00748 GModel* ptr = registry.alloc(type); 00749 00750 // If model if valid then read model from XML file 00751 if (ptr != NULL) { 00752 ptr->read(*src); 00753 } 00754 00755 // ... otherwise throw an exception 00756 else { 00757 throw GException::model_invalid(G_READ, type); 00758 } 00759 00760 // Append model 00761 append(*ptr); 00762 00763 // Free model (appending clones the model) 00764 delete ptr; 00765 00766 } // endfor: looped over all sources 00767 00768 // Return 00769 return; 00770 } 00771 00772 00773 /***********************************************************************//** 00774 * @brief Write models into XML document 00775 * 00776 * @param[in] xml XML document. 00777 * 00778 * Write models into the first source library that is found in the XML 00779 * document. In case that no source library exists, one is added to the 00780 * document. 00781 ***************************************************************************/ 00782 void GModels::write(GXml& xml) const 00783 { 00784 // If there is no source library then append one 00785 if (xml.elements("source_library") == 0) { 00786 xml.append(GXmlElement("source_library title=\"source library\"")); 00787 } 00788 00789 // Get pointer on source library 00790 GXmlElement* lib = xml.element("source_library", 0); 00791 00792 // Write all sources into library 00793 for (int i = 0; i < size(); ++i) { 00794 m_models[i]->write(*lib); 00795 } 00796 00797 // Return 00798 return; 00799 } 00800 00801 00802 /***********************************************************************//** 00803 * @brief Return number of model parameters in container 00804 * 00805 * @return Number of model parameters in container. 00806 ***************************************************************************/ 00807 int GModels::npars(void) const 00808 { 00809 // Initialise number of parameters 00810 int npars = 0; 00811 00812 // Sum of number of parameters in model 00813 for (int i = 0; i < size(); ++i) { 00814 npars += m_models[i]->size(); 00815 } 00816 00817 // Return 00818 return npars; 00819 } 00820 00821 00822 /***********************************************************************//** 00823 * @brief Return optimizer parameter container 00824 * 00825 * @return Optimizer parameter container. 00826 * 00827 * Returns an optimizer parameter container that is built by extracting 00828 * all model pointers from the model and attaching them to the parameter 00829 * container. The optimizer parameter container will thus contains a flat 00830 * array of a model parameters. 00831 ***************************************************************************/ 00832 GOptimizerPars GModels::pars(void) const 00833 { 00834 // Initialise parameter container 00835 GOptimizerPars pars; 00836 00837 // Attach all parameters 00838 for (int i = 0; i < size(); ++i) { 00839 GModel* model = m_models[i]; 00840 int npars = model->size(); 00841 for (int k = 0; k < npars; ++k) { 00842 pars.attach(&((*model)[k])); 00843 } 00844 } 00845 00846 // Return 00847 return pars; 00848 } 00849 00850 00851 /***********************************************************************//** 00852 * @brief Evaluate sum of all models 00853 * 00854 * @param[in] event Observed event. 00855 * @param[in] obs Observation. 00856 * @param[in] gradients Compute gradients? 00857 * @return Value of models. 00858 * 00859 * Evaluates the sum of all models for the specified event and observation. 00860 * Only valid models are considered in this evaluation. 00861 * 00862 * If the @p gradients flag is true the method will also set the parameter 00863 * gradients of the model parameters. 00864 ***************************************************************************/ 00865 double GModels::eval(const GEvent& event, 00866 const GObservation& obs, 00867 const bool& gradients) const 00868 { 00869 // Initialise function value 00870 double value = 0.0; 00871 00872 // Evaluate function for all models 00873 for (int i = 0; i < size(); ++i) { 00874 if (m_models[i]->is_valid(obs.instrument(), obs.id())) { 00875 value += m_models[i]->eval(event, obs, gradients); 00876 } 00877 } 00878 00879 // Return 00880 return value; 00881 } 00882 00883 00884 /***********************************************************************//** 00885 * @brief Print models 00886 * 00887 * @param[in] chatter Chattiness (defaults to NORMAL). 00888 * @return String containing model container information. 00889 * 00890 * Prints all models into a string. 00891 ***************************************************************************/ 00892 std::string GModels::print(const GChatter& chatter) const 00893 { 00894 // Initialise result string 00895 std::string result; 00896 00897 // Continue only if chatter is not silent 00898 if (chatter != SILENT) { 00899 00900 // Append header 00901 result.append("=== GModels ==="); 00902 00903 // Append information 00904 result.append("\n"+gammalib::parformat("Number of models")); 00905 result.append(gammalib::str(size())); 00906 result.append("\n"+gammalib::parformat("Number of parameters")); 00907 result.append(gammalib::str(npars())); 00908 00909 // Append models 00910 for (int i = 0; i < size(); ++i) { 00911 result.append("\n"+m_models[i]->print(chatter)); 00912 } 00913 00914 } // endif: chatter was not silent 00915 00916 // Return result 00917 return result; 00918 } 00919 00920 00921 /*========================================================================== 00922 = = 00923 = Private methods = 00924 = = 00925 ==========================================================================*/ 00926 00927 /***********************************************************************//** 00928 * @brief Initialise class members 00929 ***************************************************************************/ 00930 void GModels::init_members(void) 00931 { 00932 // Initialise members 00933 m_models.clear(); 00934 00935 // Return 00936 return; 00937 } 00938 00939 00940 /***********************************************************************//** 00941 * @brief Copy class members 00942 * 00943 * @param[in] models Model container. 00944 * 00945 * Makes a copy of all class members. All models are deep copied, and the 00946 * linear pointer array for parameter access through the GOptimizerPars 00947 * base class is set. 00948 ***************************************************************************/ 00949 void GModels::copy_members(const GModels& models) 00950 { 00951 // Copy models 00952 m_models.clear(); 00953 for (int i = 0; i < models.m_models.size(); ++i) { 00954 m_models.push_back((models.m_models[i]->clone())); 00955 } 00956 00957 // Return 00958 return; 00959 } 00960 00961 00962 /***********************************************************************//** 00963 * @brief Delete class members 00964 * 00965 * Deallocates all models. The method loops over the model container and 00966 * deallocates the memory that has been allocated before. 00967 ***************************************************************************/ 00968 void GModels::free_members(void) 00969 { 00970 // Free models 00971 for (int i = 0; i < m_models.size(); ++i) { 00972 delete m_models[i]; 00973 m_models[i] = NULL; 00974 } 00975 00976 // Return 00977 return; 00978 } 00979 00980 00981 /***********************************************************************//** 00982 * @brief Return model index by name 00983 * 00984 * @param[in] name Model name. 00985 * @return Model index (-1 if model name has not been found) 00986 * 00987 * Returns model index based on the specified @p name. If no model with the 00988 * specified @p name is found the method returns -1. 00989 ***************************************************************************/ 00990 int GModels::get_index(const std::string& name) const 00991 { 00992 // Initialise index 00993 int index = -1; 00994 00995 // Search model with specified name 00996 for (int i = 0; i < size(); ++i) { 00997 if (m_models[i]->name() == name) { 00998 index = i; 00999 break; 01000 } 01001 } 01002 01003 // Return index 01004 return index; 01005 }