/* * Summary: Given an array and a specific range [0, size) where the "size"_th * iteration is not inclusive, return the iteration of the first * instance of the specified key, or -1 if it does not exist. * Parameters: u32 array to search, u32 size of the array, and the u32 element * to locate. * Return: Iteration of the first location of the key, -1 if it doesn't * exist. */ u32 linearSearch(u32 a[], u32 size, u32 key) { if (NULL == a) // null array pointer? { logNormal("linearSearch: NULL array pointer!\n"); API_ASSERT_NONNULL(a); // blinkcode! } if (size <= 0) // invalid size? { logNormal("linearSearch: Invalid size %d\n", size); API_ASSERT_GREATER(size, 0); // blinkcode! } if (key < 0) // invalid key? { logNormal("linearSearch: Invalid size %d\n", size); API_ASSERT_GREATER_EQUAL(size, 0); // blinkcode! } for (u32 i = 0; i < size; ++i) if (a[i] == key) // If there is a match return i; // say so return INVALID; // Otherwise, return the signal that there is no match }
/* * Summary: Handles (r)esult packet reflex. Packet information is logged and * result is logged for the specific calculation. * Parameters: (r)esult packet. * Return: None. */ void r_handler(u8 * packet) { R_PKT PKT_R; if (packetScanf(packet, "%Zr%z\n", R_ZScanner, &PKT_R) != 3) { logNormal("r_handler: Failed at %d\n", packetCursor(packet)); return; // No harm done so no blinkcoding necessary } u32 NODE_INDEX; // index holder for if log is valid // only log properly formatted packets if (INVALID == (NODE_INDEX = log(PKT_R.key.ID, PKT_R.key.TIME))) return; // Don't continue if this packet has been received before // Handle packet spammers else if (PC_NODE_ARR[NODE_INDEX] > (PKT_R.key.TIME / 1000)) { // Decrease the amount of pings recorded; "spammer amnesty" of sorts. PC_NODE_ARR[NODE_INDEX] -= 2; return; // Don't continue if this IXM is spamming packets right now. } else if (PKT_R.calc_ver < HOST_CALC_VER) return; // Don't continue if this is an old calculation version else if (0xffffffff == PKT_R.calc_ver) logNormal("Calculation version overflow.\n"); if (PKT_R.neighbor) { // If this a neighboring node PKT_R.neighbor = 0; // Reset the flag before forwarding NEIGHBORS_ARR[packetSource(packet)] = PKT_R.key.ID; // And remember the ID } // If all the hoops have been jumped through FWD_R_PKT(&PKT_R, packetSource(packet)); // Forward the packet if (PKT_R.calc_ver == HOST_CALC_VER) // Same result? // Update the results from packets with proper calculation versions voteCount(NODE_INDEX, PKT_R.rslt); else if (PKT_R.calc_ver > HOST_CALC_VER) // New calculation version? { // perform standard procedures strikeCheck(); // evaluate the strikes for my neighbors flush(); // clear out my records for the new voting session voteCount(NODE_INDEX, PKT_R.rslt); // Remember the node's vote HOST_CALC = PKT_R.calc; // Remember the new calculation HOST_CALC_VER = PKT_R.calc_ver; // Remember the new calculation version voteCount(0, calculate(HOST_CALC)); // calculation occurs here } return; }
/* * Summary: Adjusts the vote count based on a recent vote. * Parameters: u32 index of the node that voted, u32 ballot of the node. * Return: None. */ void voteCount(u32 NODE_INDEX, u32 BALLOT) { if (NODE_INDEX < 0) { logNormal("voteCount: Invalid node index %d", NODE_INDEX); API_ASSERT_GREATER_EQUAL(NODE_INDEX, 0); // blinkcode! } if (BALLOT < 0) { logNormal("voteCount: Invalid ballot %d", BALLOT); API_ASSERT_GREATER_EQUAL(BALLOT, 0); // blinkcode! } if (0 == BALLOT) // 0 is never a correct answer return; // But it's not worth blinkcoding over else if (BALLOT == VOTE_NODE_ARR[NODE_INDEX]) return; // Ignore duplicate votes // Invalid vote if I've already voted (didn't flush from a new calculation) else if (0 != VOTE_NODE_ARR[NODE_INDEX]) return; else if (0 == VOTE_NODE_ARR[NODE_INDEX]) // Haven't voted yet ++VOTE_COUNT; // This is the first vote received if (VOTE_COUNT > NODE_COUNT) // Someone voted multiple times { flush(); // Clean out memory voteCount(0, calculate(HOST_CALC)); // Recount our own vote return; } // look to see if the ballot is for an existing candidate u32 k = linearSearch(CANDIDATE_ARR, CANDIDATE_COUNT + 1, BALLOT); if (INVALID != k) // if so, give him a vote ++CANDIDATE_VOTES_ARR[k]; else // otherwise the ballot is new to the candidate list { // so add it k = CANDIDATE_COUNT++; // Give him a vote CANDIDATE_ARR[k] = BALLOT; // Add the new candidate to the nominations list ++CANDIDATE_VOTES_ARR[k]; // Give the candidate a vote } VOTE_NODE_ARR[NODE_INDEX] = BALLOT; // record the node's ballot evalMajority(); //Reevaluate the majority with every different ballot return; }
/* * Summary: Logs the ID and time-stamp keys of a received packet. * Parameters: u32 ID, u32 time-stamp (from a (r)esult packet) * Return: Return index of the node if successful, otherwise INVALID. */ u32 log(u32 ID, u32 TIME) { if (TIME < 0) { logNormal("log: No time-traveling or overflow allowed!\n"); API_ASSERT_GREATER_EQUAL(TIME, 0); // blinkcode! } for (u32 i = 0; i < NODE_COUNT; ++i) { // Look for an existing match in the list of previous PING'ers if (ID == ID_NODE_ARR[i]) { if (TIME != TS_NODE_ARR[i]) { // If there is a match and it is a new packet if (PC_NODE_ARR[i] < 0xffff) // Make sure ping count won't overflow ++PC_NODE_ARR[i]; // So we can keep track of the valid packet else // Notify us if the ping count will overflow logNormal("Limit of pings reached for IXM %t\n", ID); TS_NODE_ARR[i] = TIME; // Update nodular time-stamp TS_HOST_ARR[i] = millis(); // Update host-based time-stamp return i; // Return the location of the existing node } else // Don't forward the packet if it isn't new return INVALID; } } // Otherwise check to see if there is any free space left in the array if (NODE_COUNT >= (sizeof(ID_NODE_ARR) / sizeof(u32))) { logNormal("Inadequate memory space in ID table.\n" "Rebooting.\n"); reenterBootloader(); // Clear out memory for new boards } // Add the new IXM board to the phone-book. ID_NODE_ARR[NODE_COUNT] = ID; TS_NODE_ARR[NODE_COUNT] = TIME; TS_HOST_ARR[NODE_COUNT] = millis(); ++PC_NODE_ARR[NODE_COUNT]; return NODE_COUNT++; // And pass it on }
/* * Summary: Custom (r)esult packet scanner. * Parameters: The arguments are automatically handled within a parent * header file. * Return: Boolean confirming the packet was read correctly. */ bool R_ZScanner(u8 * packet, void * arg, bool alt, int width) { /* (r)esult packet structure */ u32 ID; // hex ID (board key) u32 TIME; // integer timestamp (packet key) u32 CALC; // integer calculation u32 CALC_VER; // integer calculation version u32 VOTE; // integer vote u32 NEIGHBOR; // neighbor flag if (packetScanf(packet, "%t,%d,%d,%d,%d,%d", &ID, &TIME, &CALC, &CALC_VER, &VOTE, &NEIGHBOR) != 11) { logNormal("Inconsistent packet format for (r)esult packet.\n"); return false; } if (arg) { R_PKT * PKT_R = (R_PKT*) arg; PKT_R->key.ID = ID; PKT_R->key.TIME = TIME; PKT_R->calc = CALC; PKT_R->calc_ver = CALC_VER; PKT_R->rslt = VOTE; PKT_R->neighbor = NEIGHBOR; } return true; }
/* * Summary: Handles (c)alculation packet reflex. Packet information is saved * and converted into a R packet to be forwarded to neighboring nodes. * Parameters: (c)alculation packet. * Return: None. */ void c_handler(u8 * packet) { C_PKT PKT_R; if (packetScanf(packet, "%Zc%z\n", C_ZScanner, &PKT_R) != 3) { logNormal("c_handler: Failed at %d\n", packetCursor(packet)); return; } if (PKT_R.calc < 0) { logNormal("c_handler: Input %d must be a non-negative integer.\n", PKT_R.calc); return; } if (PKT_R.calc > PRIME_THRESHOLD) { logNormal("c_handler: Value %d is higher than the threshold %d (%d).\n", PKT_R.calc, PRIME_THRESHOLD, PRIME_ARR_THRESHOLD - 1); return; } strikeCheck(); // evaluate the strikes for my neighbors flush(); // clear out my records for the new voting session R_PKT PKT_T; // synthesize a new packet ++HOST_CALC_VER; HOST_CALC = PKT_R.calc; PKT_T.key.ID = ID_HOST; PKT_T.key.TIME = millis(); PKT_T.calc = HOST_CALC; PKT_T.calc_ver = HOST_CALC_VER; PKT_T.rslt = VOTE_NODE_ARR[0]; // If all the hoops have been jumped through FWD_R_PKT(&PKT_T, packetSource(packet)); // Forward the packet voteCount(0, calculate(HOST_CALC)); // calculation occurs here return; }
/* * Summary: Given an array and a specific range [first, size) where the * "size"_th iteration is not inclusive, return the index of the * greatest positive value in the array or INVALID if there is a * tie. * Parameters: u32 array to search, u32 size of the array. * Return: Index of the highest value greater than or equal to 0; * INVALID otherwise. */ u32 getMaxIndex(u32 a[], u32 size) { if (NULL == a) // null array pointer? { logNormal("getMaxIndex: NULL array pointer!\n"); API_ASSERT_NONNULL(a); // blinkcode! } if (size <= 0) // invalid size? { logNormal("getMaxIndex: Invalid size %d\n", size); API_ASSERT_GREATER(size, 0); // blinkcode! } bool tiedetected = false; // flag to mark if there is a tie u32 maxVotes = 0; // highest amount of ballots currently u32 maxIndex = INVALID; // index of the highest candidate for (u32 i = 0; i < size; ++i) { // iterate through the entire array if (a[i] > maxVotes) { // record higher values maxVotes = a[i]; maxIndex = i; tiedetected = false; // disarm tie flag } // if there is ever candidate that ties with the highest candidate else if (a[i] == maxVotes) tiedetected = true; // set tie flag } if (tiedetected) // if the tie flag was set return TIE; // there is no winning candidate // It worked, there's a candidate greater than 0 votes and no ties else if ((0 != maxVotes) && (INVALID != maxIndex)) return maxIndex; else return INVALID; // This should never happen. }
/* * Summary: Displays a table containing each IXM's ID, timestamp(ms), and * pings. Note that there might exist a time-stamp inconsistency * (boards may base their time based on when they started receiving * power). * Parameters: Time when function was called (handled automagically). * Return: None. */ void printTable(u32 when) { if (when < 0) { logNormal("log: No time-traveling or overflow allowed!\n"); API_ASSERT_GREATER_EQUAL(when, 0); // blinkcode! } u32 HOST_TIME = when; facePrintf( TERMINAL_FACE, "\n\n\n\n\n\n\n\n\n\n\n\n\n+===============================================================+\n"); facePrintf(TERMINAL_FACE, "|CALCULATION: %4d HOST TIME: %010d |\n", HOST_CALC, HOST_TIME); facePrintf(TERMINAL_FACE, "+---------------------------------------------------------------+\n"); facePrintf(TERMINAL_FACE, "|ID ACTIVE TIME-STAMP VOTE STRIKES PINGS|\n"); facePrintf(TERMINAL_FACE, "+---- ------ ---------- ------ ------- -----+\n"); for (u32 i = 0; i < NODE_COUNT; ++i) { facePrintf(TERMINAL_FACE, "|%04t %c%15d%11d%12d%10d|\n", ID_NODE_ARR[i], ACTIVE_NODE_ARR[i], TS_HOST_ARR[i], VOTE_NODE_ARR[i], STRIKES_NODE_ARR[i], PC_NODE_ARR[i]); } facePrintf(TERMINAL_FACE, "+---------------------------------------------------------------+\n"); if ((TIE == MAJORITY_RSLT) || (INVALID == MAJORITY_RSLT) || (0 == MAJORITY_RSLT)) facePrintf(TERMINAL_FACE, "|MAJORITY: -- |\n"); else facePrintf(TERMINAL_FACE, "|MAJORITY: %4d |\n", MAJORITY_RSLT); facePrintf(TERMINAL_FACE, "+===============================================================+\n"); // schedule the next table printout Alarms.set(Alarms.currentAlarmNumber(), when + printTable_PERIOD); return; }
/* * Summary: Custom (c)alculation packet scanner. * Parameters: The arguments are automatically handled within a parent * header file. * Return: Boolean confirming the packet was read correctly. */ bool C_ZScanner(u8 * packet, void * arg, bool alt, int width) { /* (c)alculation packet structure */ u32 CALC; // integer calculation if (packetScanf(packet, "%d", &CALC) != 1) { logNormal("Inconsistent packet format for (c)alculation packet.\n"); return false; } if (arg) { C_PKT * PKT_R = (C_PKT*) arg; PKT_R->calc = CALC; } return true; }
/***********************************************************************//** * @brief Generate the exposure cube(s). * * This method reads the task parameters from the parfile, sets up the * observation container, loops over all CTA observations in the container * and generates an exposure cube from the CTA observations. ***************************************************************************/ void ctexpcube::run(void) { // If we're in debug mode then all output is also dumped on the screen if (logDebug()) { log.cout(true); } // Get task parameters get_parameters(); // Warn if there are not enough energy bins log_string(TERSE, warn_too_few_energies(m_expcube.energies())); // Write input observation container into logger log_observations(NORMAL, m_obs, "Input observation"); // Initialise exposure cube init_cube(); // Write header into logger log_header1(TERSE, "Generate exposure cube"); // Set pointer to logger dependent on chattiness GLog* logger = (logNormal()) ? &log : NULL; // Fill exposure cube m_expcube.fill(m_obs, logger); // Write exposure cube into logger log_string(EXPLICIT, m_expcube.print(m_chatter)); // Optionally publish exposure cube if (m_publish) { publish(); } // Return return; }
/* * Summary: Turns on a specific LED color depending on the status input. * Parameters: u32 LED status denoting which LED to turn on. * OFF = off, MINORITY = red, MAJORITY = green, PROCESSING = blue * Return: None. */ void setStatus(u32 STATUS) { if ((STATUS != OFF) && // if input is not "no LED" (STATUS != MINORITY) && // or "red LED" (STATUS != MAJORITY) && // or "green LED" (STATUS != PROCESSING)) // or "blue LED" { logNormal("setStatus: Invalid input %d\n", STATUS); // blinkcode! API_ASSERT((OFF == STATUS) || (MINORITY == STATUS) || (MAJORITY == STATUS) || (PROCESSING == STATUS), E_API_EQUAL); } for (u8 i = 0; i < 3; ++i) ledOff(LED_PIN[i]); // turn off the LEDs if (STATUS == OFF) // and if the status to display is "off" return; // keep the LEDs off ledOn(LED_PIN[STATUS]); // otherwise, turn on the appropriate LED return; }
/***********************************************************************//** * @brief Optimize model parameters using Levenberg-Marquardt method ***************************************************************************/ void ctlike::optimize_lm(void) { // Write Header for optimization and indent for optimizer logging if (logTerse()) { log << std::endl; log.header1("Maximum likelihood optimisation"); log.indent(1); } // Compute number of fitted parameters int nfit = 0; for (int i = 0; i < m_obs.models().size(); ++i) { const GModel* model = m_obs.models()[i]; for (int k = 0; k < model->size(); ++k) { if ((*model)[k].is_free()) { nfit++; } } } // Notify if all parameters are fixed if (nfit == 0) { if (logTerse()) { log << "WARNING: All model parameters are fixed!"; log << std::endl; log << " ctlike will proceed without fitting parameters."; log << std::endl; log << " All curvature matrix elements will be zero."; log << std::endl; } } // Perform LM optimization m_obs.optimize(*m_opt); // Optionally refit if (m_refit) { // Dump new header log.indent(0); if (logTerse()) { log << std::endl; log.header1("Maximum likelihood re-optimisation"); log.indent(1); } // Optimise again m_obs.optimize(*m_opt); } // Optionally show curvature matrix if (logNormal()) { log << std::endl; log.header1("Curvature matrix"); log.indent(1); log << *(const_cast<GObservations::likelihood&>(m_obs.function()).curvature()); log << std::endl; } // Compute errors m_obs.errors(*m_opt); // Store maximum log likelihood value m_logL = -(m_opt->value()); // Remove indent log.indent(0); // Return return; }
/***********************************************************************//** * @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; }
/***********************************************************************//** * @brief Simulate event data * * This method runs the simulation. Results are not saved by this method. * Invoke "save" to save the results. ***************************************************************************/ void ctobssim::run(void) { // Switch screen logging on in debug mode if (logDebug()) { log.cout(true); } // Get parameters get_parameters(); // Write input parameters into logger if (logTerse()) { log_parameters(); log << std::endl; } // Special mode: if read ahead is specified we know that we called // the execute() method, hence files are saved immediately and event // lists are disposed afterwards. if (read_ahead()) { m_save_and_dispose = true; } // Determine the number of valid CTA observations, set energy dispersion flag // for all CTA observations and save old values in save_edisp vector int n_observations = 0; std::vector<bool> save_edisp; save_edisp.assign(m_obs.size(), false); for (int i = 0; i < m_obs.size(); ++i) { GCTAObservation* obs = dynamic_cast<GCTAObservation*>(m_obs[i]); if (obs != NULL) { save_edisp[i] = obs->response()->apply_edisp(); obs->response()->apply_edisp(m_apply_edisp); n_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 execution mode into logger if (logTerse()) { log << std::endl; log.header1("Execution mode"); log << gammalib::parformat("Event list management"); if (m_save_and_dispose) { log << "Save and dispose (reduces memory needs)" << std::endl; } else { log << "Keep events in memory" << std::endl; } log << gammalib::parformat("Output format"); if (m_use_xml) { log << "Write Observation Definition XML file" << std::endl; } else { log << "Write single event list FITS file" << std::endl; } } // Write seed values into logger if (logTerse()) { log << std::endl; log.header1("Seed values"); for (int i = 0; i < m_rans.size(); ++i) { log << gammalib::parformat("Seed "+gammalib::str(i)); log << gammalib::str(m_rans[i].seed()) << std::endl; } } // Write observation(s) into logger if (logTerse()) { log << std::endl; if (m_obs.size() > 1) { log.header1("Observations"); } else { log.header1("Observation"); } log << m_obs << std::endl; } // Write header if (logTerse()) { log << std::endl; if (m_obs.size() > 1) { log.header1("Simulate observations"); } else { log.header1("Simulate observation"); } } // From here on the code can be parallelized if OpenMP support // is enabled. The code in the following block corresponds to the // code that will be executed in each thread #pragma omp parallel { // Each thread will have it's own logger to avoid conflicts GLog wrklog; if (logDebug()) { wrklog.cout(true); } // Allocate and initialize copies for multi-threading GModels models(m_obs.models()); // Copy configuration from application logger to thread logger wrklog.date(log.date()); wrklog.name(log.name()); // Set a big value to avoid flushing wrklog.max_size(10000000); // Loop over all observation in the container. If OpenMP support // is enabled, this loop will be parallelized. #pragma omp for for (int i = 0; i < m_obs.size(); ++i) { // Get pointer on 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) { wrklog.header3("Observation "+obs->name()); } else { wrklog.header3("Observation"); } } // Work on a clone of the CTA observation. This makes sure that // any memory allocated for computing (for example a response // cache) is properly de-allocated on exit of this run GCTAObservation obs_clone = *obs; // Save number of events before entering simulation int events_before = obs_clone.events()->size(); // Simulate source events simulate_source(&obs_clone, models, m_rans[i], &wrklog); // Simulate source events simulate_background(&obs_clone, models, m_rans[i], &wrklog); // Dump simulation results if (logNormal()) { wrklog << gammalib::parformat("MC events"); wrklog << obs_clone.events()->size() - events_before; wrklog << " (all models)"; wrklog << std::endl; } // Append the event list to the original observation obs->events(*(obs_clone.events())); // If requested, event lists are saved immediately if (m_save_and_dispose) { // Set event output file name. If multiple observations are // handled, build the filename from prefix and observation // index. Otherwise use the outfile parameter. std::string outfile; if (m_use_xml) { m_prefix = (*this)["prefix"].string(); outfile = m_prefix + gammalib::str(i) + ".fits"; } else { outfile = (*this)["outevents"].filename(); } // Store output file name in original observation obs->eventfile(outfile); // Save observation into FITS file. This is a critical zone // to avoid multiple threads writing simultaneously #pragma omp critical { obs_clone.save(outfile, clobber()); } // Dispose events obs->dispose_events(); } // ... otherwise append the event list to the original observation /* else { obs->events(*(obs_clone.events())); } */ } // endif: CTA observation found } // endfor: looped over observations // At the end, the content of the thread logger is added to // the application logger #pragma omp critical (log) { log << wrklog; } } // end pragma omp parallel // Restore energy dispersion flag for all CTA observations for (int i = 0; i < m_obs.size(); ++i) { GCTAObservation* obs = dynamic_cast<GCTAObservation*>(m_obs[i]); if (obs != NULL) { obs->response()->apply_edisp(save_edisp[i]); } } // Return return; }
/***********************************************************************//** * @brief Simulate background events from model * * @param[in] obs Pointer on CTA observation. * @param[in] models Models. * @param[in] ran Random number generator. * @param[in] wrklog Pointer to logger. * * Simulate background events from models. The events are stored as event * list in the observation. * * This method does nothing if the observation pointer is NULL. ***************************************************************************/ void ctobssim::simulate_background(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 event list (circumvent const correctness) GCTAEventList* events = static_cast<GCTAEventList*>(const_cast<GEvents*>(obs->events())); // Loop over all models for (int i = 0; i < models.size(); ++i) { // Get data model (NULL if not a data model) const GModelData* model = dynamic_cast<const GModelData*>(models[i]); // If we have a data model that applies to the present observation // then simulate events if (model != NULL && model->is_valid(obs->instrument(), obs->id())) { // Get simulated CTA event list. Note that this method // includes the deadtime correction. GCTAEventList* list = dynamic_cast<GCTAEventList*>(model->mc(*obs, ran)); // Continue only if we got a CTA event list if (list != NULL) { // Reserves space for events events->reserve(list->size()+events->size()); // Append events for (int k = 0; k < list->size(); k++) { // Get event pointer GCTAEventAtom* event = (*list)[k]; // Use event only if it falls within ROI if (events->roi().contains(*event)) { // Set event identifier event->event_id(m_event_id); m_event_id++; // Append event events->append(*event); } // endif: event was within ROI } // endfor: looped over all events // Dump simulation results if (logNormal()) { *wrklog << gammalib::parformat("MC background events"); *wrklog << list->size() << std::endl; } // Free event list delete list; } // endif: we had a CTA event list } // endif: model was valid } // endfor: looped over all models } // endif: observation pointer was valid // Return return; }
/***********************************************************************//** * @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; }
/***********************************************************************//** * @brief Simulate event data * * This method runs the simulation. Results are not saved by this method. * Invoke "save" to save the results. ***************************************************************************/ void ctobssim::run(void) { // Switch screen logging on in debug mode if (logDebug()) { log.cout(true); } // Get parameters get_parameters(); // Write input parameters into logger if (logTerse()) { log_parameters(); log << std::endl; } // Write seed values into logger if (logTerse()) { log << std::endl; log.header1("Seed values"); for (int i = 0; i < m_rans.size(); ++i) { log << gammalib::parformat("Seed "+gammalib::str(i)); log << gammalib::str(m_rans[i].seed()) << std::endl; } } // Write observation(s) into logger if (logTerse()) { log << std::endl; if (m_obs.size() > 1) { log.header1("Observations"); } else { log.header1("Observation"); } log << m_obs << std::endl; } // Write header if (logTerse()) { log << std::endl; if (m_obs.size() > 1) { log.header1("Simulate observations"); } else { log.header1("Simulate observation"); } } // Initialise counters int n_observations = 0; // From here on the code can be parallelized if OpenMP support // is enabled. The code in the following block corresponds to the // code that will be executed in each thread #pragma omp parallel { // Each thread will have it's own logger to avoid conflicts GLog wrklog; if (logDebug()) { wrklog.cout(true); } // Copy configuration from application logger to thread logger wrklog.date(log.date()); wrklog.name(log.name()); // Set a big value to avoid flushing wrklog.max_size(10000000); // Loop over all observation in the container. If OpenMP support // is enabled, this looped will be parallelized. #pragma omp for for (int i = 0; i < m_obs.size(); ++i) { // 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) { wrklog.header3("Observation "+obs->name()); } else { wrklog.header3("Observation"); } } // Increment counter n_observations++; // Save number of events before entering simulation int events_before = obs->events()->size(); // Simulate source events simulate_source(obs, m_obs.models(), m_rans[i], &wrklog); // Simulate source events simulate_background(obs, m_obs.models(), m_rans[i], &wrklog); // Dump simulation results if (logNormal()) { wrklog << gammalib::parformat("MC events"); wrklog << obs->events()->size() - events_before; wrklog << " (all models)"; wrklog << std::endl; } } // endif: CTA observation found } // endfor: looped over observations // At the end, the content of the thread logger is added to // the application logger #pragma omp critical (log) { log << wrklog; } } // end pragma omp parallel // 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; } // Return return; }
T& Random< T, G, I, F >::logNormal(T &t, F m, F s) { return const_cast< T& >(logNormal(const_cast< const T& >(t), m, s)); }
// Returns 0 iff no measurement taken, 1 if a valid measurement was found, -1 if observed to be empty template <typename PointT, typename NormalT> int cpu_tsdf::TSDFVolumeOctree::updateVoxel ( const cpu_tsdf::OctreeNode::Ptr &voxel, const pcl::PointCloud<PointT> &cloud, const pcl::PointCloud<NormalT> &normals, const Eigen::Affine3f &trans_inv) { // assert (!voxel->hasChildren ()); if (voxel->hasChildren ()) { std::vector<OctreeNode::Ptr>& children = voxel->getChildren (); std::vector<bool> is_empty (children.size ()); //#pragma omp parallel for for (size_t i = 0; i < children.size (); i++) { is_empty[i] = updateVoxel (children[i], cloud, normals, trans_inv) < 0; } bool all_are_empty = true; for (size_t i = 0; i < is_empty.size (); i++) all_are_empty &= is_empty[i]; if (all_are_empty) { children.clear (); // Remove empty voxels } else { return (1); // Say I am not empty } } pcl::PointXYZ v_g_orig; voxel->getCenter (v_g_orig.x, v_g_orig.y, v_g_orig.z); pcl::PointXYZ v_g = pcl::transformPoint (v_g_orig, trans_inv); if (v_g.z < min_sensor_dist_ || v_g.z > max_sensor_dist_) return (0); // No observation int u, v; if (!reprojectPoint (v_g, u, v)) return (0); // No observation const PointT &pt = cloud (u,v); if (pcl_isnan (pt.z)) return (0); // No observation // if (pt.z >= max_sensor_dist_) // We want to let empty points be empty, even at noisy readings // return (0); float d; float w; voxel->getData (d, w); float d_new = (pt.z - v_g.z); // Check if we can split if (fabs (d_new) < 3*voxel->getMaxSize ()/4.)// || (fabs (d_new) < max_dist_)) { float xsize, ysize, zsize; voxel->getSize (xsize, ysize, zsize); if (xsize > xsize_ / xres_ && ysize > ysize_ / yres_ && zsize > zsize_ / zres_) { std::vector<OctreeNode::Ptr>& children = voxel->split (); std::vector<bool> is_empty (children.size ()); //#pragma omp parallel for for (size_t i = 0; i < children.size (); i++) { // TODO Make the weight and distance match the parent's? // children[i]->setData (d, w); is_empty[i] = updateVoxel (children[i], cloud, normals, trans_inv) < 0; } bool all_are_empty = true; for (size_t i = 0; i < is_empty.size (); i++) all_are_empty &= is_empty[i]; if (all_are_empty) { children.clear (); // Remove empty voxel } else { return (1); // Say I am not empty } } } if (d_new > max_dist_pos_) { d_new = max_dist_pos_; } else if (d_new < -max_dist_neg_) { return (0); // No observation, effectively } // Normalize s.t. -1 = unobserved d_new /= max_dist_neg_; float w_new = 1; if (weight_by_depth_) w_new *= (1 - std::min(pt.z / 10., 1.)); // Scales s.t. at 10m it's worthless if (weight_by_variance_ && voxel->nsample_ > 5) w_new *= std::exp (logNormal (d_new, voxel->d_, voxel->getVariance ())); if (integrate_color_) voxel->addObservation (d_new, w_new, max_weight_, pt.r, pt.g, pt.b); else voxel->addObservation (d_new, w_new, max_weight_); if (voxel->d_ < -0.99) return (0); else if (voxel->d_ < 0.99* max_dist_pos_ / max_dist_neg_) //if I am not empty return (1); // Say so else return (-1); // Otherwise say I'm empty }
void Gui::SetArm(const char* text) { //Initialize a surface used to hide a part of the screen wich is used later SDL_Surface* hide = NULL; hide=LoadImage("Images/hide.png"); //The variables that the window is going to get double mean =0;//the mean of the arm double variance =0;//its variance char armType ='A';//its type //Initializing the texts Texts arm(0,150,_font,text,_textColor); Texts instructions(0,250,_font2,"Choose a type of arm then click in the boxes and type the parameters",_textColor); //Initializing the buttons //Ok button to skip to the next window Buttons ok(361,500, "Images/ok1.png", "Images/ok2.png","Images/ok3.png"); //Type zones for the mean and the variance TypeZone meanT(300,400,_font2,"Mean",_textColor); TypeZone varianceT(600,400,_font2,"Variance",_textColor); //Radiobuttons to choose the type of arm (exponential, uniform real, uniform int, poisson, logNormal) RadioButtons exp(100,300,"Exponential",_font2,_textColor); RadioButtons unifr(exp.GetBox().x+exp.GetBox().w+20,300,"Uniform real",_font2,_textColor); RadioButtons unifi(unifr.GetBox().x+unifr.GetBox().w+20,300,"Uniform int",_font2,_textColor); RadioButtons poisson(unifi.GetBox().x+unifi.GetBox().w+20,300,"Poisson",_font2,_textColor); RadioButtons logNormal(poisson.GetBox().x+poisson.GetBox().w+20,300,"Log-normal",_font2,_textColor); //Calculate the x for centering them (width of the screen minus the sum the width of the buttons) int xCentered = ((*(_screen.GetScreen())).clip_rect.w-exp.GetBox().w-unifr.GetBox().w-unifi.GetBox().w-poisson.GetBox().w-logNormal.GetBox().w-80)/2; //Relocate the buttons exp.SetPosition(xCentered,exp.GetBox().y); unifr.SetPosition(exp.GetBox().x+exp.GetBox().w+20,unifr.GetBox().y); unifi.SetPosition(unifr.GetBox().x+unifr.GetBox().w+20,unifi.GetBox().y); poisson.SetPosition(unifi.GetBox().x+unifi.GetBox().w+20,poisson.GetBox().y); logNormal.SetPosition(poisson.GetBox().x+poisson.GetBox().w+20,logNormal.GetBox().y); //Display them all arm.DisplayCentered(_screen); instructions.DisplayCentered(_screen); //meanT.Display(_screen); ok.Show(_screen); exp.Show(_screen); unifr.Show(_screen); unifi.Show(_screen); poisson.Show(_screen); logNormal.Show(_screen); meanT.DisplayLeft(_screen,mean,_font2,_textColor); varianceT.DisplayRight(_screen,mean,_font2,_textColor); //Initialize the event structure SDL_Event event; //Initialization of the loop bool isChoiceCorrect= false; bool skip=false; while((skip==false)&&(_quit==false)) { //While there's an event to handle while( SDL_PollEvent( &event ) ) { //the buttons react to the user's actions ok.HandleEvents(event); exp.HandleEvents(event); unifr.HandleEvents(event); unifi.HandleEvents(event); poisson.HandleEvents(event); logNormal.HandleEvents(event); meanT.HandleEvents(event,mean); //For some button we just need the mean to set the distribution so in this case we hide the variance if((exp.IsActive()==false)&&(poisson.IsActive()==false)) { varianceT.HandleEvents(event,variance); } //we check if one option was chosen isChoiceCorrect = (exp.IsActive()|| unifr.IsActive()||unifi.IsActive()||poisson.IsActive()||logNormal.IsActive()); //If the user clicks on ok and made a choice if((ok.HandleEvents(event)==false)&&(isChoiceCorrect)) { //skip to the next window skip=true; } //If he clicks on ok and hasn't made a choice then change color of the text if((ok.HandleEvents(event)==false)&&(isChoiceCorrect==false)) { SDL_Color red={240,0,0}; exp.SetColor(red); unifr.SetColor(red); unifi.SetColor(red); poisson.SetColor(red); logNormal.SetColor(red); } //If the user has Xed out the window if( event.type == SDL_QUIT ) { //Quit the program _quit = true; } } //Display all ok.Show(_screen); exp.Show(_screen); unifr.Show(_screen); unifi.Show(_screen); poisson.Show(_screen); logNormal.Show(_screen); meanT.DisplayLeft(_screen,mean, _font2,_textColor); //For some button we just need the mean to set the distribution so in this case we hide the variance if((exp.IsActive()==false)&&(poisson.IsActive()==false)) { varianceT.DisplayRight(_screen,variance, _font2,_textColor); } else { ApplySurface(400,398,hide,_screen.GetScreen()); } _screen.Display(); } _screen.Clean("Images/background.png"); //Then we save the parameters in the Gui's attributes //First we get the type of arm: if(exp.IsActive()){armType='A';} if(unifr.IsActive()){armType='B';} if(unifi.IsActive()){armType='C';} if(poisson.IsActive()){armType='D';} if(logNormal.IsActive()){armType='E';} std::vector<double> parameter; //Then acoording to the type of arms we calculate the parameters required switch(armType) { case 'A'://Exponential: we need the lambda _choices.push_back('A');//we save the type in _choices parameter.push_back(1.0/(mean*1.0)); _parameters.push_back(parameter);//and the parameters calculated using the mean and the variance in _parameters break; case 'B'://uniform real on [a,b] we need a and b _choices.push_back('B'); parameter.push_back((2.0*mean-sqrt(12.0*variance))/2.0); parameter.push_back((2.0*mean+sqrt(12.0*variance))/2.0); _parameters.push_back(parameter); break; case 'C': _choices.push_back('C');//uniform integer on [a,b] we need a and b parameter.push_back((2.0*mean -sqrt(12.0*variance+1.0)+1)/2.0); parameter.push_back((2.0*mean+sqrt(12.0*variance+1)-1)/2.0); _parameters.push_back(parameter); break; case 'D': //poisson we just need the mu wich equal to the mean _choices.push_back('D'); parameter.push_back(mean); _parameters.push_back(parameter); break; default: _choices.push_back('E'); //log-normal we need mu and sigma square parameter.push_back(log(mean*1.0)-0.5*log(1.0+((variance*1.0)/(mean*mean*1.0)))); parameter.push_back((2.0*mean+sqrt(12.0*variance+1.0)-1.0)/2.0); _parameters.push_back(parameter); break; } }