@@ -65,7 +65,6 @@ function profile_grid(model::AbstractGNFW{T}, logθs, redshifts, logMs) where T
6565end
6666
6767
68-
6968"""
7069Computes a real-space beam interpolator and a maximum
7170"""
@@ -86,72 +85,17 @@ function realspacegaussbeam(::Type{T}, θ_FWHM::Ti; rtol=1e-24, N_θ::Int=2000)
8685end
8786
8887
89- # heuristic for sizehint
90- _approx_discbuffer_size (nside, θmax) = ceil (Int, 1.1 * π * θmax^ 2 / (nside2pixarea (nside)))
91-
92- struct HealpixSerialProfileWorkspace{T} <: AbstractProfileWorkspace{T}
93- nside:: Int
94- ringinfo:: RingInfo
95- disc_buffer:: Vector{Int}
96- θmax:: T
97- posmap:: Vector{Tuple{T, T, T}}
98-
99- HealpixSerialProfileWorkspace {T} (nside:: Int , θmax) where T = new {T} (
100- nside,
101- RingInfo (0 , 0 , 0 , 0.0 , true ),
102- sizehint! (Int[], _approx_discbuffer_size (nside, θmax)),
103- T (θmax),
104- vectorhealpixmap (T, nside)
105- )
106-
107- HealpixSerialProfileWorkspace {T} (nside, ringinfo, disc_buffer, θmax, posmap) where T = new {T} (
108- nside, ringinfo, disc_buffer, T (θmax), posmap)
109- end
110-
111- # default outer constructors for Float64
112- HealpixSerialProfileWorkspace (nside:: Int , θmax) = HealpixSerialProfileWorkspace {Float64} (nside, θmax)
113-
114- function Base. show (io:: IO , :: HealpixSerialProfileWorkspace{T} ) where T
115- expr = " HealpixSerialProfileWorkspace{$(T) }"
116- print (io, expr)
117- end
118-
119- struct HealpixProfileWorkspace{T} <: AbstractProfileWorkspace{T}
120- nside:: Int
121- ringinfo:: RingInfo
122- disc_buffer:: Vector{Vector{Int}}
123- θmax:: T
124- posmap:: Vector{Tuple{T, T, T}}
125-
126- HealpixProfileWorkspace {T} (nside:: Int , θmax, nthreads= Threads. nthreads ()) where T = new {T} (
127- nside,
128- RingInfo (0 , 0 , 0 , 0.0 , true ),
129- Vector{Int}[sizehint! (Int[], _approx_discbuffer_size (nside, θmax)) for i in 1 : nthreads],
130- T (θmax),
131- vectorhealpixmap (T, nside)
132- )
133- end
134-
135- HealpixProfileWorkspace (nside:: Int , θmax) = HealpixProfileWorkspace {Float64} (nside, θmax)
136-
137- # unlike other workspaces, Healpix workspace needs a mutable buffer per thread
138- # so asking for a workspace with a thread id will return the appropriate mutable workspace
139- function wrapserialworkspace (w:: HealpixProfileWorkspace{T} , tid) where T
140- return HealpixSerialProfileWorkspace {T} (w. nside, w. ringinfo, w. disc_buffer[tid], w. θmax, w. posmap)
141- end
88+ # function realspacebeampaint!(hp_map, w::HealpixSerialProfileWorkspace, realprofile, flux, θ₀, ϕ₀)
89+ # x₀, y₀, z₀ = ang2vec(θ₀, ϕ₀)
90+ # XGPaint.queryDiscRing!(w.disc_buffer, w.ringinfo, hp_map.resolution, θ₀, ϕ₀, w.θmax)
14291
143-
144- function realspacebeampaint! (hp_map, w:: HealpixSerialProfileWorkspace , realprofile, flux, θ₀, ϕ₀)
145- x₀, y₀, z₀ = ang2vec (θ₀, ϕ₀)
146- XGPaint. queryDiscRing! (w. disc_buffer, w. ringinfo, hp_map. resolution, θ₀, ϕ₀, w. θmax)
147-
148- for ir in w. disc_buffer
149- x₁, y₁, z₁ = w. posmap. pixels[ir]
150- d² = (x₁ - x₀)^ 2 + (y₁ - y₀)^ 2 + (z₁ - z₀)^ 2
151- θ = acos (1 - d² / 2 )
152- hp_map. pixels[ir] += flux * realprofile (θ)
153- end
154- end
92+ # for ir in w.disc_buffer
93+ # x₁, y₁, z₁ = w.posmap.pixels[ir]
94+ # d² = (x₁ - x₀)^2 + (y₁ - y₀)^2 + (z₁ - z₀)^2
95+ # θ = acos(1 - d² / 2)
96+ # hp_map.pixels[ir] += flux * realprofile(θ)
97+ # end
98+ # end
15599
156100
157101""" Apply a beam to a profile grid"""
@@ -385,26 +329,66 @@ function profile_paint!(m::Enmap{T, 2, Matrix{T}, Gnomonic{T}},
385329end
386330
387331
388- function profile_paint_generic! (m:: HealpixMap{T, RingOrder} , w:: HealpixSerialProfileWorkspace ,
332+ # function profile_paint_generic!(m::HealpixMap{T, RingOrder}, w::HealpixSerialProfileWorkspace,
333+ # model, Mh, z, α₀, δ₀, θmax, normalization=1) where T
334+ # ϕ₀ = α₀
335+ # θ₀ = T(π)/2 - δ₀
336+ # x₀, y₀, z₀ = ang2vec(θ₀, ϕ₀)
337+ # θmin = compute_θmin(model)
338+ # XGPaint.queryDiscRing!(w.disc_buffer, w.ringinfo, m.resolution, θ₀, ϕ₀, θmax)
339+ # for ir in w.disc_buffer
340+ # x₁, y₁, z₁ = w.posmap[ir]
341+ # d² = (x₁ - x₀)^2 + (y₁ - y₀)^2 + (z₁ - z₀)^2
342+ # θ = acos(clamp(1 - d² / 2, -one(T), one(T)))
343+ # θ = max(θmin, θ) # clamp to minimum θ
344+ # m.pixels[ir] += ifelse(θ < θmax,
345+ # normalization * model(θ, Mh, z),
346+ # zero(T))
347+ # end
348+ # end
349+
350+ function profile_paint_generic! (m:: HealpixMap{T, RingOrder} , workspace:: RingWorkspace{T} ,
389351 model, Mh, z, α₀, δ₀, θmax, normalization= 1 ) where T
390- ϕ₀ = α₀
352+ ϕ₀ = α₀
391353 θ₀ = T (π)/ 2 - δ₀
392354 x₀, y₀, z₀ = ang2vec (θ₀, ϕ₀)
393355 θmin = compute_θmin (model)
394- XGPaint. queryDiscRing! (w. disc_buffer, w. ringinfo, m. resolution, θ₀, ϕ₀, θmax)
395- for ir in w. disc_buffer
396- x₁, y₁, z₁ = w. posmap[ir]
397- d² = (x₁ - x₀)^ 2 + (y₁ - y₀)^ 2 + (z₁ - z₀)^ 2
398- θ = acos (clamp (1 - d² / 2 , - one (T), one (T)))
399- θ = max (θmin, θ) # clamp to minimum θ
400- m. pixels[ir] += ifelse (θ < θmax,
401- normalization * model (θ, Mh, z),
402- zero (T))
356+
357+ # Get relevant rings for this disc
358+ ring_start, ring_end = get_relevant_rings (workspace. res, θ₀, θmax)
359+
360+ for ring_idx in ring_start: ring_end
361+ # Get pixel ranges on this ring that intersect the disc
362+ range1, range2 = get_ring_disc_ranges (workspace, ring_idx, θ₀, ϕ₀, θmax)
363+
364+ # Get precomputed ring info
365+ first_pixel = workspace. ring_first_pixels[ring_idx]
366+
367+ # Process both ranges (range2 may be empty for no phi wraparound)
368+ for pixel_range in (range1, range2)
369+ for pix_idx in pixel_range
370+ # Convert ring pixel index to global healpix pixel index
371+ global_pix = first_pixel + pix_idx - 1
372+
373+ # Get position of this pixel
374+ x₁, y₁, z₁ = pix2vecRing (workspace. res, global_pix)
375+
376+ # Compute angular distance
377+ d² = (x₁ - x₀)^ 2 + (y₁ - y₀)^ 2 + (z₁ - z₀)^ 2
378+ θ = acos (clamp (1 - d² / 2 , - one (T), one (T)))
379+ θ = max (θmin, θ) # clamp to minimum θ
380+
381+ # Add contribution to map
382+ m. pixels[global_pix] += ifelse (θ < θmax,
383+ normalization * model (θ, Mh, z),
384+ zero (T))
385+ end
386+ end
403387 end
404388end
405389
406390# fall back to generic profile painter if no specialized painter is defined for the model
407- function profile_paint! (m:: HealpixMap{T, RingOrder} , w:: HealpixSerialProfileWorkspace , model,
391+ function profile_paint! (m:: HealpixMap{T, RingOrder} , w:: RingWorkspace{T} , model,
408392 Mh, z, α₀, δ₀, θmax, normalization= 1 ) where T
409393 profile_paint_generic! (m, w, model, Mh, z, α₀, δ₀, θmax, normalization)
410394end
0 commit comments