Alternaria
fit cylinders and ellipsoids to fungus
imaging_model.cpp
Go to the documentation of this file.
00001 /*
00002  * This work is licensed under a Creative Commons 
00003  * Attribution-Noncommercial-Share Alike 3.0 United States License.
00004  * 
00005  *    http://creativecommons.org/licenses/by-nc-sa/3.0/us/
00006  * 
00007  * You are free:
00008  * 
00009  *    to Share - to copy, distribute, display, and perform the work
00010  *    to Remix - to make derivative works
00011  * 
00012  * Under the following conditions:
00013  * 
00014  *    Attribution. You must attribute the work in the manner specified by the
00015  *    author or licensor (but not in any way that suggests that they endorse you
00016  *    or your use of the work).
00017  * 
00018  *    Noncommercial. You may not use this work for commercial purposes.
00019  * 
00020  *    Share Alike. If you alter, transform, or build upon this work, you may
00021  *    distribute the resulting work only under the same or similar license to
00022  *    this one.
00023  * 
00024  * For any reuse or distribution, you must make clear to others the license
00025  * terms of this work. The best way to do this is by including this header.
00026  * 
00027  * Any of the above conditions can be waived if you get permission from the
00028  * copyright holder.
00029  * 
00030  * Apart from the remix rights granted under this license, nothing in this
00031  * license impairs or restricts the author's moral rights.
00032  */
00033 
00034 
00047 #include <config.h>
00048 
00049 #include <cassert>
00050 #include <cmath>
00051 #include <iostream>
00052 #include <fstream>
00053 #include <sstream>
00054 
00055 #include <inttypes.h>
00056 
00057 #include <jwsc/base/limits.h>
00058 #include <jwsc/prob/pdf.h>
00059 
00060 #include <jwsc++/base/exception.h>
00061 
00062 #include "density.h"
00063 #include "printable.h"
00064 #include "imaging_model.h"
00065 
00066 
00067 #define  WINDOW_COL         0
00068 #define  WINDOW_ROW         0
00069 #define  WINDOW_IMG         0
00070 #define  WINDOW_NUM_COLS    1
00071 #define  WINDOW_NUM_ROWS    1
00072 #define  WINDOW_NUM_IMGS    1
00073 
00074 #define  SCALE_X            1.0f
00075 #define  SCALE_Y            1.0f
00076 #define  SCALE_Z            2.0f
00077 
00078 #define  BG_MU              0.8f
00079 #define  BG_SIGMA           0.1f
00080 #define  BG_MIN             0
00081 #define  BG_MAX             1.0f
00082 
00083 #define  C_2_MIN            2.0e-4f
00084 #define  C_2_MAX            2.0e-4f
00085 
00086 
00087 using std::isinf;
00088 using std::isnan;
00089 using std::log;
00090 using std::ostream;
00091 using std::istream;
00092 using std::ofstream;
00093 using std::ifstream;
00094 using std::ostringstream;
00095 using std::istringstream;
00096 using namespace jwsc;
00097 using jwscxx::base::IO_error;
00098 using jwscxx::base::Arg_error;
00099 
00100 
00101 /* --------------------------  Imaging_window  ------------------------------ */
00102 
00108 Imaging_window::Imaging_window() throw (Arg_error)
00109 {
00110     set(WINDOW_COL, WINDOW_ROW, WINDOW_IMG, WINDOW_NUM_COLS, WINDOW_NUM_ROWS,
00111             WINDOW_NUM_IMGS);
00112 }
00113 
00114 
00125 void Imaging_window::set
00126 (
00127     uint32_t col, 
00128     uint32_t row, 
00129     uint32_t img, 
00130     uint32_t num_cols,
00131     uint32_t num_rows,
00132     uint32_t num_imgs
00133 )
00134 throw (Arg_error)
00135 {
00136     if (num_cols == 0 || num_rows == 0 || num_imgs == 0)
00137     {
00138         throw Arg_error("Window size is zero");
00139     }
00140 
00141     this->col      = col;
00142     this->row      = row;
00143     this->img      = img;
00144     this->num_cols = num_cols;
00145     this->num_rows = num_rows;
00146     this->num_imgs = num_imgs;
00147 }
00148 
00149 
00154 ostream& operator<<(ostream& out, const Imaging_window& window)
00155 {
00156     return out << window.col << ' ' << window.row << ' ' << window.img << ' '
00157                << window.num_cols << ' ' << window.num_rows << ' '
00158                << window.num_imgs;
00159 }
00160 
00161 
00166 istream& operator>>(istream& in, Imaging_window& window)
00167 {
00168     in >> window.col;
00169     in >> window.row;
00170     in >> window.img;
00171     in >> window.num_cols;
00172     in >> window.num_rows;
00173     in >> window.num_imgs;
00174     return in;
00175 }
00176 
00177 /* -------------------------------------------------------------------------- */
00178 
00179 
00180 
00181 
00182 
00183 
00184 
00185 
00186 
00187 /* --------------------------  Imaging_scale  ------------------------------- */
00188 
00194 Imaging_scale::Imaging_scale() throw (Arg_error)
00195 {
00196     set(SCALE_X, SCALE_Y, SCALE_Z);
00197 }
00198 
00199 
00207 void Imaging_scale::set(float x, float y, float z) throw (Arg_error)
00208 {
00209     if (x <= 0 || y <= 0 || z <= 0)
00210     {
00211         throw Arg_error("Imaging scale <= 0");
00212     }
00213 
00214     this->x = x;
00215     this->y = y;
00216     this->z = z;
00217 }
00218 
00219 
00224 ostream& operator<<
00225 (
00226      ostream&             out, 
00227      const Imaging_scale& scale
00228 )
00229 {
00230     return out << scale.x << ' ' << scale.y << ' ' << scale.z;
00231 }
00232 
00233 
00238 istream& operator>>
00239 (
00240      istream&       in, 
00241      Imaging_scale& scale
00242 )
00243 {
00244     in >> scale.x;
00245     in >> scale.y;
00246     in >> scale.z;
00247     return in;
00248 }
00249 
00250 /* -------------------------------------------------------------------------- */
00251 
00252 
00253 
00254 
00255 
00256 
00257 
00258 
00259 
00260 /* --------------------  Imaging_model_density  ----------------------------- */
00261 
00267 Imaging_model_density::Imaging_model_density() throw (Arg_error)
00268 {
00269     float mu, sigma;
00270     float min, max;
00271 
00272     mu    = BG_MU;
00273     sigma = BG_SIGMA;
00274     min   = BG_MIN;
00275     max   = BG_MAX;
00276     set_bg(mu, sigma, min, max);
00277 
00278     min   = C_2_MIN;
00279     max   = C_2_MAX;
00280     set_c_2(min, max);
00281 }
00282 
00283 
00285 Imaging_model_density* Imaging_model_density::clone() const
00286 {
00287     float mu, sigma;
00288     float min, max;
00289 
00290     Imaging_model_density* d = new Imaging_model_density();
00291 
00292     mu    = bg.get_mu();
00293     sigma = bg.get_sigma();
00294     min   = bg.get_min();
00295     max   = bg.get_max();
00296     d->set_bg(mu, sigma, min, max);
00297 
00298     min   = c_2.get_min();
00299     max   = c_2.get_max();
00300     d->set_c_2(min, max);
00301 
00302     return d;
00303 }
00304 
00305 
00315 void Imaging_model_density::set_bg(float mu, float sigma, float min, float max) 
00316     throw (Arg_error)
00317 {
00318     if (min < 0)
00319     {
00320         throw Arg_error("Minimum must be >= 0");
00321     }
00322     if (max > 1)
00323     {
00324         throw Arg_error("Maximum must be <= 1");
00325     }
00326     bg.set(mu, sigma, min, max);
00327 }
00328 
00329 
00336 void Imaging_model_density::set_c_2(float min, float max) throw (Arg_error)
00337 {
00338     if (min < 0)
00339     {
00340         throw Arg_error("Minimum must be >= 0");
00341     }
00342     c_2.set(min, max);
00343 }
00344 
00345 
00347 float Imaging_model_density::sample_bg() const
00348 {
00349     return (float)sample_gaussian_pdf_d(bg.get_mu(), bg.get_sigma(), 
00350             bg.get_min(), bg.get_max());
00351 }
00352 
00353 
00355 float Imaging_model_density::sample_c_2() const
00356 {
00357     return (float)sample_uniform_pdf_d(c_2.get_min(), c_2.get_max());
00358 }
00359 
00360 
00367 Imaging_model* Imaging_model_density::sample
00368 (
00369     const Imaging_window* window,
00370     const Imaging_scale*  scale
00371 )
00372 const
00373 {
00374     return new Imaging_model(sample_bg(), sample_c_2(), window, scale, this);
00375 }
00376 
00377 /* -------------------------------------------------------------------------- */
00378 
00379 
00380 
00381 
00382 
00383 
00384 
00385 
00386 
00387 /* ----------------------------  Imaging_model  ----------------------------- */
00388 
00399 Imaging_model::Imaging_model
00400 (
00401     float                        bg,
00402     float                        c_2,
00403     const Imaging_window*        window,
00404     const Imaging_scale*         scale,
00405     const Imaging_model_density* density
00406 )
00407 throw (Arg_error)
00408 {
00409     this->bg      = bg;
00410     this->c_2     = c_2;
00411     this->window  = window;
00412     this->scale   = scale;
00413     this->density = density;
00414 
00415     check_bg();
00416     check_c_2();
00417 
00418     update_log_prob();
00419 }
00420 
00421 
00423 Imaging_model::Imaging_model(const Imaging_model& model)
00424 {
00425     bg       = model.bg;
00426     c_2      = model.c_2;
00427     window   = model.window;
00428     scale    = model.scale;
00429     density  = model.density;
00430     log_prob = model.log_prob;
00431 }
00432 
00433 
00445 Imaging_model::Imaging_model
00446 (
00447     const char*                  fname, 
00448     const Imaging_window*        window,
00449     const Imaging_scale*         scale,
00450     const Imaging_model_density* density
00451 )
00452 throw (IO_error, Arg_error)
00453 {
00454     ostringstream ost;
00455     istringstream ist;
00456     ifstream      in;
00457 
00458     this->window  = window;
00459     this->scale   = scale;
00460     this->density = density;
00461 
00462     in.open(fname);
00463     if (in.fail())
00464     {
00465         ost << fname << ": Could not open file";
00466         throw IO_error(ost.str());
00467     }
00468 
00469     const char* member_value;
00470 
00471     if (!(member_value = get_member_value("Bg", in)))
00472     {
00473         ost << fname << ": Missing background";
00474         throw Arg_error(ost.str());
00475     }
00476     ist.str(member_value);
00477     ist >> bg;
00478     if (ist.fail())
00479     {
00480         ost << fname << ": Invalid background";
00481         throw Arg_error(ost.str());
00482     }
00483     ist.clear(std::ios_base::goodbit);
00484 
00485     if (!(member_value = get_member_value("C_2", in)))
00486     {
00487         ost << fname << ": Missing C_2";
00488         throw Arg_error(ost.str());
00489     }
00490     ist.str(member_value);
00491     ist >> c_2;
00492     if (ist.fail())
00493     {
00494         ost << fname << ": Invalid C_2";
00495         throw Arg_error(ost.str());
00496     }
00497     ist.clear(std::ios_base::goodbit);
00498 
00499     if (!(member_value = get_member_value("Log Prob", in)))
00500     {
00501         ost << fname << ": Missing log probability";
00502         throw Arg_error(ost.str());
00503     }
00504     ist.str(member_value);
00505     ist >> log_prob;
00506     if (ist.fail())
00507     {
00508         ost << fname << ": Invalid log probability";
00509         throw Arg_error(ost.str());
00510     }
00511     ist.clear(std::ios_base::goodbit);
00512 
00513     in.close();
00514     if (in.fail())
00515     {
00516         ost << fname << ": Could not close file";
00517         throw IO_error(ost.str());
00518     }
00519 
00520     check_bg();
00521     check_c_2();
00522 
00523     update_log_prob();
00524 }
00525 
00526 
00528 Imaging_model* Imaging_model::clone()
00529 {
00530     return new Imaging_model(*this);
00531 }
00532 
00533 
00541 void Imaging_model::set_bg(float bg) throw (Arg_error)
00542 {
00543     float old_bg = this->bg;
00544 
00545     try
00546     {
00547         this->bg = bg;
00548         check_bg();
00549 
00550         update_log_prob();
00551     }
00552     catch (Arg_error e)
00553     {
00554         set_bg(old_bg);
00555         throw e;
00556     }
00557 }
00558 
00559 
00567 void Imaging_model::set_c_2(float c_2) throw (Arg_error)
00568 {
00569     float old_c_2 = this->c_2;
00570 
00571     try
00572     {
00573         this->c_2 = c_2;
00574         check_c_2();
00575 
00576         update_log_prob();
00577     }
00578     catch (Arg_error e)
00579     {
00580         set_c_2(old_c_2);
00581         throw e;
00582     }
00583 }
00584 
00585 
00601 void Imaging_model::print(const char* fname) const throw (IO_error)
00602 {
00603     ofstream out;
00604 
00605     out.open(fname);
00606     if (out.fail())
00607     {
00608         ostringstream ost;
00609         ost << fname << ": Could not open file";
00610         throw IO_error(ost.str());
00611     }
00612 
00613     print(out);
00614 
00615     out.close();
00616     if (out.fail())
00617     {
00618         ostringstream ost;
00619         ost << fname << ": Could not close file";
00620         throw IO_error(ost.str());
00621     }
00622 }
00623 
00624 
00636 void Imaging_model::print(std::ostream& out) const
00637 {
00638     out << "       Bg: " << bg << '\n'
00639         << "      C_2: " << c_2 << '\n'
00640         << " Log Prob: " << log_prob << '\n';
00641 }
00642 
00643 
00645 void Imaging_model::update_log_prob()
00646 {
00647     float  mu, sigma;
00648     float  min, max;
00649     double delta;
00650     double p_1, p_2;
00651 
00652     log_prob = 0;
00653 
00654     mu        = density->get_bg().get_mu();
00655     sigma     = density->get_bg().get_sigma();
00656     min       = density->get_bg().get_min();
00657     max       = density->get_bg().get_max();
00658     delta     = (max - min) / 1000.0;
00659     p_1       = integrate_gaussian_pdf_d(mu, sigma, bg, bg+delta); 
00660     p_2       = integrate_gaussian_pdf_d(mu, sigma, min, max);
00661     log_prob += log((p_1 < JWSC_MIN_LOG_ARG) ? JWSC_MIN_LOG_ARG : p_1);
00662     log_prob -= log((p_2 < JWSC_MIN_LOG_ARG) ? JWSC_MIN_LOG_ARG : p_2);
00663 
00664 #if defined ALTERNARIA_HAVE_ISINF && defined ALTERNARIA_HAVE_ISNAN
00665     assert(!isinf(log_prob) && !isnan(log_prob));
00666 #endif
00667 }
00668 
00669 
00674 void Imaging_model::check_bg() const throw (Arg_error)
00675 {
00676     if (density->get_bg().get_min() > bg || 
00677         density->get_bg().get_max() < bg)
00678     {
00679         ostringstream ost;
00680         ost << "Background " << bg << " outside density range ["
00681             << density->get_bg().get_min() << ','
00682             << density->get_bg().get_max() << ']';
00683         throw Arg_error(ost.str());
00684     }
00685 }
00686 
00687 
00692 void Imaging_model::check_c_2() const throw (Arg_error)
00693 {
00694     if (density->get_c_2().get_min() > c_2 || 
00695         density->get_c_2().get_max() < c_2)
00696     {
00697         ostringstream ost;
00698         ost << "C_2 " << c_2 << " outside density range ["
00699             << density->get_c_2().get_min() << ','
00700             << density->get_c_2().get_max() << ']';
00701         throw Arg_error(ost.str());
00702     }
00703 }
00704 
00705 /* -------------------------------------------------------------------------- */