コード例 #1
0
ファイル: ctobssim.cpp プロジェクト: lyang54/ctools
/***********************************************************************//**
 * @brief Simulate source events from photon list
 *
 * @param[in] obs Pointer on CTA observation.
 * @param[in] models Model list.
 * @param[in] ran Random number generator.
 * @param[in] wrklog Pointer to logger.
 *
 * Simulate source events from a photon list for a given CTA observation.
 * The events are stored in as event list in the observation.
 *
 * This method does nothing if the observation pointer is NULL. It also
 * verifies if the observation has a valid pointing and response.
 ***************************************************************************/
void ctobssim::simulate_source(GCTAObservation* obs, const GModels& models,
                               GRan& ran, GLog* wrklog)
{
    // Continue only if observation pointer is valid
    if (obs != NULL) {

        // If no logger is specified then use the default logger
        if (wrklog == NULL) {
            wrklog = &log;
        }

        // Get CTA response
        const GCTAResponseIrf* rsp =
            dynamic_cast<const GCTAResponseIrf*>(obs->response());
        if (rsp == NULL) {
            std::string msg = "Response is not an IRF response.\n" +
                              obs->response()->print();
            throw GException::invalid_value(G_SIMULATE_SOURCE, msg);
        }

        // Get pointer on event list (circumvent const correctness)
        GCTAEventList* events =
            static_cast<GCTAEventList*>(const_cast<GEvents*>(obs->events()));

        // Extract simulation region.
        GSkyDir dir = events->roi().centre().dir();
        double  rad = events->roi().radius() + g_roi_margin;

        // Dump simulation cone information
        if (logNormal()) {
            *wrklog << gammalib::parformat("Simulation area");
            *wrklog << m_area << " cm2" << std::endl;
            *wrklog << gammalib::parformat("Simulation cone");
            *wrklog << "RA=" << dir.ra_deg() << " deg";
            *wrklog << ", Dec=" << dir.dec_deg() << " deg";
            *wrklog << ", r=" << rad << " deg" << std::endl;
        }

        // Initialise indentation for logging
        int indent = 0;

        // Loop over all Good Time Intervals
        for (int it = 0; it < events->gti().size(); ++it) {

            // Extract time interval
            GTime tmin = events->gti().tstart(it);
            GTime tmax = events->gti().tstop(it);

            // Dump time interval
            if (logNormal()) {
                if (events->gti().size() > 1) {
                    indent++;
                    wrklog->indent(indent);
                }
                *wrklog << gammalib::parformat("Time interval", indent);
                *wrklog << tmin.convert(m_cta_ref);
                *wrklog << " - ";
                *wrklog << tmax.convert(m_cta_ref);
                *wrklog << " s" << std::endl;
            }

            // Loop over all energy boundaries
            for (int ie = 0; ie <  events->ebounds().size(); ++ie) {

                // Extract energy boundaries
                GEnergy emin = events->ebounds().emin(ie);
                GEnergy emax = events->ebounds().emax(ie);

                // Set true photon energy limits for simulation. If observation
                // has energy dispersion then add margin
                GEnergy e_true_min = emin;
                GEnergy e_true_max = emax;
                if (rsp->use_edisp()) {
                    e_true_min = rsp->ebounds(e_true_min).emin();
                    e_true_max = rsp->ebounds(e_true_max).emax();
                }

                // Dump energy range
                if (logNormal()) {
                    if (events->ebounds().size() > 1) {
                        indent++;
                        wrklog->indent(indent);
                    }
                    *wrklog << gammalib::parformat("Photon energy range", indent);
                    *wrklog << e_true_min << " - " << e_true_max << std::endl;
                    *wrklog << gammalib::parformat("Event energy range", indent);
                    *wrklog << emin << " - " << emax << std::endl;
                }

                // Loop over all sky models
                for (int i = 0; i < models.size(); ++i) {

                    // Get sky model (NULL if not a sky model)
                    const GModelSky* model =
                          dynamic_cast<const GModelSky*>(models[i]);

                    // If we have a sky model that applies to the present
                    // observation then simulate events
                    if (model != NULL &&
                        model->is_valid(obs->instrument(), obs->id())) {

                        // Determine duration of a time slice by limiting the
                        // number of simulated photons to m_max_photons.
                        // The photon rate is estimated from the model flux
                        // and used to set the duration of the time slice.
                        double flux     = get_model_flux(model, emin, emax,
                                                         dir, rad);
                        double rate     = flux * m_area;
                        double duration = 1800.0;  // default: 1800 sec
                        if (rate > 0.0) {
                            duration = m_max_photons / rate;
                            if (duration < 1.0) {  // not <1 sec
                                duration = 1.0;
                            }
                            else if (duration > 180000.0) { // not >50 hr
                                duration = 180000.0;
                            }
                        }
                        GTime tslice(duration, "sec");

                        // If photon rate exceeds the maximum photon rate
                        // then throw an exception
                        if (rate > m_max_rate) {
                            std::string modnam = (model->name().length() > 0) ?
                                                 model->name() : "Unknown";
                            std::string msg    = "Photon rate "+
                                                 gammalib::str(rate)+
                                                 " photons/sec for model \""+
                                                 modnam+"\" exceeds maximum"
                                                 " allowed photon rate of "+
                                                 gammalib::str(m_max_rate)+
                                                 " photons/sec. Please check"
                                                 " the model parameters for"
                                                 " model \""+modnam+"\" or"
                                                 " increase the value of the"
                                                 " hidden \"maxrate\""
                                                 " parameter.";
                            throw GException::invalid_value(G_SIMULATE_SOURCE, msg);
                        }

                        // Dump length of time slice and rate
                        if (logExplicit()) {
                            *wrklog << gammalib::parformat("Photon rate", indent);
                            *wrklog << rate << " photons/sec";
                            if (model->name().length() > 0) {
                                *wrklog << " [" << model->name() << "]";
                            }
                            *wrklog << std::endl;
                        }

                        // To reduce memory requirements we split long time
                        // intervals into several slices.
                        GTime tstart = tmin;
                        GTime tstop  = tstart + tslice;

                        // Initialise cumulative photon counters
                        int nphotons = 0;

                        // Loop over time slices
                        while (tstart < tmax) {

                            // Make sure that tstop <= tmax
                            if (tstop > tmax) {
                                tstop = tmax;
                            }

                            // Dump time slice
                            if (logExplicit()) {
                                if (tmax - tmin > tslice) {
                                    indent++;
                                    wrklog->indent(indent);
                                }
                                *wrklog << gammalib::parformat("Time slice", indent);
                                *wrklog << tstart.convert(m_cta_ref);
                                *wrklog << " - ";
                                *wrklog << tstop.convert(m_cta_ref);
                                *wrklog << " s";
                                if (model->name().length() > 0) {
                                    *wrklog << " [" << model->name() << "]";
                                }
                                *wrklog << std::endl;
                            }

                            // Get photons
                            GPhotons photons = model->mc(m_area, dir, rad,
                                                         e_true_min, e_true_max,
                                                         tstart, tstop, ran);

                            // Dump number of simulated photons
                            if (logExplicit()) {
                                *wrklog << gammalib::parformat("MC source photons/slice", indent);
                                *wrklog << photons.size();
                                if (model->name().length() > 0) {
                                    *wrklog << " [" << model->name() << "]";
                                }
                                *wrklog << std::endl;
                            }

                            // Simulate events from photons
                            for (int i = 0; i < photons.size(); ++i) {

                                // Increment photon counter
                                nphotons++;

                                // Simulate event. Note that this method
                                // includes the deadtime correction.
                                GCTAEventAtom* event = rsp->mc(m_area,
                                                               photons[i],
                                                               *obs,
                                                               ran);

                                if (event != NULL) {

                                    // Use event only if it falls within ROI
                                    // energy boundary and time slice
                                    if (events->roi().contains(*event) &&
                                        event->energy() >= emin &&
                                        event->energy() <= emax &&
                                        event->time() >= tstart &&
                                        event->time() <= tstop) {
                                        event->event_id(m_event_id);
                                        events->append(*event);
                                        m_event_id++;
                                    }
                                    delete event;
                                }

                            } // endfor: looped over events

                            // Go to next time slice
                            tstart = tstop;
                            tstop  = tstart + tslice;

                            // Reset indentation
                            if (logExplicit()) {
                                if (tmax - tmin > tslice) {
                                    indent--;
                                    wrklog->indent(indent);
                                }
                            }

                        } // endwhile: looped over time slices

                        // Dump simulation results
                        if (logNormal()) {
                            *wrklog << gammalib::parformat("MC source photons", indent);
                            *wrklog << nphotons;
                            if (model->name().length() > 0) {
                                *wrklog << " [" << model->name() << "]";
                            }
                            *wrklog << std::endl;
                            *wrklog << gammalib::parformat("MC source events", indent);
                            *wrklog << events->size();
                            if (model->name().length() > 0) {
                                *wrklog << " [" << model->name() << "]";
                            }
                            *wrklog << std::endl;

                        }

                    } // endif: model was a sky model

                } // endfor: looped over models

                // Dump simulation results
                if (logNormal()) {
                    *wrklog << gammalib::parformat("MC source events", indent);
                    *wrklog << events->size();
                    *wrklog << " (all source models)";
                    *wrklog << std::endl;
                }

                // Reset indentation
                if (logNormal()) {
                    if (events->ebounds().size() > 1) {
                        indent--;
                        wrklog->indent(indent);

                    }
                }

            } // endfor: looped over all energy boundaries

            // Reset indentation
            if (logNormal()) {
                if (events->gti().size() > 1) {
                    indent--;
                    wrklog->indent(indent);
                }
            }

        } // endfor: looped over all time intervals

        // Reset indentation
        wrklog->indent(0);

    } // endif: observation pointer was valid

    // Return
    return;
}
コード例 #2
0
ファイル: cterror.cpp プロジェクト: jdevin/ctools
/***********************************************************************//**
 * @brief Performs error computation by using a bisection method
 *
 * @param[in] min Minimum parameter value
 * @param[in] max Maximum parameter value
 *
 * This method calculates the error using a bisection method.
 ***************************************************************************/
