Skip to main content
added 4 characters in body
Source Link
Henrik Schumacher
  • 109.5k
  • 7
  • 186
  • 323

A severe problem is that Table generates an unpacked array, a thing that is often very annoying. When converting to an image, it is packed automatically (one can check that, e.g., with Developer`PackedArrayQ[ImageData[Image[dat]]]). And because many functions work faster on packed arrays than on unpacked ones, this increases the performance.

A vectorized implementation that exploits the very nature of the function (and is thus not very generalizable) is the following:

nx = ny = 1000;
dat = KroneckerProduct[
     (0.1 + Cos[Subdivide[0., 2. Pi, ny]]),
     Sin[Subdivide[0., 2. Pi, nx]]
     ];

0.003691

The maxima can be found by comparing each value to the maximum of its neighbors. The latter can be done efficiently with MaxFilter:

getindex = {Quotient[#, Dimensions[dat][[1]]] + 1, Mod[#, Dimensions[dat][[2]], 1]} &;
idx = getindex /@ 
     Random`Private`PositionsOf[
      Flatten@UnitStep[dat - MaxFilter[dat, {1, 1}]], 
      1
      ]; // AbsoluteTiming // First
idx
MatrixPlot@SparseArray[idx -> 1, Dimensions[dat]]

0.00108

{{1, 26}, {29, 1}, {30, 1}, {31, 1}, {32, 1}, {33, 1}, {34, 1}, {35, 1}, {36, 1}, {37, 1}, {38, 1}, {39, 1}, {40, 1}, {41, 1}, {42, 1}, {43, 1}, {44, 1}, {45, 1}, {46, 1}, {47, 1}, {48, 1}, {49, 1}, {50, 1}, {51, 1}, {51, 76}, {52, 1}, {53, 1}, {54, 1}, {55, 1}, {56, 1}, {57, 1}, {58, 1}, {59, 1}, {60, 1}, {61, 1}, {62, 1}, {63, 1}, {64, 1}, {65, 1}, {66, 1}, {67, 1}, {68, 1}, {69, 1}, {70, 1}, {71, 1}, {72, 1}, {73, 1}, {101, 26}}

enter image description here

This is about 10 times faster than MaxDetect>. But it does not distiguishdistinguish between local maxima and strict local maxima. However, a second sweep over the local maxima (which is much less expensive) could filter out the strict local maxima.

A severe problem is that Table generates an unpacked array, a thing that is often very annoying. When converting to an image, it is packed automatically (one can check that, e.g., with Developer`PackedArrayQ[ImageData[Image[dat]]]). And because many functions work faster on packed arrays than on unpacked ones, this increases the performance.

A vectorized implementation that exploits the very nature of the function (and is thus not very generalizable) is the following:

nx = ny = 1000;
dat = KroneckerProduct[
     (0.1 + Cos[Subdivide[0., 2. Pi, ny]]),
     Sin[Subdivide[0., 2. Pi, nx]]
     ];

0.003691

The maxima can be found by comparing each value to the maximum of its neighbors. The latter can be done efficiently with MaxFilter:

