Commit 0d92b43b4e44fd91f2c02dbb060570802e13fbbc
1 parent
18b7c535
Started to impelement gaussian error propagation for ctbutterfly
Showing
3 changed files
with
247 additions
and
132 deletions
src/ctbutterfly/ctbutterfly.cpp
| ... | ... | @@ -243,12 +243,15 @@ void ctbutterfly::run(void) |
| 243 | 243 | m_obs.optimize(m_opt); |
| 244 | 244 | m_obs.errors(m_opt); |
| 245 | 245 | |
| 246 | - // Get covariance matrix by inverting the curvature matrix. Note that | |
| 247 | - // the curvature matrix is for the unscaled parameters, hence we have | |
| 248 | - // to scale them before we can proceed. | |
| 246 | + // Get covariance matrix. | |
| 249 | 247 | GObservations::likelihood likelihood = m_obs.function(); |
| 250 | - m_covariance = likelihood.curvature()->invert(); | |
| 251 | - | |
| 248 | + if(!gepmode) { | |
| 249 | + m_covariance = likelihood.curvature()->invert(); | |
| 250 | + } | |
| 251 | + else { | |
| 252 | + m_covariance = likelihood.covariance(); | |
| 253 | + } | |
| 254 | + | |
| 252 | 255 | // Write optimizer, optimised model and covariance matrix into logger |
| 253 | 256 | log_string(NORMAL, m_opt.print(m_chatter)); |
| 254 | 257 | log_string(NORMAL, m_obs.models().print(m_chatter)); |
| ... | ... | @@ -271,10 +274,13 @@ void ctbutterfly::run(void) |
| 271 | 274 | GObservations::likelihood likelihood = m_obs.function(); |
| 272 | 275 | likelihood.eval(pars); |
| 273 | 276 | |
| 274 | - // Get covariance matrix by inverting the curvature matrix. Note that | |
| 275 | - // the curvature matrix is for the unscaled parameters, hence we have | |
| 276 | - // to scale them before we can proceed. | |
| 277 | - m_covariance = likelihood.curvature()->invert(); | |
| 277 | + // Get covariance matrix. | |
| 278 | + if(!gepmode) { | |
| 279 | + m_covariance = likelihood.curvature()->invert(); | |
| 280 | + } | |
| 281 | + else { | |
| 282 | + m_covariance = likelihood.covariance(); | |
| 283 | + } | |
| 278 | 284 | |
| 279 | 285 | // Write covariance matrix into logger |
| 280 | 286 | log_string(EXPLICIT, m_covariance.print(m_chatter)); |
| ... | ... | @@ -284,105 +290,130 @@ void ctbutterfly::run(void) |
| 284 | 290 | // Write header into logger |
| 285 | 291 | log_header1(TERSE, "Prepare butterfly computation"); |
| 286 | 292 | |
| 287 | - // Find parameter indices. We do this by the memory location of the | |
| 288 | - // model parameters. | |
| 289 | - GModelSky* skymodel = dynamic_cast<GModelSky*>(models[m_srcname]); | |
| 290 | - GModelPar* par_prefactor = &(*skymodel)["Prefactor"]; | |
| 291 | - GModelPar* par_index = &(*skymodel)["Index"]; | |
| 292 | - int inx_prefactor = -1; | |
| 293 | - int inx_index = -1; | |
| 294 | - for (int i = 0; i < models.npars(); ++i) { | |
| 295 | - if (models.pars()[i] == par_prefactor) { | |
| 296 | - inx_prefactor = i; | |
| 297 | - } | |
| 298 | - if (models.pars()[i] == par_index) { | |
| 299 | - inx_index = i; | |
| 293 | + if (!m_gepmode) { | |
| 294 | + | |
| 295 | + // Find parameter indices. We do this by the memory location of the | |
| 296 | + // model parameters. | |
| 297 | + GModelSky* skymodel = dynamic_cast<GModelSky*>(models[m_srcname]); | |
| 298 | + GModelPar* par_prefactor = &(*skymodel)["Prefactor"]; | |
| 299 | + GModelPar* par_index = &(*skymodel)["Index"]; | |
| 300 | + int inx_prefactor = -1; | |
| 301 | + int inx_index = -1; | |
| 302 | + for (int i = 0; i < models.npars(); ++i) { | |
| 303 | + if (models.pars()[i] == par_prefactor) { | |
| 304 | + inx_prefactor = i; | |
| 305 | + } | |
| 306 | + if (models.pars()[i] == par_index) { | |
| 307 | + inx_index = i; | |
| 308 | + } | |
| 300 | 309 | } |
| 301 | - } | |
| 302 | 310 | |
| 303 | - // Store model values and scales | |
| 304 | - double prefactor_mean = (*skymodel)["Prefactor"].value(); | |
| 305 | - double index_mean = (*skymodel)["Index"].value(); | |
| 306 | - double pivot_mean = (*skymodel)["PivotEnergy"].value(); | |
| 307 | - double prefactor_scale = (*skymodel)["Prefactor"].scale(); | |
| 308 | - double index_scale = (*skymodel)["Index"].scale(); | |
| 309 | - GEnergy pivot(pivot_mean, "MeV"); | |
| 310 | - | |
| 311 | - // Write parameter indices into logger | |
| 312 | - log_value(NORMAL, "Prefactor", gammalib::str(prefactor_mean)+ | |
| 313 | - " ph/cm2/s/MeV ("+gammalib::str(inx_prefactor)+")"); | |
| 314 | - log_value(NORMAL, "Index", gammalib::str(index_mean)+ | |
| 315 | - " ("+gammalib::str(inx_index)+")"); | |
| 316 | - log_value(NORMAL, "Pivot energy", pivot.print()); | |
| 317 | - | |
| 318 | - // Extract covariance elements | |
| 319 | - double cov_pp = m_covariance(inx_prefactor,inx_prefactor); | |
| 320 | - double cov_pg = m_covariance(inx_prefactor,inx_index); | |
| 321 | - double cov_gg = m_covariance(inx_index,inx_index); | |
| 322 | - | |
| 323 | - // Compute eigenvectors and eigenvalues | |
| 324 | - double lambda1; | |
| 325 | - double lambda2; | |
| 326 | - GVector vector1(2); | |
| 327 | - GVector vector2(2); | |
| 328 | - eigenvectors(cov_pp, cov_pg, cov_pg, cov_gg, | |
| 329 | - &lambda1, &lambda2, &vector1, &vector2); | |
| 330 | - | |
| 331 | - // Write eigenvectors and eigenvalues into logger | |
| 332 | - log_value(NORMAL, "Eigenvalue 1", lambda1); | |
| 333 | - log_value(NORMAL, "Eigenvalue 2", lambda2); | |
| 334 | - log_value(NORMAL, "Eigenvector 1", vector1.print()); | |
| 335 | - log_value(NORMAL, "Eigenvector 2", vector2.print()); | |
| 336 | - | |
| 337 | - // Confidence scaling | |
| 338 | - double sigma = gammalib::erfinv(m_confidence) * gammalib::sqrt_two; | |
| 339 | - double scale = (sigma*sigma); | |
| 340 | - | |
| 341 | - // Write confidence level information into logger | |
| 342 | - log_value(NORMAL, "Confidence level", m_confidence); | |
| 343 | - log_value(NORMAL, "Corresponding scaling", scale); | |
| 344 | - | |
| 345 | - // Compute minor and major axes of error ellipse | |
| 346 | - double major = scale*std::sqrt(lambda1); | |
| 347 | - double minor = scale*std::sqrt(lambda2); | |
| 311 | + // Store model values | |
| 312 | + double prefactor_mean = (*skymodel)["Prefactor"].value(); | |
| 313 | + double index_mean = (*skymodel)["Index"].value(); | |
| 314 | + double pivot_mean = (*skymodel)["PivotEnergy"].value(); | |
| 315 | + GEnergy pivot(pivot_mean, "MeV"); | |
| 316 | + | |
| 317 | + // Write parameter indices into logger | |
| 318 | + log_value(NORMAL, "Prefactor", gammalib::str(prefactor_mean)+ | |
| 319 | + " ph/cm2/s/MeV ("+gammalib::str(inx_prefactor)+")"); | |
| 320 | + log_value(NORMAL, "Index", gammalib::str(index_mean)+ | |
| 321 | + " ("+gammalib::str(inx_index)+")"); | |
| 322 | + log_value(NORMAL, "Pivot energy", pivot.print()); | |
| 323 | + | |
| 324 | + // Extract covariance elements | |
| 325 | + double cov_pp = m_covariance(inx_prefactor,inx_prefactor); | |
| 326 | + double cov_pg = m_covariance(inx_prefactor,inx_index); | |
| 327 | + double cov_gg = m_covariance(inx_index,inx_index); | |
| 328 | + | |
| 329 | + // Compute eigenvectors and eigenvalues | |
| 330 | + double lambda1; | |
| 331 | + double lambda2; | |
| 332 | + GVector vector1(2); | |
| 333 | + GVector vector2(2); | |
| 334 | + eigenvectors(cov_pp, cov_pg, cov_pg, cov_gg, | |
| 335 | + &lambda1, &lambda2, &vector1, &vector2); | |
| 336 | + | |
| 337 | + // Write eigenvectors and eigenvalues into logger | |
| 338 | + log_value(NORMAL, "Eigenvalue 1", lambda1); | |
| 339 | + log_value(NORMAL, "Eigenvalue 2", lambda2); | |
| 340 | + log_value(NORMAL, "Eigenvector 1", vector1.print()); | |
| 341 | + log_value(NORMAL, "Eigenvector 2", vector2.print()); | |
| 342 | + | |
| 343 | + // Confidence scaling | |
| 344 | + double sigma = gammalib::erfinv(m_confidence) * gammalib::sqrt_two; | |
| 345 | + double scale = (sigma*sigma); | |
| 346 | + | |
| 347 | + // Write confidence level information into logger | |
| 348 | + log_value(NORMAL, "Confidence level", m_confidence); | |
| 349 | + log_value(NORMAL, "Corresponding scaling", scale); | |
| 350 | + | |
| 351 | + // Compute minor and major axes of error ellipse | |
| 352 | + double major = scale*std::sqrt(lambda1); | |
| 353 | + double minor = scale*std::sqrt(lambda2); | |
| 348 | 354 | |
| 349 | - // Write header into logger | |
| 350 | - log_header1(TERSE, "Generate butterfly"); | |
| 351 | - | |
| 352 | - // Initialise result arrays | |
| 353 | - m_energies.assign(m_ebounds.size(), 0.0); | |
| 354 | - m_intensities.assign(m_ebounds.size(), 0.0); | |
| 355 | - m_min_intensities.assign(m_ebounds.size(), 1e30); | |
| 356 | - m_max_intensities.assign(m_ebounds.size(), 0.0); | |
| 357 | - | |
| 358 | - // Walk around the error ellipse | |
| 359 | - int nt = 360; | |
| 360 | - double dt = gammalib::twopi/double(nt); | |
| 361 | - double t = 0.0; | |
| 362 | - for (int i = 0; i < nt; ++i, t += dt) { | |
| 363 | - | |
| 364 | - // Pre-compute sin and cosine | |
| 365 | - double sin_t = std::sin(t); | |
| 366 | - double cos_t = std::cos(t); | |
| 367 | - | |
| 368 | - // Compute prefactor and index | |
| 369 | - double prefactor = (major * cos_t * vector1[0] + | |
| 370 | - minor * sin_t * vector2[0]) * prefactor_scale + | |
| 371 | - prefactor_mean; | |
| 372 | - double index = (major * cos_t * vector1[1] + | |
| 373 | - minor * sin_t * vector2[1]) * index_scale + | |
| 374 | - index_mean; | |
| 375 | - | |
| 376 | - // Write prefactor and index into logger | |
| 377 | - log_value(EXPLICIT, "Angle "+gammalib::str(t*gammalib::rad2deg), | |
| 378 | - gammalib::str(prefactor)+" ph/cm2/s/MeV; "+ | |
| 379 | - gammalib::str(index)); | |
| 380 | - | |
| 381 | - // Setup power law model | |
| 382 | - GModelSpectralPlaw plaw(prefactor, index, pivot); | |
| 383 | - | |
| 384 | - // Evaluate power law at each energy and extract minimum and | |
| 385 | - // maximum intensity | |
| 355 | + // Write header into logger | |
| 356 | + log_header1(TERSE, "Generate butterfly"); | |
| 357 | + | |
| 358 | + // Initialise result arrays | |
| 359 | + m_energies.assign(m_ebounds.size(), 0.0); | |
| 360 | + m_intensities.assign(m_ebounds.size(), 0.0); | |
| 361 | + m_min_intensities.assign(m_ebounds.size(), 1e30); | |
| 362 | + m_max_intensities.assign(m_ebounds.size(), 0.0); | |
| 363 | + | |
| 364 | + // Walk around the error ellipse | |
| 365 | + int nt = 360; | |
| 366 | + double dt = gammalib::twopi/double(nt); | |
| 367 | + double t = 0.0; | |
| 368 | + for (int i = 0; i < nt; ++i, t += dt) { | |
| 369 | + | |
| 370 | + // Pre-compute sin and cosine | |
| 371 | + double sin_t = std::sin(t); | |
| 372 | + double cos_t = std::cos(t); | |
| 373 | + | |
| 374 | + // Compute prefactor and index | |
| 375 | + double prefactor = (major * cos_t * vector1[0] + | |
| 376 | + minor * sin_t * vector2[0]) + | |
| 377 | + prefactor_mean; | |
| 378 | + double index = (major * cos_t * vector1[1] + | |
| 379 | + minor * sin_t * vector2[1]) + | |
| 380 | + index_mean; | |
| 381 | + | |
| 382 | + // Write prefactor and index into logger | |
| 383 | + log_value(EXPLICIT, "Angle "+gammalib::str(t*gammalib::rad2deg), | |
| 384 | + gammalib::str(prefactor)+" ph/cm2/s/MeV; "+ | |
| 385 | + gammalib::str(index)); | |
| 386 | + | |
| 387 | + // Setup power law model | |
| 388 | + GModelSpectralPlaw plaw(prefactor, index, pivot); | |
| 389 | + | |
| 390 | + // Evaluate power law at each energy and extract minimum and | |
| 391 | + // maximum intensity | |
| 392 | + for (int k = 0; k < m_ebounds.size(); ++k) { | |
| 393 | + | |
| 394 | + // Get the energy of current bin | |
| 395 | + GTime time; | |
| 396 | + GEnergy energy = m_ebounds.elogmean(k); | |
| 397 | + | |
| 398 | + // Evaluate power law | |
| 399 | + double intensity = plaw.eval(energy, time); | |
| 400 | + | |
| 401 | + // Get extremes | |
| 402 | + if (intensity < m_min_intensities[k]) { | |
| 403 | + m_min_intensities[k] = intensity; | |
| 404 | + } | |
| 405 | + if (intensity > m_max_intensities[k]) { | |
| 406 | + m_max_intensities[k] = intensity; | |
| 407 | + } | |
| 408 | + | |
| 409 | + } // endfor: looped over all energies | |
| 410 | + | |
| 411 | + } // endfor: looped over all angles | |
| 412 | + | |
| 413 | + // Setup power law model for mean prefactor and index | |
| 414 | + GModelSpectralPlaw plaw(prefactor_mean, index_mean, pivot); | |
| 415 | + | |
| 416 | + // Compute energy and intensity vectors for mean power law | |
| 386 | 417 | for (int k = 0; k < m_ebounds.size(); ++k) { |
| 387 | 418 | |
| 388 | 419 | // Get the energy of current bin |
| ... | ... | @@ -392,37 +423,112 @@ void ctbutterfly::run(void) |
| 392 | 423 | // Evaluate power law |
| 393 | 424 | double intensity = plaw.eval(energy, time); |
| 394 | 425 | |
| 395 | - // Get extremes | |
| 396 | - if (intensity < m_min_intensities[k]) { | |
| 397 | - m_min_intensities[k] = intensity; | |
| 398 | - } | |
| 399 | - if (intensity > m_max_intensities[k]) { | |
| 400 | - m_max_intensities[k] = intensity; | |
| 401 | - } | |
| 426 | + // Store results | |
| 427 | + m_energies[k] = energy.MeV(); | |
| 428 | + m_intensities[k] = intensity; | |
| 429 | + | |
| 430 | + } // endfor: looped over energies | |
| 402 | 431 | |
| 403 | - } // endfor: looped over all energies | |
| 432 | + } //endif: use butterfly envelope for computation | |
| 404 | 433 | |
| 405 | - } // endfor: looped over all angles | |
| 434 | + else { | |
| 406 | 435 | |
| 407 | - // Setup power law model for mean prefactor and index | |
| 408 | - GModelSpectralPlaw plaw(prefactor_mean, index_mean, pivot); | |
| 436 | + // Use gaussian error propagation scheme to calculate | |
| 437 | + // butterfly | |
| 438 | + log_header2(TERSE, "Using gaussian error propagation to" | |
| 439 | + " calculate butterfly"); | |
| 409 | 440 | |
| 410 | - // Compute energy and intensity vectors for mean power law | |
| 411 | - for (int k = 0; k < m_ebounds.size(); ++k) { | |
| 441 | + // Initialise dummy time to evaluate spectral model | |
| 442 | + GTime time = GTime(); | |
| 412 | 443 | |
| 413 | - // Get the energy of current bin | |
| 414 | - GTime time; | |
| 415 | - GEnergy energy = m_ebounds.elogmean(k); | |
| 444 | + // Initialise vector of gradients | |
| 445 | + GVector grad = GVector(m_obs.models().npars()); | |
| 416 | 446 | |
| 417 | - // Evaluate power law | |
| 418 | - double intensity = plaw.eval(energy, time); | |
| 447 | + // Loop over energy bins positions | |
| 448 | + for (int i = 0; i < m_ebounds.size(); ++i) { | |
| 419 | 449 | |
| 420 | - // Store results | |
| 421 | - m_energies[k] = energy.MeV(); | |
| 422 | - m_intensities[k] = intensity; | |
| 450 | + // Initialise number of gradients | |
| 451 | + int num_gradient = 0; | |
| 423 | 452 | |
| 424 | - } // endfor: looped over energies | |
| 453 | + // Get the energy of current bin | |
| 454 | + GEnergy energy = m_ebounds.elogmean(i); | |
| 455 | + | |
| 456 | + // Log status info | |
| 457 | + std::string msg = "Computing butterfly for bin number "+ | |
| 458 | + gammalib::str(i)+" at "+energy.print(); | |
| 459 | + log_string(NORMAL, msg); | |
| 460 | + | |
| 461 | + // Initialise model flux value | |
| 462 | + double model_flux = 0.0; | |
| 463 | + | |
| 464 | + // Loop over models | |
| 465 | + for (int j = 0; j < models.size(); ++j) { | |
| 466 | + | |
| 467 | + // Check wether model is a skymodel | |
| 468 | + GModelSky* skymodel = dynamic_cast<GModelSky*>(models[j]); | |
| 469 | + | |
| 470 | + // Yes ... | |
| 471 | + if (skymodel != NULL) { | |
| 472 | + | |
| 473 | + // Skip spatial models | |
| 474 | + num_gradient += skymodel->spatial()->size(); | |
| 475 | + | |
| 476 | + // Get pointer to spectral model | |
| 477 | + GModelSpectral* spectral = skymodel->spectral(); | |
| 478 | + | |
| 479 | + // Set flux value of source of interest, evaluate gradients | |
| 480 | + if (skymodel->name() == m_srcname) { | |
| 481 | + model_flux = spectral->eval(energy, time, true); | |
| 482 | + } // endif: model was source of interest | |
| 483 | + | |
| 484 | + // Loop over model parameters, get gradients | |
| 485 | + // and assign them to the vector | |
| 486 | + if(skymodel->name() == m_srcname) { | |
| 487 | + | |
| 488 | + // set gradient if we deal with source of interest | |
| 489 | + for (int k = 0; k < spectral->size(); ++k) { | |
| 490 | + grad[num_gradient] = (*spectral)[k].gradient(); | |
| 491 | + num_gradient++; | |
| 492 | + | |
| 493 | + } // endfor: looped over spectral parameters | |
| 494 | + | |
| 495 | + } //endif: spectrum was of source of interest | |
| 496 | + else{ | |
| 497 | + // Skip gradient of other models (0=default) | |
| 498 | + num_gradient += skymodel->spectral()->size(); | |
| 499 | + | |
| 500 | + } //endelse: Model was not model of interest | |
| 501 | + | |
| 502 | + // Skip temporal models | |
| 503 | + num_gradient += skymodel->temporal()->size(); | |
| 504 | + | |
| 505 | + } // endif: model was sky model | |
| 506 | + | |
| 507 | + else { | |
| 508 | + // Skip other models (e.g. GModelData instances) | |
| 509 | + num_gradient += models[j]->size(); | |
| 510 | + | |
| 511 | + } // endelse: Model was not GModelSky | |
| 512 | + | |
| 513 | + } // endfor: Looped over models | |
| 514 | + | |
| 515 | + // Multiply covariance to the gradient vector | |
| 516 | + GVector vector = m_covariance * grad; | |
| 517 | + | |
| 518 | + // Get the error from the scalar product | |
| 519 | + double error = std::sqrt(grad * vector); | |
| 520 | + | |
| 521 | + // Store flux, value and energy for saving | |
| 522 | + m_intensities.push_back(model_flux); | |
| 523 | + m_energies.push_back(energy.MeV()); | |
| 524 | + m_min_intensities.push_back(model_flux-error); | |
| 525 | + m_max_intensities.push_back(model_flux+error); | |
| 526 | + | |
| 527 | + } //endfor: loop over energy bin | |
| 528 | + | |
| 529 | + } //endelse: use gaussian error propagation | |
| 425 | 530 | |
| 531 | + | |
| 426 | 532 | // Write header into logger |
| 427 | 533 | log_header1(TERSE, "Results"); |
| 428 | 534 | |
| ... | ... | @@ -434,9 +540,11 @@ void ctbutterfly::run(void) |
| 434 | 540 | gammalib::str(m_intensities[k])+" ("+ |
| 435 | 541 | gammalib::str(m_min_intensities[k])+", "+ |
| 436 | 542 | gammalib::str(m_max_intensities[k])+") ph/cm2/s/MeV"); |
| 543 | + | |
| 544 | + } //endfor: loop over energy bin | |
| 545 | + | |
| 437 | 546 | |
| 438 | - } // endfor: looped over energies | |
| 439 | - | |
| 547 | + | |
| 440 | 548 | // Restore energy dispersion flag for all CTA observations |
| 441 | 549 | for (int i = 0; i < m_obs.size(); ++i) { |
| 442 | 550 | GCTAObservation* obs = dynamic_cast<GCTAObservation*>(m_obs[i]); |
| ... | ... | @@ -507,6 +615,7 @@ void ctbutterfly::init_members(void) |
| 507 | 615 | m_confidence = 0.68; |
| 508 | 616 | m_max_iter = 50; |
| 509 | 617 | m_apply_edisp = false; |
| 618 | + m_gepmode = false; | |
| 510 | 619 | m_fit = false; |
| 511 | 620 | m_chatter = static_cast<GChatter>(2); |
| 512 | 621 | m_ebounds.clear(); |
| ... | ... | @@ -540,6 +649,7 @@ void ctbutterfly::copy_members(const ctbutterfly& app) |
| 540 | 649 | m_confidence = app.m_confidence; |
| 541 | 650 | m_max_iter = app.m_max_iter; |
| 542 | 651 | m_apply_edisp = app.m_apply_edisp; |
| 652 | + m_gepmode = app.m_gepmode; | |
| 543 | 653 | m_fit = app.m_fit; |
| 544 | 654 | m_chatter = app.m_chatter; |
| 545 | 655 | m_ebounds = app.m_ebounds; |
| ... | ... | @@ -590,9 +700,6 @@ void ctbutterfly::get_parameters(void) |
| 590 | 700 | // Get name of test source |
| 591 | 701 | m_srcname = (*this)["srcname"].string(); |
| 592 | 702 | |
| 593 | - // Check model name and type | |
| 594 | - check_model(); | |
| 595 | - | |
| 596 | 703 | // Create energy boundaries from user parameters |
| 597 | 704 | m_ebounds = create_ebounds(); |
| 598 | 705 | |
| ... | ... | @@ -608,10 +715,16 @@ void ctbutterfly::get_parameters(void) |
| 608 | 715 | |
| 609 | 716 | // Get remaining parameters |
| 610 | 717 | m_apply_edisp = (*this)["edisp"].boolean(); |
| 718 | + m_gepmode = (*this)["gepmode"].boolean(); | |
| 611 | 719 | m_confidence = (*this)["confidence"].real(); |
| 612 | 720 | m_fit = (*this)["fit"].boolean(); |
| 613 | 721 | m_chatter = static_cast<GChatter>((*this)["chatter"].integer()); |
| 614 | 722 | |
| 723 | + if (!m_gepmode) { | |
| 724 | + // Check model name and type | |
| 725 | + check_model(); | |
| 726 | + } | |
| 727 | + | |
| 615 | 728 | // Optionally read ahead parameters so that they get correctly |
| 616 | 729 | // dumped into the log file |
| 617 | 730 | if (read_ahead()) { | ... | ... |
src/ctbutterfly/ctbutterfly.hpp
| ... | ... | @@ -92,6 +92,7 @@ protected: |
| 92 | 92 | double m_confidence; //!< Confidence level |
| 93 | 93 | int m_max_iter; //!< Maximum number of iterations |
| 94 | 94 | bool m_apply_edisp; //!< Apply energy dispersion? |
| 95 | + bool m_gepmode; //!< Switch to gaussian error propagation scheme | |
| 95 | 96 | bool m_fit; //!< Do fit? |
| 96 | 97 | GEbounds m_ebounds; //!< Energy binning definition |
| 97 | 98 | GFilename m_outfile; //!< Output ASCII file name | ... | ... |
src/ctbutterfly/ctbutterfly.par
| ... | ... | @@ -27,6 +27,7 @@ caldb, s, a, "prod2",,, "Calibration database" |
| 27 | 27 | irf, s, a, "South_0.5h",,, "Instrument response function" |
| 28 | 28 | edisp, b, h, no,,, "Apply energy dispersion?" |
| 29 | 29 | outfile, f, a, "butterfly.txt",,, "Output ASCII file" |
| 30 | +gepmode, b, h, no,,, "Use Gaussian Error Propagation" | |
| 30 | 31 | |
| 31 | 32 | # |
| 32 | 33 | # Butterfly parameters | ... | ... |