double cterror::error_bisection(const double& min, const double& max)
{
    // Copy values to working values
    double wrk_min = min;
    double wrk_max = max;

    // Initialise iteration counter
    int iter = 1;

    // Initialize mid value
    double mid = (wrk_min + wrk_max) / 2.0;

    // Loop until breaking condition is reached
    while (true) {

        // Throw exception if maximum iterations are reached
        if (iter > m_max_iter) {
            if (wrk_min - m_model_par->factor_min() < m_tol) {
                std::string msg = "The \""+m_model_par->name()+"\" parameter "
                                  "minimum has been reached during error "
                                  "calculation. To obtain accurate errors, "
                                  "consider setting the minimum parameter "
                                  "value to a lower value, and re-run "
                                  "cterror.";
                if (logTerse()) {
                    log << msg;
                }
                break;
            }
            else if (m_model_par->factor_max() - wrk_max < m_tol) {
                std::string msg = "The \""+m_model_par->name()+"\" parameter "
                                  "maximum has been reached during error "
                                  "calculation. To obtain accurate errors, "
                                  "consider setting the maximum parameter "
                                  "value to a higher value, and re-run "
                                  "cterror.";
                if (logTerse()) {
                    log << msg;
                }
                break;
            }
            else {
                std::string msg = "The maximum number of "+
                                  gammalib::str(m_max_iter)+" iterations has "
                                  "been reached. Please increase the "
                                  "\"max_iter\" parameter, and re-run "
                                  "cterror.";
                throw GException::invalid_value(G_ERR_BISECTION, msg);
            }
        }

        // Compute center of boundary
        mid = (wrk_min + wrk_max) / 2.0;

        // Calculate function value
        double eval_mid = evaluate(mid);

        // Log interval
        if (logExplicit()) {
            log << gammalib::parformat("  Iteration "+gammalib::str(iter));
            log << "[";
            log << wrk_min;
            log << ", ";
            log << wrk_max;
            log << "] ";
            log << eval_mid;
            log << std::endl;
        }

        // Check for convergence inside tolerance
        if (std::abs(eval_mid) < m_tol) {
            break;
        }

        // Check if interval is smaller than 1.0e-6
        if (std::abs(wrk_max-wrk_min) < 1.0e-6) {
            break;
        }

        // If we are on the crescent side of the parabola ...
        if (mid > m_value) {

            // Change boundaries for further iteration
            if (eval_mid > 0.0) {
                wrk_max = mid;
            }
            else if (eval_mid < 0.0) {
                wrk_min = mid;
            }
        }

        // ... otherwise we are on the decrescent side of the parabola
        else {

            // Change boundaries for further iteration
            if (eval_mid > 0.0) {
                wrk_min = mid;
            }
            else if (eval_mid < 0.0) {
                wrk_max = mid;
            }
        }

        // Increment counter
        iter++;

    } // endwhile

    // Return mid value
    return mid;

}
コード例 #3
0
ファイル: ctobssim.cpp プロジェクト: hsiejkowski/ctools
/***********************************************************************//**
 * @brief Simulate source events from photon list
 *
 * @param[in] obs Pointer on CTA observation.
 * @param[in] models Model list.
 * @param[in] ran Random number generator.
 * @param[in] wrklog Pointer to logger.
 *
 * Simulate source events from a photon list for a given CTA observation.
 * The events are stored in as event list in the observation.
 *
 * This method does nothing if the observation pointer is NULL. It also
 * verifies if the observation has a valid pointing and response.
 ***************************************************************************/
