diff --git a/ChangeLog b/ChangeLog index b3a9154..7a2f05e 100644 --- a/ChangeLog +++ b/ChangeLog @@ -3,6 +3,7 @@ * Version 1.2.0 released ======================== + Rename ctskymap::map() to ctskymap::skymap() (#1828) Introduce ctobservation and ctlikelihood base classes (#1828) Remove ctselect::time_reference() method Add ctool and cscript pars() methods (#1838) diff --git a/NEWS b/NEWS index 8fade37..f41420e 100644 --- a/NEWS +++ b/NEWS @@ -30,6 +30,9 @@ observation container. The class implements the following methods: - obs() Returns reference to observation container - first_unbinned_observation() First unbinned CTA observation in container - next_unbinned_observation() Next unbinned CTA observation in container +The following ctools derive from the class: +- ctbin +- ctskymap The ctlikelihood base class that derives from the ctobservation base class was introduced to provide a common base class for all ctools that perform @@ -92,6 +95,9 @@ ctskymap - CTA sky mapping The clear() method now calls GApplication::clear() to conserve the properties of the tool (#1835). +The ctskymap::map() method has been renamed to ctskymap::skymap() to avoid a +name conflict with Python (#1828). + ctmodel - CTA counts cube modelling ----------------------------------- diff --git a/pyext/ctbin.i b/pyext/ctbin.i index 22c3384..e6c564c 100644 --- a/pyext/ctbin.i +++ b/pyext/ctbin.i @@ -34,7 +34,7 @@ * * @brief Event binning tool ***************************************************************************/ -class ctbin : public ctool { +class ctbin : public ctobservation { public: // Constructors and destructors ctbin(void); @@ -48,7 +48,6 @@ public: void run(void); void save(void); void publish(const std::string& name = ""); - const GObservations& obs(void) const; const GCTAEventCube& cube(void) const; }; diff --git a/pyext/ctool.i b/pyext/ctool.i index 5e85e0d..fd1c400 100644 --- a/pyext/ctool.i +++ b/pyext/ctool.i @@ -150,7 +150,7 @@ public: GObservations get_observations(const bool& get_response = true); GSkyDir get_mean_pointing(const GObservations& obs); size_t get_current_rss(void); - std::string get_obs_header(const GObservation* obs); + std::string get_obs_header(const GObservation* obs) const; GEnergies insert_energy_boundaries(const GEnergies& energies, const GCTAObservation& obs); std::vector cube_layer_usage(const GEbounds& cube_ebounds, diff --git a/pyext/ctskymap.i b/pyext/ctskymap.i index 8ad7396..15cc9f5 100644 --- a/pyext/ctskymap.i +++ b/pyext/ctskymap.i @@ -34,7 +34,7 @@ * * @brief Sky mapping tool ***************************************************************************/ -class ctskymap : public ctool { +class ctskymap : public ctobservation { public: // Constructors and destructors ctskymap(void); @@ -48,7 +48,7 @@ public: void run(void); void save(void); void publish(const std::string& name = ""); - const GSkyMap& map(void) const; + const GSkyMap& skymap(void) const; }; diff --git a/src/ctbin/ctbin.cpp b/src/ctbin/ctbin.cpp index c2f5584..a049e1a 100644 --- a/src/ctbin/ctbin.cpp +++ b/src/ctbin/ctbin.cpp @@ -53,9 +53,9 @@ /***********************************************************************//** * @brief Void constructor * - * Constructs an empty ctbin tool. + * Constructs an empty event binning tool. ***************************************************************************/ -ctbin::ctbin(void) : ctool(CTBIN_NAME, CTBIN_VERSION) +ctbin::ctbin(void) : ctobservation(CTBIN_NAME, CTBIN_VERSION) { // Initialise members init_members(); @@ -70,16 +70,14 @@ ctbin::ctbin(void) : ctool(CTBIN_NAME, CTBIN_VERSION) * * param[in] obs Observation container. * - * Constructs ctbin tool from an observation container. + * Constructs event binning tool from an observation container. ***************************************************************************/ -ctbin::ctbin(const GObservations& obs) : ctool(CTBIN_NAME, CTBIN_VERSION) +ctbin::ctbin(const GObservations& obs) : + ctobservation(CTBIN_NAME, CTBIN_VERSION, obs) { // Initialise members init_members(); - // Set observations - m_obs = obs; - // Return return; } @@ -92,11 +90,11 @@ ctbin::ctbin(const GObservations& obs) : ctool(CTBIN_NAME, CTBIN_VERSION) * @param[in] argc Number of arguments in command line. * @param[in] argv Array of command line arguments. * - * Constructs ctbin tool using command line arguments for user parameter - * setting. + * Constructs event binning tool using command line arguments for user + * parameter setting. ***************************************************************************/ ctbin::ctbin(int argc, char *argv[]) : - ctool(CTBIN_NAME, CTBIN_VERSION, argc, argv) + ctobservation(CTBIN_NAME, CTBIN_VERSION, argc, argv) { // Initialise members init_members(); @@ -109,11 +107,11 @@ ctbin::ctbin(int argc, char *argv[]) : /***********************************************************************//** * @brief Copy constructor * - * @param[in] app Application. + * @param[in] app Event binning tool. * - * Constructs ctbin tool from another ctbin instance. + * Constructs event binning tool from another event binning tool. ***************************************************************************/ -ctbin::ctbin(const ctbin& app) : ctool(app) +ctbin::ctbin(const ctbin& app) : ctobservation(app) { // Initialise members init_members(); @@ -129,7 +127,7 @@ ctbin::ctbin(const ctbin& app) : ctool(app) /***********************************************************************//** * @brief Destructor * - * Destructs ctbin tool. + * Destructs event binning tool. ***************************************************************************/ ctbin::~ctbin(void) { @@ -150,10 +148,10 @@ ctbin::~ctbin(void) /***********************************************************************//** * @brief Assignment operator * - * @param[in] app ctbin tool. - * @return ctbin tool. + * @param[in] app Event binning tool. + * @return Event binning tool. * - * Assigns ctbin tool. + * Assigns event binning tool. ***************************************************************************/ ctbin& ctbin::operator=(const ctbin& app) { @@ -161,7 +159,7 @@ ctbin& ctbin::operator=(const ctbin& app) if (this != &app) { // Copy base class members - this->ctool::operator=(app); + this->ctobservation::operator=(app); // Free members free_members(); @@ -186,21 +184,23 @@ ctbin& ctbin::operator=(const ctbin& app) ==========================================================================*/ /***********************************************************************//** - * @brief Clear ctbin tool + * @brief Clear event binning tool * - * Clears ctbin tool. + * Clears event binning tool. ***************************************************************************/ void ctbin::clear(void) { // Free members free_members(); this->ctool::free_members(); + this->ctobservation::free_members(); // Clear base class (needed to conserve tool name and version) this->GApplication::clear(); // Initialise members this->ctool::init_members(); + this->ctobservation::init_members(); init_members(); // Write header into logger @@ -212,7 +212,7 @@ void ctbin::clear(void) /***********************************************************************//** - * @brief Run the ctbin tool + * @brief Run the event binning tool * * Gets the user parameters and loops over all CTA observations in the * observation container to bin the events into a single counts cube. All @@ -235,30 +235,9 @@ void ctbin::run(void) // Write header into logger log_header1(TERSE, gammalib::number("Bin observation", m_obs.size())); - // Loop over all observations in the container - for (int i = 0; i < m_obs.size(); ++i) { - - // Write header for the current observation - log_header3(TERSE, get_obs_header(m_obs[i])); - - // Get CTA observation - GCTAObservation* obs = dynamic_cast(m_obs[i]); - - // Skip observation if it's not CTA - if (obs == NULL) { - std::string msg = " Skipping "+m_obs[i]->instrument()+ - " observation"; - log_string(NORMAL, msg); - continue; - } - - // Skip observation if we have a binned observation - if (obs->eventtype() == "CountsCube") { - std::string msg = " Skipping binned "+obs->instrument()+ - " observation"; - log_string(NORMAL, msg); - continue; - } + // Loop over all unbinned CTA observations in the container + for (GCTAObservation* obs = first_unbinned_observation(); obs != NULL; + obs = next_unbinned_observation()) { // Fill the cube fill_cube(obs); @@ -374,7 +353,6 @@ void ctbin::init_members(void) m_chatter = static_cast(2); // Initialise protected members - m_obs.clear(); m_counts.clear(); m_weights.clear(); m_ebounds.clear(); @@ -402,7 +380,6 @@ void ctbin::copy_members(const ctbin& app) m_chatter = app.m_chatter; // Copy protected members - m_obs = app.m_obs; m_counts = app.m_counts; m_weights = app.m_weights; m_ebounds = app.m_ebounds; diff --git a/src/ctbin/ctbin.hpp b/src/ctbin/ctbin.hpp index 73930d1..5b3cf03 100644 --- a/src/ctbin/ctbin.hpp +++ b/src/ctbin/ctbin.hpp @@ -28,14 +28,11 @@ #define CTBIN_HPP /* __ Includes ___________________________________________________________ */ -#include -#include "GammaLib.hpp" -#include "GCTALib.hpp" -#include "ctool.hpp" +#include "ctobservation.hpp" /* __Definitions _________________________________________________________ */ #define CTBIN_NAME "ctbin" -#define CTBIN_VERSION "1.1.0" +#define CTBIN_VERSION "1.2.0" /***********************************************************************//** @@ -63,7 +60,7 @@ * PSF cubes should be used for response computation. This is however not * yet fully implemented. ***************************************************************************/ -class ctbin : public ctool { +class ctbin : public ctobservation { public: // Constructors and destructors ctbin(void); @@ -80,7 +77,6 @@ public: void run(void); void save(void); void publish(const std::string& name = ""); - const GObservations& obs(void) const; const GCTAEventCube& cube(void) const; protected: @@ -100,7 +96,6 @@ protected: GChatter m_chatter; //!< Chattiness // Protected members - GObservations m_obs; //!< Observation container GSkyMap m_counts; //!< Event cube counts GSkyMap m_weights; //!< Event cube weights GEbounds m_ebounds; //!< Energy boundaries @@ -110,19 +105,6 @@ protected: double m_livetime; //!< Total livetime }; -/***********************************************************************//** - * @brief Return observation container - * - * @return Reference to observation container - * - * Returns a reference to an observation container. - ***************************************************************************/ -inline -const GObservations& ctbin::obs(void) const -{ - return m_obs; -} - /***********************************************************************//** * @brief Return event cube diff --git a/src/ctskymap/ctskymap.cpp b/src/ctskymap/ctskymap.cpp index f705124..dd6e959 100644 --- a/src/ctskymap/ctskymap.cpp +++ b/src/ctskymap/ctskymap.cpp @@ -49,8 +49,10 @@ /***********************************************************************//** * @brief Void constructor + * + * Constructs an empty sky mapping tool. ***************************************************************************/ -ctskymap::ctskymap(void) : ctool(CTSKYMAP_NAME, CTSKYMAP_VERSION) +ctskymap::ctskymap(void) : ctobservation(CTSKYMAP_NAME, CTSKYMAP_VERSION) { // Initialise members init_members(); @@ -65,18 +67,14 @@ ctskymap::ctskymap(void) : ctool(CTSKYMAP_NAME, CTSKYMAP_VERSION) * * param[in] obs Observation container. * - * This method creates an instance of the class by copying an existing - * observations container. + * Constructs sky mapping tool from an observation container. ***************************************************************************/ ctskymap::ctskymap(const GObservations& obs) : - ctool(CTSKYMAP_NAME, CTSKYMAP_VERSION) + ctobservation(CTSKYMAP_NAME, CTSKYMAP_VERSION, obs) { // Initialise members init_members(); - // Set observations - m_obs = obs; - // Return return; } @@ -88,9 +86,12 @@ ctskymap::ctskymap(const GObservations& obs) : * * @param[in] argc Number of arguments in command line. * @param[in] argv Array of command line arguments. + * + * Constructs sky mapping tool using command line arguments for user + * parameter setting. ***************************************************************************/ ctskymap::ctskymap(int argc, char *argv[]) : - ctool(CTSKYMAP_NAME, CTSKYMAP_VERSION, argc, argv) + ctobservation(CTSKYMAP_NAME, CTSKYMAP_VERSION, argc, argv) { // Initialise members init_members(); @@ -103,9 +104,9 @@ ctskymap::ctskymap(int argc, char *argv[]) : /***********************************************************************//** * @brief Copy constructor * - * @param[in] app Application. + * @param[in] app Sky mapping tool. ***************************************************************************/ -ctskymap::ctskymap(const ctskymap& app) : ctool(app) +ctskymap::ctskymap(const ctskymap& app) : ctobservation(app) { // Initialise members init_members(); @@ -140,8 +141,8 @@ ctskymap::~ctskymap(void) /***********************************************************************//** * @brief Assignment operator * - * @param[in] app Application. - * @return Application. + * @param[in] app Sky mapping tool. + * @return Sky mapping tool. ***************************************************************************/ ctskymap& ctskymap::operator=(const ctskymap& app) { @@ -149,7 +150,7 @@ ctskymap& ctskymap::operator=(const ctskymap& app) if (this != &app) { // Copy base class members - this->ctool::operator=(app); + this->ctobservation::operator=(app); // Free members free_members(); @@ -174,21 +175,23 @@ ctskymap& ctskymap::operator=(const ctskymap& app) ==========================================================================*/ /***********************************************************************//** - * @brief Clear ctskymap tool + * @brief Clear sky mapping tool * - * Clears ctskymap tool. + * Clears sky mapping tool. ***************************************************************************/ void ctskymap::clear(void) { // Free members free_members(); this->ctool::free_members(); + this->ctobservation::free_members(); // Clear base class (needed to conserve tool name and version) this->GApplication::clear(); // Initialise members this->ctool::init_members(); + this->ctobservation::init_members(); init_members(); // Write header into logger @@ -200,18 +203,14 @@ void ctskymap::clear(void) /***********************************************************************//** - * @brief Creates sky maps from data + * @brief Run the sky mapping tool * - * This method is the main code. It - * (1) reads task parameters from the par file - * (2) initialises the sky maps - * (3) loops over all observations to add its events to the sky map + * Generates a sky map from event list by looping over all unbinned CTA + * observation in the observation container and filling all events into + * a sky map. ***************************************************************************/ void ctskymap::run(void) { - // Initialise statistics - int num_obs = 0; - // Switch screen logging on in debug mode if (logDebug()) { log.cout(true); @@ -226,37 +225,13 @@ void ctskymap::run(void) // Write header into logger log_header1(TERSE, gammalib::number("Map observation", m_obs.size())); - // Loop over all observation in the container - for (int i = 0; i < m_obs.size(); ++i) { - - // Write header for the current observation - log_header3(TERSE, get_obs_header(m_obs[i])); - - // Get CTA observation - GCTAObservation* obs = dynamic_cast(m_obs[i]); - - // Skip observation if it's not CTA - if (obs == NULL) { - std::string msg = " Skipping "+m_obs[i]->instrument()+ - " observation"; - log_string(NORMAL, msg); - continue; - } - - // Skip observation if we have a binned observation - if (obs->eventtype() == "CountsCube") { - std::string msg = " Skipping binned "+obs->instrument()+ - " observation"; - log_string(NORMAL, msg); - continue; - } + // Loop over all unbinned CTA observations in the container + for (GCTAObservation* obs = first_unbinned_observation(); obs != NULL; + obs = next_unbinned_observation()) { // Map events into sky map map_events(obs); - // Increment observation counter - num_obs++; - } // endfor: looped over observations // Optionally publish sky map @@ -348,7 +323,6 @@ void ctskymap::publish(const std::string& name) void ctskymap::init_members(void) { // Initialise members - m_obs.clear(); m_skymap.clear(); m_emin = 0.0; m_emax = 0.0; @@ -368,7 +342,6 @@ void ctskymap::init_members(void) void ctskymap::copy_members(const ctskymap& app) { // Copy attributes - m_obs = app.m_obs; m_skymap = app.m_skymap; m_emin = app.m_emin; m_emax = app.m_emax; diff --git a/src/ctskymap/ctskymap.hpp b/src/ctskymap/ctskymap.hpp index 1636b80..ecfd07b 100644 --- a/src/ctskymap/ctskymap.hpp +++ b/src/ctskymap/ctskymap.hpp @@ -28,9 +28,7 @@ #define CTSKYMAP_HPP /* __ Includes ___________________________________________________________ */ -#include "GammaLib.hpp" -#include "GCTALib.hpp" -#include "ctool.hpp" +#include "ctobservation.hpp" /* __Definitions _________________________________________________________ */ #define CTSKYMAP_NAME "ctskymap" @@ -44,7 +42,7 @@ * * This class creates a sky map from a CTA event list. ***************************************************************************/ -class ctskymap : public ctool { +class ctskymap : public ctobservation { public: // Constructors and destructors @@ -62,7 +60,7 @@ public: void run(void); void save(void); void publish(const std::string& name = ""); - const GSkyMap& map(void) const; + const GSkyMap& skymap(void) const; protected: // Protected methods @@ -80,7 +78,6 @@ protected: GChatter m_chatter; //!< Chattiness // Protected members - GObservations m_obs; //!< Observation container GSkyMap m_skymap; //!< Sky map }; @@ -91,7 +88,7 @@ protected: * @return Reference to observation container ***************************************************************************/ inline -const GSkyMap& ctskymap::map(void) const +const GSkyMap& ctskymap::skymap(void) const { return m_skymap; } diff --git a/src/support/ctobservation.cpp b/src/support/ctobservation.cpp index e922f45..f4045f6 100644 --- a/src/support/ctobservation.cpp +++ b/src/support/ctobservation.cpp @@ -219,9 +219,12 @@ ctobservation& ctobservation::operator=(const ctobservation& app) ***************************************************************************/ void ctobservation::init_members(void) { - // Initialise members + // Initialise protected members m_obs.clear(); + // Initialise private members + m_index_unbinned = 0; + // Return return; } @@ -234,9 +237,12 @@ void ctobservation::init_members(void) ***************************************************************************/ void ctobservation::copy_members(const ctobservation& app) { - // Copy members + // Copy protected members m_obs = app.m_obs; + // Copy private members + m_index_unbinned = app.m_index_unbinned; + // Return return; } @@ -250,3 +256,88 @@ void ctobservation::free_members(void) // Return return; } + + +/***********************************************************************//** + * @brief Return first unbinned CTA observation (const version) + * + * @return Const pointer to first unbinned CTA observation + * + * Returns a const pointer to the first unbinned CTA observation in the + * container. If no CTA observation exists a NULL pointer is returned. + * + * The method calls next_unbinned_observation(). See the method for details. + ***************************************************************************/ +const GCTAObservation* ctobservation::first_unbinned_observation(void) const +{ + // Initialise index + m_index_unbinned = 0; + + // Get next unbinned CTA observation + const GCTAObservation* obs = next_unbinned_observation(); + + // Return first CTA observation + return obs; +} + + +/***********************************************************************//** + * @brief Return next unbinned CTA observation (const version) + * + * @return Const pointer to next unbinned CTA observation + * + * Returns a const pointer to the next unbinned CTA observation in the + * container. If no CTA observation exists any more a NULL pointer is + * returned. + * + * The method writes for each encountered observation a level 3 header into + * the logger. It will also signal when an observation was skipped because + * it either was not a CTA observation or not an unbinned observation. + * + * @todo Logger methods should be declared const to avoid the const casting. + ***************************************************************************/ +const GCTAObservation* ctobservation::next_unbinned_observation(void) const +{ + // Initialise pointer on CTA observation + const GCTAObservation* obs = NULL; + + // Loop over all remaining observation in the container + for (; m_index_unbinned < m_obs.size(); ++m_index_unbinned) { + + // Write header for the current observation + const_cast(this)->log_header3(TERSE, + get_obs_header(m_obs[m_index_unbinned])); + + // Case the observation to a CTA observation. This will return a + // NULL pointer if the observation is not a CTA observation. + obs = dynamic_cast(m_obs[m_index_unbinned]); + + // Skip observation if it's not CTA + if (obs == NULL) { + std::string msg = " Skipping "+ + m_obs[m_index_unbinned]->instrument()+ + " observation"; + const_cast(this)->log_string(NORMAL, msg); + continue; + } + + // Skip observation if we have a binned observation + if (obs->eventtype() == "CountsCube") { + obs = NULL; + std::string msg = " Skipping binned "+ + m_obs[m_index_unbinned]->instrument()+ + " observation"; + const_cast(this)->log_string(NORMAL, msg); + continue; + } + + // If we come to this point we have an unbinned CTA observation and + // we can forward the index to the next index and break the loop + m_index_unbinned++; + break; + + } // endfor: looped over all observation + + // Return next CTA observation + return obs; +} diff --git a/src/support/ctobservation.hpp b/src/support/ctobservation.hpp index a63a4f5..0768352 100644 --- a/src/support/ctobservation.hpp +++ b/src/support/ctobservation.hpp @@ -71,8 +71,18 @@ protected: void copy_members(const ctobservation& app); void free_members(void); + // Iterator methods and members + GCTAObservation* first_unbinned_observation(void); + GCTAObservation* next_unbinned_observation(void); + const GCTAObservation* first_unbinned_observation(void) const; + const GCTAObservation* next_unbinned_observation(void) const; + // Protected members - GObservations m_obs; //!< Observation container + GObservations m_obs; //!< Observation container + +private: + // Private members + mutable int m_index_unbinned; //!< Current index of unbinned observation }; @@ -89,4 +99,44 @@ const GObservations& ctobservation::obs(void) const return m_obs; } + +/***********************************************************************//** + * @brief Return first unbinned CTA observation + * + * @return Pointer to first unbinned CTA observation + * + * Returns a pointer to the first unbinned CTA observation in the container. + * If no CTA observation exists a NULL pointer is returned. + * + * The method calls next_unbinned_observation(). See the method for details. + ***************************************************************************/ +inline +GCTAObservation* ctobservation::first_unbinned_observation(void) +{ + return (const_cast + (static_cast + (*this).first_unbinned_observation())); +} + + +/***********************************************************************//** + * @brief Return next unbinned CTA observation + * + * @return Pointer to next unbinned CTA observation + * + * Returns a pointer to the next unbinned CTA observation in the container. + * If no CTA observation exists any more a NULL pointer is returned. + * + * The method writes for each encountered observation a level 3 header into + * the logger. It will also signal when an observation was skipped because + * it either was not a CTA observation or not an unbinned observation. + ***************************************************************************/ +inline +GCTAObservation* ctobservation::next_unbinned_observation(void) +{ + return (const_cast + (static_cast + (*this).next_unbinned_observation())); +} + #endif /* CTOBSERVATION_HPP */ diff --git a/src/support/ctool.cpp b/src/support/ctool.cpp index c37f159..b332de2 100644 --- a/src/support/ctool.cpp +++ b/src/support/ctool.cpp @@ -1559,7 +1559,7 @@ size_t ctool::get_current_rss(void) * XXX observation "name" (id=YYYYY) * ***************************************************************************/ -std::string ctool::get_obs_header(const GObservation* obs) +std::string ctool::get_obs_header(const GObservation* obs) const { // Initialise header string std::string header = obs->instrument() + " observation"; diff --git a/src/support/ctool.hpp b/src/support/ctool.hpp index f6ead66..b42345f 100644 --- a/src/support/ctool.hpp +++ b/src/support/ctool.hpp @@ -113,7 +113,7 @@ protected: GObservations get_observations(const bool& get_response = true); GSkyDir get_mean_pointing(const GObservations& obs); size_t get_current_rss(void); - std::string get_obs_header(const GObservation* obs); + std::string get_obs_header(const GObservation* obs) const; GEnergies insert_energy_boundaries(const GEnergies& energies, const GCTAObservation& obs); std::vector cube_layer_usage(const GEbounds& cube_ebounds, diff --git a/test/test_ctskymap.py b/test/test_ctskymap.py index a00c532..25fd9e4 100755 --- a/test/test_ctskymap.py +++ b/test/test_ctskymap.py @@ -108,7 +108,7 @@ class Test(test): skymap = ctools.ctskymap() # Check that empty ctskymap tool holds a map that has no pixels - self._check_map(skymap.map(), nx=0, ny=0) + self._check_map(skymap.skymap(), nx=0, ny=0) # Check that saving does not nothing skymap['outmap'] = 'ctskymap_py0.fits' @@ -148,7 +148,7 @@ class Test(test): cpy_skymap = skymap.copy() # Check sky map of ctskymap copy - self._check_map(cpy_skymap.map()) + self._check_map(cpy_skymap.skymap()) # Execute copy of ctskymap tool again, now with a higher chatter # level than before @@ -169,7 +169,7 @@ class Test(test): cpy_skymap.clear() # Check that cleared ctskymap tool holds a map that has no pixels - self._check_map(cpy_skymap.map(), nx=0, ny=0) + self._check_map(cpy_skymap.skymap(), nx=0, ny=0) # Get mixed observation container obs = self._obs_mixed()