getindex = {Quotient[#, Dimensions[dat][[1]]] + 1, Mod[#, Dimensions[dat][[2]], 1]} &;
idx = getindex /@ 
     Random`Private`PositionsOf[
      Flatten@UnitStep[dat - MaxFilter[dat, {1, 1}]], 
      1
      ]; // AbsoluteTiming // First
idx
MatrixPlot@SparseArray[idx -> 1, Dimensions[dat]]

0.00108

{{1, 26}, {29, 1}, {30, 1}, {31, 1}, {32, 1}, {33, 1}, {34, 1}, {35, 1}, {36, 1}, {37, 1}, {38, 1}, {39, 1}, {40, 1}, {41, 1}, {42, 1}, {43, 1}, {44, 1}, {45, 1}, {46, 1}, {47, 1}, {48, 1}, {49, 1}, {50, 1}, {51, 1}, {51, 76}, {52, 1}, {53, 1}, {54, 1}, {55, 1}, {56, 1}, {57, 1}, {58, 1}, {59, 1}, {60, 1}, {61, 1}, {62, 1}, {63, 1}, {64, 1}, {65, 1}, {66, 1}, {67, 1}, {68, 1}, {69, 1}, {70, 1}, {71, 1}, {72, 1}, {73, 1}, {101, 26}}

enter image description here

This about 10 times faster than MaxDetect> But it does not distiguish between local maxima and strict local maxima. However, a second sweep over the local maxima (which is much less expensive) could filter out the strict local maxima.

A severe problem is that Table generates an unpacked array, a thing that is often very annoying. When converting to an image, it is packed automatically (one can check that, e.g., with Developer`PackedArrayQ[ImageData[Image[dat]]]). And because many functions work faster on packed arrays than on unpacked ones, this increases the performance.

A vectorized implementation that exploits the very nature of the function (and is thus not very generalizable) is the following:

nx = ny = 1000;
dat = KroneckerProduct[
     (0.1 + Cos[Subdivide[0., 2. Pi, ny]]),
     Sin[Subdivide[0., 2. Pi, nx]]
     ];

0.003691

The maxima can be found by comparing each value to the maximum of its neighbors. The latter can be done efficiently with MaxFilter:

getindex = {Quotient[#, Dimensions[dat][[1]]] + 1, Mod[#, Dimensions[dat][[2]], 1]} &;
idx = getindex /@ 
     Random`Private`PositionsOf[
      Flatten@UnitStep[dat - MaxFilter[dat, {1, 1}]], 
      1
      ]; // AbsoluteTiming // First
idx
MatrixPlot@SparseArray[idx -> 1, Dimensions[dat]]

0.00108

{{1, 26}, {29, 1}, {30, 1}, {31, 1}, {32, 1}, {33, 1}, {34, 1}, {35, 1}, {36, 1}, {37, 1}, {38, 1}, {39, 1}, {40, 1}, {41, 1}, {42, 1}, {43, 1}, {44, 1}, {45, 1}, {46, 1}, {47, 1}, {48, 1}, {49, 1}, {50, 1}, {51, 1}, {51, 76}, {52, 1}, {53, 1}, {54, 1}, {55, 1}, {56, 1}, {57, 1}, {58, 1}, {59, 1}, {60, 1}, {61, 1}, {62, 1}, {63, 1}, {64, 1}, {65, 1}, {66, 1}, {67, 1}, {68, 1}, {69, 1}, {70, 1}, {71, 1}, {72, 1}, {73, 1}, {101, 26}}

enter image description here

This is about 10 times faster than MaxDetect. But it does not distinguish between local maxima and strict local maxima. However, a second sweep over the local maxima (which is much less expensive) could filter out the strict local maxima.

added 2 characters in body
Source Link

A severe problem is that Table generates an unpacked array, a thing that is often very annoying. When converting to an image, it is packed automatically (one can check that, e.g., with DeveloperDeveloper`PackedArrayQ[ImageData[Image[dat]]]PackedArrayQ[ImageData[Image[dat]]]`). And because many functions work faster on packed arrays than on unpacked ones, this increases the performance.

A vectorized implementation that exploits the very nature of the function (and is thus not very generalizable) is the following:

nx = ny = 1000;
dat = KroneckerProduct[
     (0.1 + Cos[Subdivide[0., 2. Pi, ny]]),
     Sin[Subdivide[0., 2. Pi, nx]]
     ];

0.003691

The maxima can be found by comparing each value to the maximum of its neighbors. The latter can be done efficiently with MaxFilter:

getindex = {Quotient[#, Dimensions[dat][[1]]] + 1, Mod[#, Dimensions[dat][[2]], 1]} &;
idx = getindex /@ 
     Random`Private`PositionsOf[
      Flatten@UnitStep[dat - MaxFilter[dat, {1, 1}]], 
      1
      ]; // AbsoluteTiming // First
idx
MatrixPlot@SparseArray[idx -> 1, Dimensions[dat]]

0.00108

{{1, 26}, {29, 1}, {30, 1}, {31, 1}, {32, 1}, {33, 1}, {34, 1}, {35, 1}, {36, 1}, {37, 1}, {38, 1}, {39, 1}, {40, 1}, {41, 1}, {42, 1}, {43, 1}, {44, 1}, {45, 1}, {46, 1}, {47, 1}, {48, 1}, {49, 1}, {50, 1}, {51, 1}, {51, 76}, {52, 1}, {53, 1}, {54, 1}, {55, 1}, {56, 1}, {57, 1}, {58, 1}, {59, 1}, {60, 1}, {61, 1}, {62, 1}, {63, 1}, {64, 1}, {65, 1}, {66, 1}, {67, 1}, {68, 1}, {69, 1}, {70, 1}, {71, 1}, {72, 1}, {73, 1}, {101, 26}}

enter image description here

This about 10 times faster than MaxDetect> But it does not distiguish between local maxima and strict local maxima. However, a second sweep over the local maxima (which is much less expensive) could filter out the strict local maxima.

A severe problem is that Table generates an unpacked array, a thing that is often very annoying. When converting to an image, it is packed automatically (one can check that, e.g., with DeveloperPackedArrayQ[ImageData[Image[dat]]]`). And because many functions work faster on packed arrays than on unpacked ones, this increases the performance.

A vectorized implementation that exploits the very nature of the function (and is thus not very generalizable) is the following:

nx = ny = 1000;
dat = KroneckerProduct[
     (0.1 + Cos[Subdivide[0., 2. Pi, ny]]),
     Sin[Subdivide[0., 2. Pi, nx]]
     ];

0.003691

The maxima can be found by comparing each value to the maximum of its neighbors. The latter can be done efficiently with MaxFilter:

getindex = {Quotient[#, Dimensions[dat][[1]]] + 1, Mod[#, Dimensions[dat][[2]], 1]} &;
idx = getindex /@ 
     Random`Private`PositionsOf[
      Flatten@UnitStep[dat - MaxFilter[dat, {1, 1}]], 
      1
      ]; // AbsoluteTiming // First
idx
MatrixPlot@SparseArray[idx -> 1, Dimensions[dat]]

0.00108

{{1, 26}, {29, 1}, {30, 1}, {31, 1}, {32, 1}, {33, 1}, {34, 1}, {35, 1}, {36, 1}, {37, 1}, {38, 1}, {39, 1}, {40, 1}, {41, 1}, {42, 1}, {43, 1}, {44, 1}, {45, 1}, {46, 1}, {47, 1}, {48, 1}, {49, 1}, {50, 1}, {51, 1}, {51, 76}, {52, 1}, {53, 1}, {54, 1}, {55, 1}, {56, 1}, {57, 1}, {58, 1}, {59, 1}, {60, 1}, {61, 1}, {62, 1}, {63, 1}, {64, 1}, {65, 1}, {66, 1}, {67, 1}, {68, 1}, {69, 1}, {70, 1}, {71, 1}, {72, 1}, {73, 1}, {101, 26}}

enter image description here

This about 10 times faster than MaxDetect> But it does not distiguish between local maxima and strict local maxima. However, a second sweep over the local maxima (which is much less expensive) could filter out the strict local maxima.

A severe problem is that Table generates an unpacked array, a thing that is often very annoying. When converting to an image, it is packed automatically (one can check that, e.g., with Developer`PackedArrayQ[ImageData[Image[dat]]]). And because many functions work faster on packed arrays than on unpacked ones, this increases the performance.

A vectorized implementation that exploits the very nature of the function (and is thus not very generalizable) is the following:

nx = ny = 1000;
dat = KroneckerProduct[
     (0.1 + Cos[Subdivide[0., 2. Pi, ny]]),
     Sin[Subdivide[0., 2. Pi, nx]]
     ];

0.003691

The maxima can be found by comparing each value to the maximum of its neighbors. The latter can be done efficiently with MaxFilter:

getindex = {Quotient[#, Dimensions[dat][[1]]] + 1, Mod[#, Dimensions[dat][[2]], 1]} &;
idx = getindex /@ 
     Random`Private`PositionsOf[
      Flatten@UnitStep[dat - MaxFilter[dat, {1, 1}]], 
      1
      ]; // AbsoluteTiming // First
idx
MatrixPlot@SparseArray[idx -> 1, Dimensions[dat]]

0.00108

{{1, 26}, {29, 1}, {30, 1}, {31, 1}, {32, 1}, {33, 1}, {34, 1}, {35, 1}, {36, 1}, {37, 1}, {38, 1}, {39, 1}, {40, 1}, {41, 1}, {42, 1}, {43, 1}, {44, 1}, {45, 1}, {46, 1}, {47, 1}, {48, 1}, {49, 1}, {50, 1}, {51, 1}, {51, 76}, {52, 1}, {53, 1}, {54, 1}, {55, 1}, {56, 1}, {57, 1}, {58, 1}, {59, 1}, {60, 1}, {61, 1}, {62, 1}, {63, 1}, {64, 1}, {65, 1}, {66, 1}, {67, 1}, {68, 1}, {69, 1}, {70, 1}, {71, 1}, {72, 1}, {73, 1}, {101, 26}}

enter image description here

This about 10 times faster than MaxDetect> But it does not distiguish between local maxima and strict local maxima. However, a second sweep over the local maxima (which is much less expensive) could filter out the strict local maxima.

added 249 characters in body
Source Link
Henrik Schumacher
  • 109.5k
  • 7
  • 186
  • 323

A severe problem is that Table generates an unpacked array, a thing that is often very annoying. When converting to an image, it is packed automatically (one can check that, e.g., with DeveloperPackedArrayQ[ImageData[Image[dat]]]`). And because many functions work faster on packed arrays than on unpacked ones, this increases the performance.

A vectorized implementation that exploits the very nature of the function (and is thus not very generalizable) is the following:

nx = ny = 1000;
dat = KroneckerProduct[
     (0.1 + Cos[Subdivide[0., 2. Pi, ny]]),
     Sin[Subdivide[0., 2. Pi, nx]]
     ];

0.003691

The maxima can be found by comparing each value to the maximum of its neighbors. The latter can be done efficiently with MaxFilter:

getindex = {Quotient[#, Dimensions[dat][[1]]] + 1, Mod[#, Dimensions[dat][[2]], 1]} &;
idx = getindex /@ 
     Random`Private`PositionsOf[
      Flatten@UnitStep[dat - MaxFilter[dat, {1, 1}]], 
      1
      ]; // AbsoluteTiming // First
idx
MatrixPlot@SparseArray[idx -> 1, Dimensions[dat]]

0.00108

{{1, 26}, {29, 1}, {30, 1}, {31, 1}, {32, 1}, {33, 1}, {34, 1}, {35, 1}, {36, 1}, {37, 1}, {38, 1}, {39, 1}, {40, 1}, {41, 1}, {42, 1}, {43, 1}, {44, 1}, {45, 1}, {46, 1}, {47, 1}, {48, 1}, {49, 1}, {50, 1}, {51, 1}, {51, 76}, {52, 1}, {53, 1}, {54, 1}, {55, 1}, {56, 1}, {57, 1}, {58, 1}, {59, 1}, {60, 1}, {61, 1}, {62, 1}, {63, 1}, {64, 1}, {65, 1}, {66, 1}, {67, 1}, {68, 1}, {69, 1}, {70, 1}, {71, 1}, {72, 1}, {73, 1}, {101, 26}}

enter image description here

This about 10 times faster than MaxDetect> But it does not distiguish between local maxima and strict local maxima. However, a second sweep over the local maxima (which is much less expensive) could filter out the strict local maxima.

A severe problem is that Table generates an unpacked array, a thing that is often very annoying.

A vectorized implementation that exploits the very nature of the function (and is thus not very generalizable) is the following:

nx = ny = 1000;
dat = KroneckerProduct[
     (0.1 + Cos[Subdivide[0., 2. Pi, ny]]),
     Sin[Subdivide[0., 2. Pi, nx]]
     ];

0.003691

The maxima can be found by comparing each value to the maximum of its neighbors. The latter can be done efficiently with MaxFilter:

getindex = {Quotient[#, Dimensions[dat][[1]]] + 1, Mod[#, Dimensions[dat][[2]], 1]} &;
idx = getindex /@ 
     Random`Private`PositionsOf[
      Flatten@UnitStep[dat - MaxFilter[dat, {1, 1}]], 
      1
      ]; // AbsoluteTiming // First
idx
MatrixPlot@SparseArray[idx -> 1, Dimensions[dat]]

0.00108

{{1, 26}, {29, 1}, {30, 1}, {31, 1}, {32, 1}, {33, 1}, {34, 1}, {35, 1}, {36, 1}, {37, 1}, {38, 1}, {39, 1}, {40, 1}, {41, 1}, {42, 1}, {43, 1}, {44, 1}, {45, 1}, {46, 1}, {47, 1}, {48, 1}, {49, 1}, {50, 1}, {51, 1}, {51, 76}, {52, 1}, {53, 1}, {54, 1}, {55, 1}, {56, 1}, {57, 1}, {58, 1}, {59, 1}, {60, 1}, {61, 1}, {62, 1}, {63, 1}, {64, 1}, {65, 1}, {66, 1}, {67, 1}, {68, 1}, {69, 1}, {70, 1}, {71, 1}, {72, 1}, {73, 1}, {101, 26}}

enter image description here

This about 10 times faster than MaxDetect> But it does not distiguish between local maxima and strict local maxima. However, a second sweep over the local maxima (which is much less expensive) could filter out the strict local maxima.

A severe problem is that Table generates an unpacked array, a thing that is often very annoying. When converting to an image, it is packed automatically (one can check that, e.g., with DeveloperPackedArrayQ[ImageData[Image[dat]]]`). And because many functions work faster on packed arrays than on unpacked ones, this increases the performance.

A vectorized implementation that exploits the very nature of the function (and is thus not very generalizable) is the following:

nx = ny = 1000;
dat = KroneckerProduct[
     (0.1 + Cos[Subdivide[0., 2. Pi, ny]]),
     Sin[Subdivide[0., 2. Pi, nx]]
     ];

0.003691

The maxima can be found by comparing each value to the maximum of its neighbors. The latter can be done efficiently with MaxFilter:

getindex = {Quotient[#, Dimensions[dat][[1]]] + 1, Mod[#, Dimensions[dat][[2]], 1]} &;
idx = getindex /@ 
     Random`Private`PositionsOf[
      Flatten@UnitStep[dat - MaxFilter[dat, {1, 1}]], 
      1
      ]; // AbsoluteTiming // First
idx
MatrixPlot@SparseArray[idx -> 1, Dimensions[dat]]

0.00108

{{1, 26}, {29, 1}, {30, 1}, {31, 1}, {32, 1}, {33, 1}, {34, 1}, {35, 1}, {36, 1}, {37, 1}, {38, 1}, {39, 1}, {40, 1}, {41, 1}, {42, 1}, {43, 1}, {44, 1}, {45, 1}, {46, 1}, {47, 1}, {48, 1}, {49, 1}, {50, 1}, {51, 1}, {51, 76}, {52, 1}, {53, 1}, {54, 1}, {55, 1}, {56, 1}, {57, 1}, {58, 1}, {59, 1}, {60, 1}, {61, 1}, {62, 1}, {63, 1}, {64, 1}, {65, 1}, {66, 1}, {67, 1}, {68, 1}, {69, 1}, {70, 1}, {71, 1}, {72, 1}, {73, 1}, {101, 26}}

enter image description here

This about 10 times faster than MaxDetect> But it does not distiguish between local maxima and strict local maxima. However, a second sweep over the local maxima (which is much less expensive) could filter out the strict local maxima.

Post Undeleted by Henrik Schumacher
added 594 characters in body
Source Link
Henrik Schumacher
  • 109.5k
  • 7
  • 186
  • 323
Loading
Post Deleted by Henrik Schumacher
Source Link
Henrik Schumacher
  • 109.5k
  • 7
  • 186
  • 323
Loading