void ctobssim::simulate_source(GCTAObservation* obs, const GModels& models,
                               GRan& ran, GLog* wrklog)
{
    // Continue only if observation pointer is valid
    if (obs != NULL) {

        // If no logger is specified then use the default logger
        if (wrklog == NULL) {
            wrklog = &log;
        }

        // Get pointer on CTA response. Throw an exception if the response
        // is not defined.
        const GCTAResponse& rsp = obs->response();

        // Make sure that the observation holds a CTA event list. If this
        // is not the case then allocate and attach a CTA event list now.
        if (dynamic_cast<const GCTAEventList*>(obs->events()) == NULL) {
            set_list(obs);
        }

        // Get pointer on event list (circumvent const correctness)
        GCTAEventList* events = static_cast<GCTAEventList*>(const_cast<GEvents*>(obs->events()));

        // Extract simulation region.
        GSkyDir dir = events->roi().centre().dir();
        double  rad = events->roi().radius() + g_roi_margin;

        // Dump simulation cone information
        if (logNormal()) {
            *wrklog << gammalib::parformat("Simulation area");
            *wrklog << m_area << " cm2" << std::endl;
            *wrklog << gammalib::parformat("Simulation cone");
            *wrklog << "RA=" << dir.ra_deg() << " deg";
            *wrklog << ", Dec=" << dir.dec_deg() << " deg";
            *wrklog << ", r=" << rad << " deg" << std::endl;
        }

        // Initialise indentation for logging
        int indent = 0;

        // Loop over all Good Time Intervals
        for (int it = 0; it < events->gti().size(); ++it) {

            // Extract time interval
            GTime tmin = events->gti().tstart(it);
            GTime tmax = events->gti().tstop(it);

            // Dump time interval
            if (logNormal()) {
                if (events->gti().size() > 1) {
                    indent++;
                    wrklog->indent(indent);
                }
                *wrklog << gammalib::parformat("Time interval", indent);
                *wrklog << tmin.convert(m_cta_ref);
                *wrklog << " - ";
                *wrklog << tmax.convert(m_cta_ref);
                *wrklog << " s" << std::endl;
            }

            // Loop over all energy boundaries
            for (int ie = 0; ie <  events->ebounds().size(); ++ie) {

                // Extract energy boundaries
                GEnergy emin = events->ebounds().emin(ie);
                GEnergy emax = events->ebounds().emax(ie);

                // Dump energy range
                if (logNormal()) {
                    if (events->ebounds().size() > 1) {
                        indent++;
                        wrklog->indent(indent);
                    }
                    *wrklog << gammalib::parformat("Energy range", indent);
                    *wrklog << emin << " - " << emax << std::endl;
                }

                // Loop over all sky models
                for (int i = 0; i < models.size(); ++i) {

                    // Get sky model (NULL if not a sky model)
                    const GModelSky* model =
                          dynamic_cast<const GModelSky*>(models[i]);

                    // If we have a sky model that applies to the present
                    // observation then simulate events
                    if (model != NULL &&
                        model->is_valid(obs->instrument(), obs->id())) {

                        // Determine duration of a time slice by limiting the
                        // number of simulated photons to m_max_photons.
                        // The photon rate is estimated from the model flux
                        // and used to set the duration of the time slice.
                        double flux     = model->spectral()->flux(emin, emax);
                        double rate     = flux * m_area;
                        double duration = 1800.0;  // default: 1800 sec
                        if (rate > 0.0) {
                            duration = m_max_photons / rate;
                            if (duration < 1.0) {  // not <1 sec
                                duration = 1.0;
                            }
                            else if (duration > 180000.0) { // not >50 hr
                                duration = 180000.0;
                            }
                        }
                        GTime tslice(duration, "sec");

                        // To reduce memory requirements we split long time
                        // intervals into several slices.
                        GTime tstart = tmin;
                        GTime tstop  = tstart + tslice;

                        // Initialise cumulative photon counters
                        int nphotons = 0;

                        // Loop over time slices
                        while (tstart < tmax) {

                            // Make sure that tstop <= tmax
                            if (tstop > tmax) {
                                tstop = tmax;
                            }

                            // Dump time slice
                            if (logExplicit()) {
                                if (tmax - tmin > tslice) {
                                    indent++;
                                    wrklog->indent(indent);
                                }
                                *wrklog << gammalib::parformat("Time slice", indent);
                                *wrklog << tstart.convert(m_cta_ref);
                                *wrklog << " - ";
                                *wrklog << tstop.convert(m_cta_ref);
                                *wrklog << " s" << std::endl;
                            }

                            // Get photons
                            GPhotons photons = model->mc(m_area, dir, rad,
                                                         emin, emax,
                                                         tstart, tstop, ran);

                            // Dump number of simulated photons
                            if (logExplicit()) {
                                *wrklog << gammalib::parformat("MC source photons/slice", indent);
                                *wrklog << photons.size();
                                if (model->name().length() > 0) {
                                    *wrklog << " [" << model->name() << "]";
                                }
                                *wrklog << std::endl;
                            }

                            // Simulate events from photons
                            for (int i = 0; i < photons.size(); ++i) {

                                // Increment photon counter
                                nphotons++;

                                // Simulate event. Note that this method
                                // includes the deadtime correction.
                                GCTAEventAtom* event = rsp.mc(m_area,
                                                              photons[i],
                                                              *obs,
                                                              ran);
                                if (event != NULL) {

                                    // Use event only if it falls within ROI
                                    if (events->roi().contains(*event)) {
                                        event->event_id(m_event_id);
                                        events->append(*event);
                                        m_event_id++;
                                    }
                                    delete event;
                                }

                            } // endfor: looped over events

                            // Go to next time slice
                            tstart = tstop;
                            tstop  = tstart + tslice;

                            // Reset indentation
                            if (logExplicit()) {
                                if (tmax - tmin > tslice) {
                                    indent--;
                                    wrklog->indent(indent);
                                }
                            }

                        } // endwhile: looped over time slices

                        // Dump simulation results
                        if (logNormal()) {
                            *wrklog << gammalib::parformat("MC source photons", indent);
                            *wrklog << nphotons;
                            if (model->name().length() > 0) {
                                *wrklog << " [" << model->name() << "]";
                            }
                            *wrklog << std::endl;
                            *wrklog << gammalib::parformat("MC source events", indent);
                            *wrklog << events->size();
                            if (model->name().length() > 0) {
                                *wrklog << " [" << model->name() << "]";
                            }
                            *wrklog << std::endl;

                        }

                    } // endif: model was a sky model

                } // endfor: looped over models

                // Dump simulation results
                if (logNormal()) {
                    *wrklog << gammalib::parformat("MC source events", indent);
                    *wrklog << events->size();
                    *wrklog << " (all source models)";
                    *wrklog << std::endl;
                }

                // Reset indentation
                if (logNormal()) {
                    if (events->ebounds().size() > 1) {
                        indent--;
                        wrklog->indent(indent);

                    }
                }

            } // endfor: looped over all energy boundaries

            // Reset indentation
            if (logNormal()) {
                if (events->gti().size() > 1) {
                    indent--;
                    wrklog->indent(indent);
                }
            }

        } // endfor: looped over all time intervals

        // Reset indentation
        wrklog->indent(0);

    } // endif: observation pointer was valid

    // Return
    return;
}
コード例 #4
0
ファイル: ctbin.cpp プロジェクト: lyang54/ctools
/***********************************************************************//**
 * @brief Fill events into counts cube
 *
 * @param[in] obs CTA observation.
 *
 * @exception GException::invalid_value
 *            No event list found in observation.
 *
 * Fills the events from an event list in the counts cube setup by init_cube.
 ***************************************************************************/
