--- name: samples_to_grid_2d kind: function lang: cpp domain: datascience version: "1.0.0" purity: pure signature: "void samples_to_grid_2d_counts(const double* x, const double* y, size_t n, double xmin, double xmax, double ymin, double ymax, int nx, int ny, unsigned int* out_counts); void samples_to_grid_2d_density(...float* out_density); void counts_to_density(const unsigned int* counts, int nx, int ny, float* out_density)" description: "Binning 2D CPU para alimentar heatmap_cpp_viz / contour_cpp_viz / surface_plot_3d desde un set de samples (x[], y[]). Variante counts (uint, acumulable) y density (float [0,1] normalizado a max). Pareja CPU del gpu_histogram_2d." tags: [binning, histogram_2d, density, heatmap, contour, datascience] uses_functions: [] uses_types: [] returns: [] returns_optional: false error_type: "" imports: [cstddef, cmath, vector] tested: false tests: [] test_file_path: "" file_path: "cpp/functions/datascience/samples_to_grid_2d.cpp" params: - name: samples_x desc: "Array de coordenadas X de los samples." - name: samples_y desc: "Array de coordenadas Y de los samples." - name: n desc: "Numero de samples (longitud de samples_x y samples_y)." - name: xmin desc: "Limite inferior X. Samples con x fuera de [xmin, xmax) se descartan." - name: xmax desc: "Limite superior X." - name: ymin desc: "Limite inferior Y." - name: ymax desc: "Limite superior Y." - name: nx desc: "Bins en X." - name: ny desc: "Bins en Y." - name: out_counts desc: "Buffer destino unsigned int[nx*ny] row-major (idx = y*nx + x). NO se inicializa: el caller decide si poner a cero (acumular sobre llamadas previas)." - name: out_density desc: "Buffer destino float[nx*ny] normalizado a max=1.0. Variante density auto-rellena." - name: counts desc: "(counts_to_density) input uint[nx*ny]." output: "out_counts incrementado con los conteos; out_density normalizado [0, 1]. Si todos los counts son 0, density se llena con 0." --- # samples_to_grid_2d Binning 2D para densidades de muestras (joint posteriors, walks 2D, scatter density). Versión CPU canónica — usar GPU `gpu_histogram_2d` cuando los samples ya viven en GPU. ## Patron tipico (mcmc-visualizer / mcmc-full) ```cpp constexpr int NX = 128, NY = 128; std::vector density(NX * NY); fn::ds::samples_to_grid_2d_density( chain_x.data(), chain_y.data(), chain_x.size(), -5.0, 5.0, -5.0, 5.0, NX, NY, density.data() ); fn::viz::heatmap(density.data(), NX, NY, /*...*/); ``` ## Acumulado a lo largo de iteraciones Para visualizar la cadena creciendo en vivo sin recomputar todo: ```cpp std::vector counts(NX * NY, 0u); // Cada iteracion del MCMC: fn::ds::samples_to_grid_2d_counts( new_x.data(), new_y.data(), new_x.size(), -5.0, 5.0, -5.0, 5.0, NX, NY, counts.data() // sigue acumulando ); std::vector density(NX * NY); fn::ds::counts_to_density(counts.data(), NX, NY, density.data()); fn::viz::heatmap(density.data(), NX, NY, /*...*/); ``` ## Notas - Samples fuera del rango `[xmin, xmax) x [ymin, ymax)` se descartan, no se clampean. Si quieres clamp, pre-clamp los samples antes de llamar. - O(n) sobre samples + O(nx*ny) para to_density. Para n = 10^7, nx=ny=256: ~70 ms CPU. Para refresh interactivo a 60 FPS, downsample a n=10^5 o usar la version GPU. - Layout row-major idx = y*nx + x — coincide con lo que esperan `heatmap_cpp_viz` y `contour_cpp_viz`.