00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028 #ifdef HAVE_CONFIG_H
00029 #include <config.h>
00030 #endif
00031 #include "GException.hpp"
00032 #include "GTools.hpp"
00033 #include "GMath.hpp"
00034 #include "GHealpix.hpp"
00035 #include "GEnergies.hpp"
00036 #include "GFits.hpp"
00037 #include "GFitsTable.hpp"
00038 #include "GFitsTableCol.hpp"
00039 #include "GXmlElement.hpp"
00040 #include "GModelSpatialRegistry.hpp"
00041 #include "GModelSpatialDiffuseCube.hpp"
00042
00043
00044
00045
00046 const GModelSpatialDiffuseCube g_spatial_cube_seed;
00047 const GModelSpatialRegistry g_spatial_cube_registry(&g_spatial_cube_seed);
00048 #if defined(G_LEGACY_XML_FORMAT)
00049 const GModelSpatialDiffuseCube g_spatial_cube_legacy_seed(true, "MapCubeFunction");
00050 const GModelSpatialRegistry g_spatial_cube_legacy_registry(&g_spatial_cube_legacy_seed);
00051 #endif
00052
00053
00054 #define G_MC "GModelSpatialDiffuseCube::mc(GEnergy&, GTime&, GRan&)"
00055 #define G_READ "GModelSpatialDiffuseCube::read(GXmlElement&)"
00056 #define G_WRITE "GModelSpatialDiffuseCube::write(GXmlElement&)"
00057 #define G_ENERGIES "GModelSpatialDiffuseCube::energies(GEnergies&)"
00058 #define G_LOAD_CUBE "GModelSpatialDiffuseCube::load_cube(GFilename&)"
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080 GModelSpatialDiffuseCube::GModelSpatialDiffuseCube(void) :
00081 GModelSpatialDiffuse()
00082 {
00083
00084 init_members();
00085
00086
00087 return;
00088 }
00089
00090
00091
00092
00093
00094
00095
00096
00097
00098
00099 GModelSpatialDiffuseCube::GModelSpatialDiffuseCube(const bool& dummy,
00100 const std::string& type) :
00101 GModelSpatialDiffuse()
00102 {
00103
00104 init_members();
00105
00106
00107 m_type = type;
00108
00109
00110 return;
00111 }
00112
00113
00114
00115
00116
00117
00118
00119
00120
00121
00122
00123 GModelSpatialDiffuseCube::GModelSpatialDiffuseCube(const GXmlElement& xml) :
00124 GModelSpatialDiffuse()
00125 {
00126
00127 init_members();
00128
00129
00130 read(xml);
00131
00132
00133 return;
00134 }
00135
00136
00137
00138
00139
00140
00141
00142
00143
00144
00145
00146 GModelSpatialDiffuseCube::GModelSpatialDiffuseCube(const GFilename& filename,
00147 const double& value) :
00148 GModelSpatialDiffuse()
00149 {
00150
00151 init_members();
00152
00153
00154 m_value.value(value);
00155
00156
00157 autoscale();
00158
00159
00160 m_filename = filename;
00161
00162
00163 return;
00164 }
00165
00166
00167
00168
00169
00170
00171
00172
00173
00174
00175
00176
00177
00178 GModelSpatialDiffuseCube::GModelSpatialDiffuseCube(const GSkyMap& cube,
00179 const GEnergies& energies,
00180 const double& value) :
00181 GModelSpatialDiffuse()
00182 {
00183
00184 init_members();
00185
00186
00187 m_value.value(value);
00188
00189
00190 autoscale();
00191
00192
00193 this->cube(cube);
00194
00195
00196 this->energies(energies);
00197
00198
00199 return;
00200 }
00201
00202
00203
00204
00205
00206
00207
00208 GModelSpatialDiffuseCube::GModelSpatialDiffuseCube(const GModelSpatialDiffuseCube& model) :
00209 GModelSpatialDiffuse(model)
00210 {
00211
00212 init_members();
00213
00214
00215 copy_members(model);
00216
00217
00218 return;
00219 }
00220
00221
00222
00223
00224
00225 GModelSpatialDiffuseCube::~GModelSpatialDiffuseCube(void)
00226 {
00227
00228 free_members();
00229
00230
00231 return;
00232 }
00233
00234
00235
00236
00237
00238
00239
00240
00241
00242
00243
00244
00245
00246
00247 GModelSpatialDiffuseCube& GModelSpatialDiffuseCube::operator=(const GModelSpatialDiffuseCube& model)
00248 {
00249
00250 if (this != &model) {
00251
00252
00253 this->GModelSpatialDiffuse::operator=(model);
00254
00255
00256 free_members();
00257
00258
00259 init_members();
00260
00261
00262 copy_members(model);
00263
00264 }
00265
00266
00267 return *this;
00268 }
00269
00270
00271
00272
00273
00274
00275
00276
00277
00278
00279
00280 void GModelSpatialDiffuseCube::clear(void)
00281 {
00282
00283 free_members();
00284 this->GModelSpatialDiffuse::free_members();
00285 this->GModelSpatial::free_members();
00286
00287
00288 this->GModelSpatial::init_members();
00289 this->GModelSpatialDiffuse::init_members();
00290 init_members();
00291
00292
00293 return;
00294 }
00295
00296
00297
00298
00299
00300
00301
00302 GModelSpatialDiffuseCube* GModelSpatialDiffuseCube::clone(void) const
00303 {
00304
00305 return new GModelSpatialDiffuseCube(*this);
00306 }
00307
00308
00309
00310
00311
00312
00313
00314
00315
00316
00317
00318
00319
00320
00321 double GModelSpatialDiffuseCube::eval(const GPhoton& photon,
00322 const bool& gradients) const
00323 {
00324
00325 double intensity = cube_intensity(photon);
00326
00327
00328 double value = intensity * m_value.value();
00329
00330
00331 if (gradients) {
00332
00333
00334
00335 double g_value = (m_value.is_free()) ? intensity * m_value.scale() : 0.0;
00336 if (value < 0.0) {
00337 g_value = 0.0;
00338 }
00339
00340
00341 m_value.factor_gradient(g_value);
00342
00343 }
00344
00345
00346 if (value < 0.0) {
00347 value = 0.0;
00348 }
00349
00350
00351 return value;
00352 }
00353
00354
00355
00356
00357
00358
00359
00360
00361
00362
00363
00364
00365
00366
00367
00368
00369
00370
00371
00372 GSkyDir GModelSpatialDiffuseCube::mc(const GEnergy& energy,
00373 const GTime& time,
00374 GRan& ran) const
00375 {
00376
00377 fetch_cube();
00378
00379
00380 int npix = pixels();
00381
00382
00383 if (npix <= 0) {
00384 std::string msg = "No map cube defined. Please specify a valid map cube.";
00385 throw GException::invalid_value(G_MC, msg);
00386 }
00387
00388
00389 if (m_ebounds.size() < 1) {
00390 std::string msg = "The energy boundaries of the maps in the cube have "
00391 "not been defined. Maybe the map cube file is missing "
00392 "the \"ENERGIES\" extension which defines the energy "
00393 "of each map in the cube. Please provide the energy "
00394 "information.";
00395 throw GException::invalid_value(G_MC, msg);
00396 }
00397
00398
00399 m_logE.set_value(energy.log10MeV());
00400
00401
00402
00403 double max = 0.0;
00404 double max_left = m_mc_max[m_logE.inx_left()];
00405 double max_right = m_mc_max[m_logE.inx_right()];
00406 if (max_left > 0.0 && max_right > 0.0) {
00407 double max_log = m_logE.wgt_left() * std::log(max_left) +
00408 m_logE.wgt_right() * std::log(max_right);
00409 max = std::exp(max_log);
00410 }
00411 else if (max_left > 0.0) {
00412 max = max_left;
00413 }
00414 else if (max_right > 0.0) {
00415 max = max_right;
00416 }
00417
00418
00419
00420
00421 if (max <= 0.0) {
00422 std::string msg = "Simulation cone has not been defined or does not "
00423 "overlap with the sky map. Please specify a valid "
00424 "simulation cone.";
00425 throw GException::invalid_value(G_MC, msg);
00426 }
00427
00428
00429 GSkyDir dir;
00430
00431
00432 #if defined(G_DEBUG_MC)
00433 int num_iterations = 0;
00434 #endif
00435
00436
00437 while (true) {
00438
00439
00440 #if defined(G_DEBUG_MC)
00441 num_iterations++;
00442 #endif
00443
00444
00445 double theta = std::acos(1.0 - ran.uniform() * m_mc_one_minus_cosrad) *
00446 gammalib::rad2deg;
00447 double phi = 360.0 * ran.uniform();
00448 dir = m_mc_centre;
00449 dir.rotate_deg(phi, theta);
00450
00451
00452 double value = 0.0;
00453 double value_left = m_cube(dir, m_logE.inx_left());
00454 double value_right = m_cube(dir, m_logE.inx_right());
00455 if (value_left > 0.0 && value_right > 0.0) {
00456 double value_log = m_logE.wgt_left() * std::log(value_left) +
00457 m_logE.wgt_right() * std::log(value_right);
00458 value = std::exp(value_log);
00459 }
00460 else if (value_left > 0.0) {
00461 value = value_left;
00462 }
00463 else if (value_right > 0.0) {
00464 value = value_right;
00465 }
00466
00467
00468 if (value <= 0.0) {
00469 continue;
00470 }
00471
00472
00473 double uniform = ran.uniform() * max;
00474
00475
00476 if (uniform <= value) {
00477 break;
00478 }
00479
00480 }
00481
00482
00483 #if defined(G_DEBUG_MC)
00484 std::cout << num_iterations << " ";
00485 #endif
00486
00487
00488 return dir;
00489 }
00490
00491
00492
00493
00494
00495
00496
00497
00498
00499
00500
00501
00502
00503
00504 bool GModelSpatialDiffuseCube::contains(const GSkyDir& dir,
00505 const double& margin) const
00506 {
00507 return (true);
00508 }
00509
00510
00511
00512
00513
00514
00515
00516
00517
00518
00519
00520
00521
00522
00523
00524
00525
00526 void GModelSpatialDiffuseCube::read(const GXmlElement& xml)
00527 {
00528
00529
00530 if (gammalib::xml_has_par(xml, "Normalization")) {
00531 const GXmlElement* par = gammalib::xml_get_par(G_READ, xml, "Normalization");
00532 m_value.read(*par);
00533 }
00534
00535
00536 #if defined(G_LEGACY_XML_FORMAT)
00537 else if (gammalib::xml_has_par(xml, "Value")) {
00538 const GXmlElement* par = gammalib::xml_get_par(G_READ, xml, "Value");
00539 m_value.read(*par);
00540 }
00541 #endif
00542
00543
00544 else {
00545 #if defined(G_LEGACY_XML_FORMAT)
00546 std::string msg = "Diffuse map cube model requires either "
00547 "\"Normalization\" or \"Value\" parameter.";
00548 #else
00549 std::string msg = "Diffuse map cube model requires \"Normalization\" "
00550 "parameter.";
00551 #endif
00552 throw GException::invalid_value(G_READ, msg);
00553 }
00554
00555
00556 m_filename = gammalib::xml_file_expand(xml, xml.attribute("file"));
00557
00558
00559 return;
00560 }
00561
00562
00563
00564
00565
00566
00567
00568
00569
00570
00571
00572
00573
00574
00575
00576
00577
00578
00579
00580
00581
00582
00583
00584
00585
00586
00587
00588
00589
00590 void GModelSpatialDiffuseCube::write(GXmlElement& xml) const
00591 {
00592
00593 if (xml.attribute("type") == "") {
00594 xml.attribute("type", type());
00595 }
00596
00597
00598 if (xml.attribute("type") != type()) {
00599 throw GException::model_invalid_spatial(G_WRITE, xml.attribute("type"),
00600 "Spatial model is not of type \""+type()+"\".");
00601 }
00602
00603
00604
00605
00606
00607 if (xml.elements() == 0) {
00608 xml.append(GXmlElement("parameter name=\"Normalization\""));
00609 }
00610
00611
00612 if (xml.elements() != 1 || xml.elements("parameter") != 1) {
00613 throw GException::model_invalid_parnum(G_WRITE, xml,
00614 "Map cube spatial model requires exactly 1 parameter.");
00615 }
00616
00617
00618 GXmlElement* par = xml.element("parameter", 0);
00619
00620
00621 if (par->attribute("name") == "Normalization" ||
00622 par->attribute("name") == "Value") {
00623 m_value.write(*par);
00624 }
00625 else {
00626 throw GException::model_invalid_parnames(G_WRITE, xml,
00627 "Map cube spatial model requires either \"Value\" or"
00628 " \"Normalization\" parameter.");
00629 }
00630
00631
00632
00633 xml.attribute("file", gammalib::xml_file_reduce(xml, m_filename));
00634
00635
00636 return;
00637 }
00638
00639
00640
00641
00642
00643
00644
00645
00646
00647 void GModelSpatialDiffuseCube::cube(const GSkyMap& cube)
00648 {
00649
00650 m_filename.clear();
00651 m_loaded = false;
00652
00653
00654 m_cube = cube;
00655
00656
00657 update_mc_cache();
00658
00659
00660 return;
00661 }
00662
00663
00664
00665
00666
00667
00668
00669
00670
00671
00672
00673
00674 void GModelSpatialDiffuseCube::energies(const GEnergies& energies)
00675 {
00676
00677 m_logE.clear();
00678
00679
00680 fetch_cube();
00681
00682
00683 int num = energies.size();
00684
00685
00686 if (num != m_cube.nmaps() ) {
00687 std::string msg = "Number of specified energies ("+gammalib::str(num)+")"
00688 " does not match the number of maps ("
00689 ""+gammalib::str(m_cube.nmaps())+" in the map cube.\n"
00690 "The energies argument shall provide a vector of length"
00691 " "+gammalib::str(m_cube.nmaps())+".";
00692 throw GException::invalid_argument(G_ENERGIES, msg);
00693 }
00694
00695
00696 for (int i = 0; i < num; ++i) {
00697 m_logE.append(energies[i].log10MeV());
00698 }
00699
00700
00701 set_energy_boundaries();
00702
00703
00704 update_mc_cache();
00705
00706
00707 return;
00708 }
00709
00710
00711
00712
00713
00714
00715
00716
00717
00718 GEnergies GModelSpatialDiffuseCube::energies(void)
00719 {
00720
00721 GEnergies energies;
00722
00723
00724 fetch_cube();
00725
00726
00727 int num = m_logE.size();
00728
00729
00730 if (num > 0) {
00731
00732
00733 energies.reserve(num);
00734
00735
00736 for (int i = 0; i < num; ++i) {
00737 GEnergy energy;
00738 energy.log10MeV(m_logE[i]);
00739 energies.append(energy);
00740 }
00741
00742 }
00743
00744
00745 return energies;
00746 }
00747
00748
00749
00750
00751
00752
00753
00754
00755
00756
00757
00758
00759
00760 void GModelSpatialDiffuseCube::set_mc_cone(const GSkyDir& centre,
00761 const double& radius) const
00762 {
00763
00764 if ((centre != m_mc_centre) || (radius != m_mc_radius)) {
00765
00766
00767 m_mc_centre = centre;
00768 m_mc_radius = radius;
00769
00770
00771 m_mc_one_minus_cosrad = 1.0 - std::cos(m_mc_radius*gammalib::deg2rad);
00772
00773
00774 m_mc_max.clear();
00775 m_mc_spectrum.clear();
00776
00777
00778 fetch_cube();
00779
00780
00781 int npix = pixels();
00782 int nmaps = maps();
00783
00784
00785 if (npix > 0 && nmaps > 0) {
00786
00787
00788 m_mc_max.reserve(nmaps);
00789 m_mc_spectrum.reserve(nmaps);
00790
00791
00792 for (int i = 0; i < nmaps; ++i) {
00793
00794
00795
00796 double total_flux = 0.0;
00797 double max_intensity = 0.0;
00798 for (int k = 0; k < npix; ++k) {
00799 double distance = centre.dist_deg(m_cube.pix2dir(k));
00800 if (distance <= radius) {
00801 double flux = m_cube.flux(k,i);
00802 if (flux > 0.0) {
00803 total_flux += flux;
00804 }
00805 double value = m_cube(k,i);
00806 if (value > max_intensity) {
00807 max_intensity = value;
00808 }
00809 }
00810 }
00811
00812
00813 m_mc_max.push_back(max_intensity);
00814
00815
00816 if (m_logE.size() == nmaps) {
00817
00818
00819 GEnergy energy;
00820 energy.log10MeV(m_logE[i]);
00821
00822
00823
00824 if (total_flux > 0.0) {
00825 m_mc_spectrum.append(energy, total_flux);
00826 }
00827
00828 }
00829
00830 }
00831
00832
00833 #if defined(G_DEBUG_MC_CACHE)
00834 std::cout << "GModelSpatialDiffuseCube::set_mc_cone:" << std::endl;
00835 std::cout << " Maximum map intensity:" << std::endl;
00836 for (int i = 0; i < m_mc_max.size(); ++i) {
00837 GEnergy energy;
00838 energy.log10MeV(m_logE[i]);
00839 std::cout << " " << i;
00840 std::cout << " " << energy;
00841 std::cout << " " << m_mc_max[i] << " ph/cm2/s/sr/MeV";
00842 std::cout << std::endl;
00843 }
00844 std::cout << " Spatially integrated flux:" << std::endl;
00845 for (int i = 0; i < m_mc_spectrum.nodes(); ++i) {
00846 std::cout << " " << i;
00847 std::cout << " " << m_mc_spectrum.energy(i);
00848 std::cout << " " << m_mc_spectrum.intensity(i);
00849 std::cout << " ph/cm2/s/MeV" << std::endl;
00850 }
00851 #endif
00852
00853 }
00854
00855 }
00856
00857
00858 return;
00859 }
00860
00861
00862
00863
00864
00865
00866
00867
00868
00869 void GModelSpatialDiffuseCube::load(const GFilename& filename)
00870 {
00871
00872 load_cube(filename);
00873
00874
00875 update_mc_cache();
00876
00877
00878 return;
00879 }
00880
00881
00882
00883
00884
00885
00886
00887
00888
00889
00890 void GModelSpatialDiffuseCube::save(const GFilename& filename,
00891 const bool& clobber) const
00892 {
00893
00894 GFits fits;
00895
00896
00897 write(fits);
00898
00899
00900 fits.saveto(filename, clobber);
00901
00902
00903 return;
00904 }
00905
00906
00907
00908
00909
00910
00911
00912 void GModelSpatialDiffuseCube::write(GFits& file) const
00913 {
00914
00915 m_cube.write(file);
00916
00917
00918 GEnergies energies;
00919 for (int i = 0; i < m_logE.size(); ++i) {
00920 double energy = std::pow(10.0, m_logE[i]);
00921 energies.append(GEnergy(energy, "MeV"));
00922 }
00923
00924
00925 energies.write(file);
00926
00927
00928 return;
00929 }
00930
00931
00932
00933
00934
00935
00936
00937
00938 std::string GModelSpatialDiffuseCube::print(const GChatter& chatter) const
00939 {
00940
00941 std::string result;
00942
00943
00944 if (chatter != SILENT) {
00945
00946
00947 result.append("=== GModelSpatialDiffuseCube ===");
00948
00949
00950 result.append("\n"+gammalib::parformat("Map cube file"));
00951 result.append(m_filename);
00952 if (m_loaded) {
00953 result.append(" [loaded]");
00954 }
00955 result.append("\n"+gammalib::parformat("Number of parameters"));
00956 result.append(gammalib::str(size()));
00957 for (int i = 0; i < size(); ++i) {
00958 result.append("\n"+m_pars[i]->print(chatter));
00959 }
00960
00961
00962 if (m_cube.npix() > 0) {
00963
00964
00965 if (chatter >= NORMAL) {
00966 result.append("\n"+m_cube.print(chatter));
00967 }
00968
00969
00970 if (chatter >= EXPLICIT && m_logE.size() > 0) {
00971 result.append("\n"+gammalib::parformat("Map energy values"));
00972 if (m_logE.size() > 0) {
00973 for (int i = 0; i < m_logE.size(); ++i) {
00974 result.append("\n"+gammalib::parformat(" Map "+gammalib::str(i+1)));
00975 result.append(gammalib::str(std::pow(10.0, m_logE[i])));
00976 result.append(" MeV (log10E=");
00977 result.append(gammalib::str(m_logE[i]));
00978 result.append(")");
00979 if (m_ebounds.size() == m_logE.size()) {
00980 result.append(" [");
00981 result.append(m_ebounds.emin(i).print());
00982 result.append(", ");
00983 result.append(m_ebounds.emax(i).print());
00984 result.append("]");
00985 }
00986 }
00987 }
00988 else {
00989 result.append("not specified");
00990 }
00991 }
00992
00993
00994 if (chatter >= VERBOSE) {
00995 result.append("\n"+gammalib::parformat("Map flux"));
00996 if (m_mc_spectrum.nodes() > 0) {
00997 for (int i = 0; i < m_mc_spectrum.nodes(); ++i) {
00998 result.append("\n"+gammalib::parformat(" Map "+gammalib::str(i+1)));
00999 result.append(gammalib::str(m_mc_spectrum.intensity(i)));
01000 }
01001 }
01002 else {
01003 result.append("not specified");
01004 }
01005 }
01006
01007 }
01008
01009 }
01010
01011
01012 return result;
01013 }
01014
01015
01016
01017
01018
01019
01020
01021
01022
01023
01024
01025 void GModelSpatialDiffuseCube::init_members(void)
01026 {
01027
01028 m_type = "DiffuseMapCube";
01029
01030
01031 m_value.clear();
01032 m_value.name("Normalization");
01033 m_value.value(1.0);
01034 m_value.scale(1.0);
01035 m_value.range(0.001, 1000.0);
01036 m_value.gradient(0.0);
01037 m_value.fix();
01038 m_value.has_grad(true);
01039
01040
01041 m_pars.clear();
01042 m_pars.push_back(&m_value);
01043
01044
01045 m_filename.clear();
01046 m_cube.clear();
01047 m_logE.clear();
01048 m_ebounds.clear();
01049 m_loaded = false;
01050 m_region.clear();
01051
01052
01053 m_mc_centre.clear();
01054 m_mc_radius = -1.0;
01055 m_mc_one_minus_cosrad = 1.0;
01056 m_mc_max.clear();
01057 m_mc_spectrum.clear();
01058
01059
01060 return;
01061 }
01062
01063
01064
01065
01066
01067
01068
01069 void GModelSpatialDiffuseCube::copy_members(const GModelSpatialDiffuseCube& model)
01070 {
01071
01072 m_type = model.m_type;
01073 m_value = model.m_value;
01074 m_filename = model.m_filename;
01075 m_cube = model.m_cube;
01076 m_logE = model.m_logE;
01077 m_ebounds = model.m_ebounds;
01078 m_loaded = model.m_loaded;
01079 m_region = model.m_region;
01080
01081
01082 m_mc_centre = model.m_mc_centre;
01083 m_mc_radius = model.m_mc_radius;
01084 m_mc_one_minus_cosrad = model.m_mc_one_minus_cosrad;
01085 m_mc_max = model.m_mc_max;
01086 m_mc_spectrum = model.m_mc_spectrum;
01087
01088
01089 m_pars.clear();
01090 m_pars.push_back(&m_value);
01091
01092
01093 return;
01094 }
01095
01096
01097
01098
01099
01100 void GModelSpatialDiffuseCube::free_members(void)
01101 {
01102
01103 return;
01104 }
01105
01106
01107
01108
01109
01110
01111
01112 void GModelSpatialDiffuseCube::fetch_cube(void) const
01113 {
01114
01115 if (!m_loaded && !m_filename.is_empty()) {
01116
01117
01118 #pragma omp critical(GModelSpatialDiffuseCube_fetch_cube)
01119 {
01120 const_cast<GModelSpatialDiffuseCube*>(this)->load_cube(m_filename);
01121 }
01122
01123 }
01124
01125
01126 return;
01127 }
01128
01129
01130
01131
01132
01133
01134
01135
01136
01137
01138
01139
01140 void GModelSpatialDiffuseCube::load_cube(const GFilename& filename)
01141 {
01142
01143 m_cube.clear();
01144 m_logE.clear();
01145
01146
01147
01148
01149
01150 m_filename = filename;
01151
01152
01153 m_cube.load(filename);
01154
01155
01156 GEnergies energies(filename);
01157
01158
01159 int num = energies.size();
01160
01161
01162 if (num != m_cube.nmaps() ) {
01163 std::string msg = "Number of energies in \"ENERGIES\""
01164 " extension ("+gammalib::str(num)+")"
01165 " does not match the number of maps ("+
01166 gammalib::str(m_cube.nmaps())+" in the"
01167 " map cube.\n"
01168 "The \"ENERGIES\" extension table shall"
01169 " provide one enegy value for each map"
01170 " in the cube.";
01171 throw GException::invalid_value(G_LOAD_CUBE, msg);
01172 }
01173
01174
01175 for (int i = 0; i < num; ++i) {
01176 m_logE.append(energies[i].log10MeV());
01177 }
01178
01179
01180 m_loaded = true;
01181
01182
01183 set_energy_boundaries();
01184
01185
01186 return;
01187 }
01188
01189
01190
01191
01192
01193
01194
01195
01196
01197 void GModelSpatialDiffuseCube::set_energy_boundaries(void)
01198 {
01199
01200 m_ebounds.clear();
01201
01202
01203 int num = m_logE.size();
01204
01205
01206 if (num > 1) {
01207
01208
01209 for (int i = 0; i < num; ++i) {
01210
01211
01212 double e_min = (i == 0) ? m_logE[i] - 0.5 * (m_logE[i+1] - m_logE[i])
01213 : m_logE[i] - 0.5 * (m_logE[i] - m_logE[i-1]);
01214
01215
01216 double e_max = (i < num-1) ? m_logE[i] + 0.5 * (m_logE[i+1] - m_logE[i])
01217 : m_logE[i] + 0.5 * (m_logE[i] - m_logE[i-1]);
01218
01219
01220 GEnergy emin;
01221 GEnergy emax;
01222 emin.log10MeV(e_min);
01223 emax.log10MeV(e_max);
01224
01225
01226 m_ebounds.append(emin, emax);
01227
01228 }
01229
01230 }
01231
01232
01233 return;
01234 }
01235
01236
01237
01238
01239
01240
01241
01242
01243
01244 void GModelSpatialDiffuseCube::update_mc_cache(void)
01245 {
01246
01247 GSkyDir centre;
01248 double radius = 360.0;
01249
01250
01251 set_mc_cone(centre, radius);
01252
01253
01254 return;
01255 }
01256
01257
01258
01259
01260
01261
01262
01263
01264 double GModelSpatialDiffuseCube::cube_intensity(const GPhoton& photon) const
01265 {
01266
01267 fetch_cube();
01268
01269
01270 double intensity = 0.0;
01271
01272
01273 if (m_logE.size() > 0) {
01274
01275
01276 m_logE.set_value(photon.energy().log10MeV());
01277
01278
01279 double left_intensity = m_cube(photon.dir(), m_logE.inx_left());
01280 double right_intensity = m_cube(photon.dir(), m_logE.inx_right());
01281
01282
01283 if (left_intensity > 0.0 && right_intensity > 0.0) {
01284 double log_intensity = m_logE.wgt_left() * std::log(left_intensity) +
01285 m_logE.wgt_right() * std::log(right_intensity);
01286 intensity = std::exp(log_intensity);
01287 }
01288 else if (left_intensity > 0.0) {
01289 intensity = left_intensity;
01290 }
01291 else if (right_intensity > 0.0) {
01292 intensity = right_intensity;
01293 }
01294
01295 }
01296
01297
01298 return intensity;
01299 }
01300
01301
01302
01303
01304
01305
01306
01307 void GModelSpatialDiffuseCube::set_region(void) const
01308 {
01309
01310 m_region.centre(0.0, 0.0);
01311
01312
01313 m_region.radius(180.0);
01314
01315
01316 return;
01317 }