void ctbin::fill_cube(GCTAObservation* obs)
{
    // Continue only if observation pointer is valid
    if (obs != NULL) {

        // Make sure that the observation holds a CTA event list. If this
        // is not the case then throw an exception.
        const GCTAEventList* events = dynamic_cast<const GCTAEventList*>(obs->events());
        if (events == NULL) {
            std::string msg = "CTA Observation does not contain an event "
                              "list. Event list information is needed to "
                              "fill the counts map.";
            throw GException::invalid_value(G_FILL_CUBE, msg);
        }

        // Get the RoI
        const GCTARoi& roi = events->roi();

        // Initialise binning statistics
        int num_outside_roi  = 0;
        int num_outside_map  = 0;
        int num_outside_ebds = 0;
        int num_in_map       = 0;

        // Fill sky map
        for (int i = 0; i < events->size(); ++i) {

            // Get event
            const GCTAEventAtom* event = (*events)[i];

            // Determine sky pixel
            GCTAInstDir* inst  = (GCTAInstDir*)&(event->dir());
            GSkyDir      dir   = inst->dir();
            GSkyPixel    pixel = m_cube.dir2pix(dir);

            // Skip if pixel is outside RoI
            if (roi.centre().dir().dist_deg(dir) > roi.radius()) {
                num_outside_roi++;
                continue;
            }

            // Skip if pixel is out of range
            if (pixel.x() < -0.5 || pixel.x() > (m_cube.nx()-0.5) ||
                    pixel.y() < -0.5 || pixel.y() > (m_cube.ny()-0.5)) {
                num_outside_map++;
                continue;
            }

            // Determine energy bin. Skip if we are outside the energy range
            int index = m_ebounds.index(event->energy());
            if (index == -1) {
                num_outside_ebds++;
                continue;
            }

            // Fill event in skymap
            m_cube(pixel, index) += 1.0;
            num_in_map++;

        } // endfor: looped over all events

        // Append GTIs
        m_gti.extend(events->gti());

        // Update ontime and livetime
        m_ontime   += obs->ontime();
        m_livetime += obs->livetime();

        // Log filling results
        if (logTerse()) {
            log << gammalib::parformat("Events in list");
            log << obs->events()->size() << std::endl;
            log << gammalib::parformat("Events in cube");
            log << num_in_map << std::endl;
            log << gammalib::parformat("Event bins outside RoI");
            log << num_outside_roi << std::endl;
            log << gammalib::parformat("Events outside cube area");
            log << num_outside_map << std::endl;
            log << gammalib::parformat("Events outside energy bins");
            log << num_outside_ebds << std::endl;
        }

        // Log cube
        if (logExplicit()) {
            log.header1("Counts cube");
            log << m_cube << std::endl;
        }

    } // endif: observation was valid

    // Return
    return;
}
コード例 #5
0
ファイル: ctmodel.cpp プロジェクト: jdevin/ctools
/***********************************************************************//**
 * @brief Fill model into model cube
 *
 * @param[in] obs CTA observation.
 *
 * Adds the expected number of events for a given observation to the events
 * that are already found in the model cube. The method also updates the
 * GTI of the model cube so that cube GTI is a list of the GTIs of all
 * observations that were used to generate the model cube.
 ***************************************************************************/
