@@ -274,7 +274,7 @@ void write_best_fits(const options_t& opts, const input_state_t& input, const gr
274274}
275275
276276void write_sfhs (const options_t & opts, const input_state_t & input, const gridder_t & gridder,
277- const output_state_t & output) {
277+ const fitter_t & fitter, const output_state_t & output) {
278278
279279 if (opts.verbose ) note (" saving star formation histories" );
280280
@@ -292,9 +292,20 @@ void write_sfhs(const options_t& opts, const input_state_t& input, const gridder
292292 unit = " Msol" ;
293293 }
294294
295+ uint_t nconf = input.conf_interval .size ();
296+ bool has_median = false ;
297+ if (!input.conf_interval .empty () && !opts.interval_from_chi2 ) {
298+ // Also add the median SFH for MC simulations
299+ ++nconf;
300+ has_median = true ;
301+ }
302+
295303 std::string header = " # t " +quantity+" (t) (" +unit+" )" ;
296304 if (!opts.c_interval .empty ()) {
297- header += " med_" +quantity;
305+ if (has_median) {
306+ header += " med_" +quantity;
307+ }
308+
298309 for (float c : input.conf_interval ) {
299310 float cc = 100 *(1 -2 *c);
300311 std::string is = (cc < 0.0 ? " u" : " l" )+to_string (round (abs (cc)));
@@ -308,9 +319,10 @@ void write_sfhs(const options_t& opts, const input_state_t& input, const gridder
308319 for (uint_t is : range (input.id )) {
309320 vec1u idm = gridder.grid_ids (output.best_model [is]);
310321 vec1d t = rgen_step (1e6 , e10 (gridder.auniv [idm[grid_id::z]]), opts.sfh_output_step );
322+ vec2f sfh = replicate (fnan, t.size (), 1 +nconf);
311323
312- // Get best fit SFH
313- vec2f sfh (t. size (), 1 +input. conf_interval . size ()+(input. conf_interval . empty () ? 0 : 1 )); {
324+ // Best fit
325+ {
314326 vec1d tsfh;
315327 if (!gridder.get_sfh (output.best_model [is], t, tsfh)) {
316328 return ;
@@ -322,23 +334,58 @@ void write_sfhs(const options_t& opts, const input_state_t& input, const gridder
322334
323335 // Get confidence intervals
324336 if (!opts.c_interval .empty ()) {
325- vec2f sim_sfh (t.size (), opts.n_sim );
326- for (uint_t ir : range (opts.n_sim )) {
327- vec1d tsfh;
328- if (!gridder.get_sfh (output.mc_best_model (is,ir), t, tsfh)) {
329- return ;
330- }
337+ if (opts.n_sim != 0 ) {
338+ // From Monte Carlo simulations
339+ vec2f sim_sfh (t.size (), opts.n_sim );
340+ for (uint_t ir : range (opts.n_sim )) {
341+ vec1d tsfh;
342+ if (!gridder.get_sfh (output.mc_best_model (is,ir), t, tsfh)) {
343+ return ;
344+ }
331345
332- float mass = output.mc_best_props (is,prop_id::mass,ir);
333- sim_sfh (_,ir) = tsfh*mass;
334- }
346+ float mass = output.mc_best_props (is,prop_id::mass,ir);
347+ sim_sfh (_,ir) = tsfh*mass;
348+ }
335349
336- for (uint_t it : range (t)) {
337- vec1f tsfh = sim_sfh (it,_);
338- sfh (it,1 ) = inplace_median (tsfh);
339- for (uint_t ic : range (input.conf_interval )) {
340- sfh (it,2 +ic) = inplace_percentile (tsfh, input.conf_interval [ic]);
350+ for (uint_t it : range (t)) {
351+ vec1f tsfh = sim_sfh.safe (it,_);
352+ sfh.safe (it,1 ) = inplace_median (tsfh);
353+ for (uint_t ic : range (input.conf_interval )) {
354+ sfh.safe (it,2 +ic) = inplace_percentile (tsfh, input.conf_interval [ic]);
355+ }
341356 }
357+ } else {
358+ // From chi2 grid
359+
360+ fitter.iterate_best_chi2 (is, [&](uint_t id, const vec1f& p, float chi2) {
361+ if (chi2 - output.best_chi2 .safe [is] > input.delta_chi2 .back ()) return ;
362+
363+ vec1d tsfh;
364+ if (!gridder.get_sfh (id, t, tsfh)) {
365+ return ;
366+ }
367+
368+ float mass = p[prop_id::mass];
369+ tsfh *= mass;
370+
371+ for (uint_t ic : range (input.conf_interval )) {
372+ if (chi2 - output.best_chi2 .safe [is] < abs (input.delta_chi2 [ic])) {
373+ for (uint_t it : range (t)) {
374+ double v = tsfh.safe [it];
375+ float & saved = sfh.safe (it,1 +ic);
376+ if (input.delta_chi2 [ic] < 0.0 ) {
377+ if (saved > v || !is_finite (saved)) {
378+ saved = v;
379+ }
380+ } else {
381+ if (saved < v || !is_finite (saved)) {
382+ saved = v;
383+ }
384+ }
385+ }
386+ }
387+ }
388+ });
342389 }
343390 }
344391
@@ -363,7 +410,7 @@ void write_sfhs(const options_t& opts, const input_state_t& input, const gridder
363410}
364411
365412void write_output (const options_t & opts, const input_state_t & input, const gridder_t & gridder,
366- const output_state_t & output) {
413+ const fitter_t & fitter, const output_state_t & output) {
367414
368415 write_catalog (opts, input, gridder, output);
369416
@@ -372,7 +419,7 @@ void write_output(const options_t& opts, const input_state_t& input, const gridd
372419 }
373420
374421 if (opts.best_sfhs ) {
375- write_sfhs (opts, input, gridder, output);
422+ write_sfhs (opts, input, gridder, fitter, output);
376423 }
377424
378425 if (opts.verbose ) {
0 commit comments