Alternaria
fit cylinders and ellipsoids to fungus
|
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 /* -------------------------------------------------------------------------- */