void ctmodel::fill_cube(const GCTAObservation* obs)
{
    // Continue only if observation pointer is valid
    if (obs != NULL) {

        // Get GTI and energy boundaries references for observation
        const GGti&     gti         = obs->events()->gti();
        const GEbounds& obs_ebounds = obs->ebounds();

        // Get cube energy boundaries
        const GEbounds& cube_ebounds = m_cube.ebounds();

        // Initialise empty, invalid RoI
        GCTARoi roi;

        // Retrieve RoI in case we have an unbinned observation
        if (obs->eventtype() == "EventList") {
            roi = obs->roi();
        }

        // Initialise statistics
        double sum              = 0.0;
        int    num_outside_ebds = 0;
        int    num_outside_roi  = 0;

        // Setup cube GTIs for this observation
        m_cube.gti(obs->events()->gti());

        // Loop over all cube bins
        for (int i = 0; i < m_cube.size(); ++i) {

            // Get cube bin
            GCTAEventBin* bin = m_cube[i];

            // Skip bin if it is outside the energy range of the observation
            int index = cube_ebounds.index(bin->energy());
            if (index == -1 ||
                !obs_ebounds.contains(cube_ebounds.emin(index)+g_energy_margin,
                                      cube_ebounds.emax(index)-g_energy_margin)) {
                num_outside_ebds++;
                continue;
            }

            // Check if RoI is valid, i.e. check if we have an unbinned
            // observation
            if (roi.is_valid()) {

                // Skip bin if it is outside the RoI of the observation
                if (!roi.contains(*bin)) {
                    num_outside_roi++;
                    continue;
                }

            } // endif: RoI was not valid

            // Get actual bin value
            double value = bin->counts();
            
            // Compute model value for cube bin
            double model = m_obs.models().eval(*bin, *obs) * bin->size();

            // Add model to actual value
            value += model;
            sum   += model;

            // Store value
            bin->counts(value);

        } // endfor: looped over all cube bins

        // Append GTIs of observation to list of GTIs
        m_gti.extend(gti);

        // Update GTIs
        m_cube.gti(m_gti);

        // Log results
        if (logTerse()) {
            log << gammalib::parformat("Model events in cube");
            log << sum << std::endl;
            log << gammalib::parformat("Bins outside energy range");
            log << num_outside_ebds << std::endl;
            log << gammalib::parformat("Bins outside RoI");
            log << num_outside_roi << std::endl;
        }

        // Log cube
        if (logExplicit()) {
            log.header2("Model cube");
            log << m_cube << std::endl;
        }

    } // endif: observation was valid

    // Return
    return;
}
コード例 #6
0
ファイル: ctselect.cpp プロジェクト: adonath/ctools
/***********************************************************************//**
 * @brief Select events
 *
 * @param[in] obs CTA observation.
 * @param[in] filename File name.
 *
 * Select events from a FITS file by making use of the selection possibility
 * of the cfitsio library on loading a file. A selection string is created
 * from the specified criteria that is appended to the filename so that
 * cfitsio will automatically filter the event data. This selection string
 * is then applied when opening the FITS file. The opened FITS file is then
 * saved into a temporary file which is the loaded into the actual CTA
 * observation, overwriting the old CTA observation. The ROI, GTI and EBounds
 * of the CTA event list are then set accordingly to the specified selection.
 * Finally, the temporary file created during this process is removed.
 *
 * Good Time Intervals of the observation will be limited to the time
 * interval [m_tmin, m_tmax]. If m_tmin=m_tmax=0, no time selection is
 * performed.
 *
 * @todo Use INDEF instead of 0.0 for pointing as RA/DEC selection
 ***************************************************************************/
