efficiently adding many 2D Gaussians
- To: mathgroup at smc.vnet.net
- Subject: [mg91562] efficiently adding many 2D Gaussians
- From: "M.Roellig" <markus.roellig at googlemail.com>
- Date: Wed, 27 Aug 2008 06:43:36 -0400 (EDT)
Dear group, I need some help on reducing run time and memory usage for the following problem: I want to place a large number N (10000+) of 2D Gaussians in a plane (on a large array, m x m ) and add them up. I came up with a few approaches but they all fail, or become very slow once N >10000 or m>100. Here are my ideas so far (not bothering about dimensions, units, etc. and using 1000 positions only): SeedRandom[1111111]; posTab = RandomReal[NormalDistribution[0, 1], {1000, 2}]; 1. idea (fastest I could get): gsum = Compile[{{x, _Real, 1}}, Evaluate[ Total[Map[(1.* Exp[-(((x[[1]] - #[[1]])^2 + (x[[2]] - #[[2]])^2)/( 2. 0.25^2.))]) &, posTab]]]]; (* Warning Output: ----------------------- Part::partd: Part specification x[[1]] is longer than depth of \ object. >> Part::partd: Part specification x[[2]] is longer than depth of \ object. >> ------------------------*) xyArray = Array[{#1, #2} &, {100, 100}] // MatrixForm; map1e4 = Map[gsum, xyArray, {3}]; // Timing Out[22]= {11.843, Null} 2. idea (trying to use mapping, and came up with a very inefficient solution :-) Total[ Table[Exp[-(((x - #[[1]])^2 + (y - #[[2]])^2)/0.125)], {x, -5, 5, .1}, {y, -5, 5, .1}] & /@ posTab]; // Timing Out[9]= {85.375, Null} Using more than 1000 Gaussians doesn't fit into my memory and makes WinXp swapping memory to disk basically making the computation time unbearable. Of course this is no big surprise since I create one array for each individual Gaussian before adding them up. 3. completely different approach hoping to take advantage of internal mathematica optimization: SeedRandom[1111111]; posTab = RandomReal[NormalDistribution[0, 100], {1000, 2}]; clumpSum = Total[Map[(1.* Exp[-(((x - #[[1]])^2 + (y - #[[2]])^2)/(2. 10.^2.))]) &, posTab]]; clumpEm100 = Plot3D[clumpSum, {x, -350, 350}, {y, -350, 350}, PlotRange -> All, PlotPoints -> 100, MaxRecursion -> 0]; // Timing mapEm100 = clumpEm100[[1]] /. GraphicsComplex[pts_, __] -> pts; Out[25]= {53.485, Null} I am grateful for any advice on how to do this faster and more efficiently. I guess a clever usage of Fold/Nest could do it, but I failed to get it done. The code I use now is a little more complex, since I need to add up Gaussians with different sizes and amplitudes, which I take from a list: -------------------- fullEns ={{1/1000, 63095, 374775., 0.00237989, 112.101, 0.818147}, {1/100, 10000, 185962., 0.00647649, 20.143, 2.22645}, {1/10, 1584, 92273.2, 0.0176247, 5.91138, 6.05894}, {1, 251, 45785.5, 0.0479629, 0.837552, 16.4884}, {10, 39, 22718.5, 0.130523, 0.156455, 44.8706}, {100, 6, 11272.8, 0.355198, 0.220978, 122.108}, {1000, 1, 5593.51, 0.966614, 0.240513, 332.297}} (*In each sublist element 2 is the number, element 5 the amplitude, element 6 the stand.dev. I am discarding the first to rows to reduce total numbers. *) SeedRandom[1111111]; posEnsTab = Append[Table[ RandomReal[NormalDistribution[0, 100], {fullEns[[j, 2]], 2}], {j, 1, Length[fullEns] - 1}], {{0., 0.}}]; ensSum = Plus @@ Table[Total[ Map[( fullEns[[j, 5]]* Exp[-(((x - #[[1]])^2 + (y - #[[2]])^2)/( 2. fullEns[[j, 6]]^2.))]) &, posEnsTab[[j]]]], {j, 3, Length[fullEns]}]; ensSum100 = Plot3D[ensSum, {x, -350, 350}, {y, -350, 350}, PlotRange -> All, PlotPoints -> 100, MaxRecursion -> 0]; // Timing (* Out: {116.453, Null} *) ensMap100 = ensSum100[[1]] /. GraphicsComplex[pts_, __] -> pts; ListPlot3D[ensMap100, PlotRange -> All] Hope somebody can help me. Cheers, Markus
- Follow-Ups:
- Re: efficiently adding many 2D Gaussians
- From: Carl Woll <carlw@wolfram.com>
- Re: efficiently adding many 2D Gaussians