void ctselect::select_events(GCTAObservation* obs, const std::string& filename)
{
    // Allocate selection string
    std::string selection;
    char        cmin[80];
    char        cmax[80];
    char        cra[80];
    char        cdec[80];
    char        crad[80];

    // Set requested selections
    bool select_time = (m_tmin != 0.0 || m_tmax != 0.0);

    // Set RA/DEC selection
    double ra  = m_ra;
    double dec = m_dec;
    if (m_usepnt) {
        const GCTAPointing *pnt = obs->pointing();
        ra = pnt->dir().ra_deg();
        dec = pnt->dir().dec_deg();
    }

    // Set time selection interval. We make sure here that the time selection
    // interval cannot be wider than the GTIs covering the data. This is done
    // using GGti's reduce() method.
    if (select_time) {

        // Reduce GTIs to specified time interval. The complicated cast is
        // necessary here because the gti() method is declared const, so
        // we're not officially allowed to modify the GTIs.
        ((GGti*)(&obs->events()->gti()))->reduce(m_timemin, m_timemax);

    } // endif: time selection was required

    // Save GTI for later usage
    GGti gti = obs->events()->gti();

    // Make time selection
    if (select_time) {
    
        // Extract effective time interval in CTA reference time. We need
        // this reference for filtering.
        double tmin = gti.tstart().convert(m_cta_ref);
        double tmax = gti.tstop().convert(m_cta_ref);

        // Format time with sufficient accuracy and add to selection string
        sprintf(cmin, "%.8f", tmin);
        sprintf(cmax, "%.8f", tmax);
        selection = "TIME >= "+std::string(cmin)+" && TIME <= "+std::string(cmax);
        if (logTerse()) {
            log << parformat("Time range");
            log << tmin << " - " << tmax << " s" << std::endl;
        }
        if (selection.length() > 0) {
            selection += " && ";
        }
    }

    // Make energy selection
    sprintf(cmin, "%.8f", m_emin);
    sprintf(cmax, "%.8f", m_emax);
    selection += "ENERGY >= "+std::string(cmin)+" && ENERGY <= "+std::string(cmax);
    if (logTerse()) {
        log << parformat("Energy range");
        log << m_emin << " - " << m_emax << " TeV" << std::endl;
    }
    if (selection.length() > 0) {
        selection += " && ";
    }

    // Make ROI selection
    sprintf(cra,  "%.6f", ra);
    sprintf(cdec, "%.6f", dec);
    sprintf(crad, "%.6f", m_rad);
    selection += "ANGSEP("+std::string(cra)+"," +
                 std::string(cdec)+",RA,DEC) <= " +
                 std::string(crad);
    if (logTerse()) {
        log << parformat("Acceptance cone centre");
        log << "RA=" << ra << ", DEC=" << dec << " deg" << std::endl;
        log << parformat("Acceptance cone radius");
        log << m_rad << " deg" << std::endl;
    }
    if (logTerse()) {
        log << parformat("cfitsio selection");
        log << selection << std::endl;
    }

    // Add additional expression
    if (strip_whitespace(m_expr).length() > 0) {
        if (selection.length() > 0) {
            selection += " && ";
        }
        selection += "("+strip_whitespace(m_expr)+")";
    }

    // Build input filename including selection expression
    std::string expression = filename;
    if (selection.length() > 0)
        expression += "[EVENTS]["+selection+"]";
    if (logTerse()) {
        log << parformat("FITS filename");
        log << expression << std::endl;
    }

    // Open FITS file
    GFits file(expression);

    // Log selected FITS file
    if (logExplicit()) {
        log << std::endl;
        log.header1("FITS file content after selection");
        log << file << std::endl;
    }

    // Check if we have an EVENTS HDU
    if (!file.hashdu("EVENTS")) {
        std::string message = "No \"EVENTS\" extension found in FITS file "+
                              expression+".";
        throw GException::app_error(G_SELECT_EVENTS, message);
    }

    // Determine number of events in EVENTS HDU
    int nevents = file.table("EVENTS")->nrows();

    // If the selected event list is empty then append an empty event list
    // to the observation. Otherwise load the data from the temporary file.
    if (nevents < 1) {

        // Create empty event list
        GCTAEventList eventlist;

        // Append list to observation
        obs->events(&eventlist);

    }
    else {

        // Get temporary file name
        std::string tmpname = std::tmpnam(NULL);

        // Save FITS file to temporary file
        file.saveto(tmpname, true);

        // Load observation from temporary file
        obs->load_unbinned(tmpname);

        // Remove temporary file
        std::remove(tmpname.c_str());

    }

    // Get CTA event list pointer
    GCTAEventList* list =
        static_cast<GCTAEventList*>(const_cast<GEvents*>(obs->events()));

    // Set ROI
    GCTARoi     roi;
    GCTAInstDir instdir;
    instdir.radec_deg(ra, dec);
    roi.centre(instdir);
    roi.radius(m_rad);
    list->roi(roi);

    // Set GTI
    list->gti(gti);

    // Set energy boundaries
    GEbounds ebounds;
    GEnergy  emin;
    GEnergy  emax;
    emin.TeV(m_emin);
    emax.TeV(m_emax);
    ebounds.append(emin, emax);
    list->ebounds(ebounds);

    // Recompute ontime and livetime.
    GTime meantime = 0.5 * (gti.tstart() + gti.tstop());
    obs->ontime(gti.ontime());
    obs->livetime(gti.ontime() * obs->deadc(meantime));

    // Return
    return;
}
コード例 #7
0
ファイル: ctselect.cpp プロジェクト: adonath/ctools
/***********************************************************************//**
 * @brief Select event data
 *
 * This method reads in the application parameters and loops over all
 * observations that were found to perform an event selection. Event
 * selection is done by writing each observation to a temporary file and
 * re-opening the temporary file using the cfitsio event filter syntax.
 * The temporary file is deleted after this action so that no disk overflow
 * will occur. 
 ***************************************************************************/
void ctselect::run(void)
{
    // Switch screen logging on in debug mode
    if (logDebug()) {
        log.cout(true);
    }

    // Get parameters
    get_parameters();

    // Write parameters into logger
    if (logTerse()) {
        log_parameters();
        log << std::endl;
    }

    // Write observation(s) into logger
    if (logTerse()) {
        log << std::endl;
        log.header1("Observations before selection");
        log << m_obs << std::endl;
    }

    // Write header
    if (logTerse()) {
        log << std::endl;
        log.header1("Event selection");
    }

    // Initialise counters
    int n_observations = 0;

    // Loop over all observation in the container
    for (int i = 0; i < m_obs.size(); ++i) {

        // Initialise event input and output filenames
        m_infiles.push_back("");

        // Get CTA observation
        GCTAObservation* obs = dynamic_cast<GCTAObservation*>(&m_obs[i]);

        // Continue only if observation is a CTA observation
        if (obs != NULL) {

            // Write header for observation
            if (logTerse()) {
                if (obs->name().length() > 1) {
                    log.header3("Observation "+obs->name());
                }
                else {
                    log.header3("Observation");
                }
            }

            // Increment counter
            n_observations++;

            // Save event file name (for possible saving)
            m_infiles[i] = obs->eventfile();

            // Get temporary file name
            std::string filename = std::tmpnam(NULL);

            // Save observation in temporary file
            obs->save(filename, true);

            // Log saved FITS file
            if (logExplicit()) {
                GFits tmpfile(filename);
                log << std::endl;
                log.header1("FITS file content of temporary file");
                log << tmpfile << std::endl;
                tmpfile.close();
            }

            // Check temporary file
            std::string message = check_infile(filename);
            if (message.length() > 0) {
                throw GException::app_error(G_RUN, message);
            }

            // Load observation from temporary file, including event selection
            select_events(obs, filename);

            // Remove temporary file
            std::remove(filename.c_str());
            
        } // endif: had a CTA observation

    } // endfor: looped over all observations

    // If more than a single observation has been handled then make sure that
    // an XML file will be used for storage
    if (n_observations > 1) {
        m_use_xml = true;
    }

    // Write observation(s) into logger
    if (logTerse()) {
        log << std::endl;
        log.header1("Observations after selection");
        log << m_obs << std::endl;
    }

    // Return
    return;
}