Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
58 commits
Select commit Hold shift + click to select a range
5dd2da6
Update CMakeLists.txt
marcschefer May 22, 2025
519ad8f
Update README.md
marcschefer May 22, 2025
9bf1525
Optimize VariablePsfStack using KdTree
marcschefer Jun 27, 2025
da6f69c
benchmark code cleanup
marcschefer Jun 30, 2025
8f1e8a4
update .gitignore
marcschefer Jun 30, 2025
658644b
changed fitting window calculation to use doubles
marcschefer Aug 8, 2025
0bbbf71
fix regression
marcschefer Aug 12, 2025
1990c86
fix helgrind problems
marcschefer Aug 29, 2025
661b05c
Includes a nan and inf test that works with fast-math
mkuemmel Sep 5, 2025
cf0f9c8
Pushed some feedback to debug
mkuemmel Sep 20, 2025
e9c7541
fix regression with exceptions in threads
marcschefer Sep 26, 2025
a092f36
moved isnan function to SEUtils, small fixes
marcschefer Sep 26, 2025
6aea35f
print filename of PSF that doesn't load
marcschefer Sep 26, 2025
13905a5
fix regression
marcschefer Sep 29, 2025
8f86e9c
added option to specify max nb of simultaneous files
marcschefer Oct 31, 2025
a497f42
Merge pull request #620 from astrorama/feature/psfstack_optimization
marcschefer Dec 3, 2025
97528f8
Merge pull request #621 from astrorama/fix/assoc_pixel_size_as_double
marcschefer Dec 3, 2025
af6610e
Merge pull request #624 from astrorama/fix/helgrind
marcschefer Dec 3, 2025
16f3e29
Merge pull request #626 from astrorama/feature/solve_nan
marcschefer Dec 3, 2025
6d7ce09
Merge branch 'develop' into feature/max_files_option
marcschefer Dec 3, 2025
03cd776
remove leftover debug print
marcschefer Dec 3, 2025
42b0bd5
Merge branch 'feature/max_files_option' of github.com:astrorama/Sourc…
marcschefer Dec 3, 2025
e35f96d
Merge pull request #628 from astrorama/feature/max_files_option
marcschefer Dec 3, 2025
22da3e6
fix Dependent parameters not removing observers in destructor
marcschefer Feb 20, 2026
0e2d8dd
avoid recreating the model fitting parameter object multiple times
marcschefer Feb 20, 2026
bcb7228
Revert "Changed fitting window calculation to use doubles"
marcschefer Mar 6, 2026
4164ff2
Merge remote-tracking branch 'origin/revert-621-fix/assoc_pixel_size_…
marcschefer Mar 6, 2026
634e461
propagate bad coords flag
marcschefer Mar 18, 2026
74f5e86
change pearson's formula constant for mode estimation
marcschefer Mar 19, 2026
f7bcc14
remove int coordinates completely
marcschefer Mar 20, 2026
5c8fde5
Add isValid() to MeasurementFrameRectangle
marcschefer Mar 20, 2026
89d0174
stricter checks
marcschefer Mar 27, 2026
588bb42
remove FindBoostPython.cmake, it should not be needed anymore
marcschefer Mar 31, 2026
c7559ec
actually delete the file
marcschefer Mar 31, 2026
4955ca1
changing MeasurementFrameRectangle.h
marcschefer Apr 17, 2026
3061074
fix litmus test failing
marcschefer Apr 17, 2026
a7eeab8
add framevalid check when building deblend image
marcschefer Apr 23, 2026
8149c6d
more infinite tests
marcschefer Apr 23, 2026
2ee3de3
remove infiite in case of error
marcschefer Apr 23, 2026
e95897c
remove commented out code
marcschefer Apr 24, 2026
984c21b
Reapply "Changed fitting window calculation to use doubles"
marcschefer Apr 30, 2026
7c1834f
Merge pull request #636 from astrorama/fix/modfit_bad_coords
marcschefer Apr 30, 2026
8b4b655
merge develop
marcschefer Apr 30, 2026
e88c6e7
Merge pull request #639 from astrorama/feature/remove_boost_python
marcschefer Jun 3, 2026
c2b1d44
Update CMakeLists.txt
marcschefer Jun 3, 2026
0df24e5
bump cmake version
marcschefer Jun 5, 2026
32994bf
Merge branch 'develop' into feature/pearson35b
marcschefer Jun 5, 2026
4896489
add pearson factor parameter
marcschefer Jun 5, 2026
1b38e57
Merge pull request #641 from astrorama/feature/bump_verions
marcschefer Jun 9, 2026
c575579
Merge branch 'develop' into feature/pearson35b
marcschefer Jun 9, 2026
a7f090c
fix: pass the right parameter
marcschefer Jun 9, 2026
8e60b60
make sure the mode stays 100% identical when using the default value,…
marcschefer Jun 9, 2026
7444e2c
Merge pull request #638 from astrorama/feature/pearson35b
marcschefer Jun 9, 2026
82663c3
Merge branch 'develop' into feature/model_fitting_param_optimization
marcschefer Jun 11, 2026
7c55238
Merge pull request #633 from astrorama/feature/model_fitting_param_op…
marcschefer Jun 11, 2026
3659a3a
Use Alexandria version 2.33.0 Elements 6.3.7
marcschefer Jun 19, 2026
149ccb8
Merge pull request #643 from astrorama/feature/alexandria233
marcschefer Jun 19, 2026
17643d9
Update README.md
marcschefer Jul 7, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -11,3 +11,4 @@ __pycache__
/packages
/doc/build/
/build/
.vscode
4 changes: 2 additions & 2 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
CMAKE_MINIMUM_REQUIRED(VERSION 2.8.5)
CMAKE_MINIMUM_REQUIRED(VERSION 3.5)

#---------------------------------------------------------------
# Load macros and functions for Elements-based projects
find_package(ElementsProject)
#---------------------------------------------------------------

# Declare project name and version
elements_project(SourceXtractorPlusPlus 1.0.3 USE Alexandria 2.32.0 DESCRIPTION "SourceXtractor++, the next generation SExtractor")
elements_project(SourceXtractorPlusPlus 1.1.0 USE Alexandria 2.33.0 DESCRIPTION "SourceXtractor++, the next generation SExtractor")
13 changes: 11 additions & 2 deletions ModelFitting/ModelFitting/Parameters/DependentParameter.h
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,11 @@ class DependentParameter: public BasicParameter {
//m_get_value_hook = std::bind(&DependentParameter::getValueHook, this);
}

virtual ~DependentParameter() = default;
virtual ~DependentParameter() {
for (auto& parameter_observer : m_parameter_observers) {
std::get<0>(parameter_observer)->removeObserver(std::get<1>(parameter_observer));
}
}

double getValue() const override {
if (!this->isObserved()) {
Expand Down Expand Up @@ -118,13 +122,17 @@ class DependentParameter: public BasicParameter {

template<typename Param>
void addParameterObserver(int, Param& param) {
param->addObserver([this](double){
auto id = param->addObserver([this](double){
// Do not bother updating live if there are no observers
if (this->isObserved()) {
this->update((*m_params)[0]->getValue());
}
});

m_parameter_observers.emplace_back(param, id);
}

std::vector<std::tuple<std::shared_ptr<BasicParameter>, size_t>> m_parameter_observers;
};

template<typename ... Parameters>
Expand All @@ -133,6 +141,7 @@ std::shared_ptr<DependentParameter<Parameters...>> createDependentParameter(
return std::make_shared<DependentParameter<Parameters...>>(value_calculator, parameters...);
}


}

#endif /* MODELFITTING_DEPENDENTPARAMETER_H */
46 changes: 4 additions & 42 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,13 +17,13 @@ Documentation: https://astrorama.github.io/SourceXtractorPlusPlus/
SourceXtractor++ is available on [Anaconda Cloud for Linux and MacOSX](https://anaconda.org/astrorama/sourcextractor)

```bash
conda install -c conda-forge -c astrorama sourcextractor==1.0.2
conda install -c conda-forge -c astrorama sourcextractor==1.1.0
```

We would recommend, however, to install it into its own environment.

```bash
conda create -n sourcex -c astrorama -c conda-forge sourcextractor==1.0.2
conda create -n sourcex -c astrorama -c conda-forge sourcextractor==1.1.0
conda activate sourcex
```

Expand All @@ -36,47 +36,9 @@ conda activate sourcex-dev

We recommend always using an explicit version number as there is no guarantee that `conda` will install the latest version otherwise.

## Fedora
Fedora and RPM

SourceXtractor++ is shipped directly in Fedora. It can be installed simply as follows:

```bash
sudo dnf install sourcextractor++
```

[We also build our own RPMs as part of our CI setup](http://repository.astro.unige.ch/euclid/)
They can be installed adding a `.repo` file under `/etc/yum.repos.d` with the following content:

```ini
# Stable and tagged versions
# This is the recommended way to install sourcextractor++
[Astrorama]
name=Astrorama
baseurl=http://repository.astro.unige.ch/euclid/fedora/$releasever/$basearch
enabled=1
gpgcheck=0

# Enable this to get the stable (untagged) version
[Astrorama-Stable]
name=Astrorama Stable
baseurl=http://repository.astro.unige.ch/euclid/devel/stable/fedora/$releasever/$basearch
enabled=0
gpgcheck=0

# Enable this to get the development version
# Use with care!
[Astrorama-Develop]
name=Astrorama Develop
baseurl=http://repository.astro.unige.ch/euclid/devel/develop/fedora/$releasever/$basearch
enabled=0
gpgcheck=0
```

And install with

```bash
dnf install SourceXtractorPlusPlus
```
RPM packages are temporarily not available due to technical problems.

## Test Data Set

Expand Down
4 changes: 2 additions & 2 deletions SEBenchmarks/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
CMAKE_MINIMUM_REQUIRED(VERSION 2.8.5)

#===============================================================================
# Load elements_subdir macro here
# Examples:
Expand Down Expand Up @@ -56,6 +54,8 @@ elements_add_executable(BenchRendering src/program/BenchRendering.cpp
LINK_LIBRARIES SEFramework SEImplementation ${Boost_LIBRARIES})
elements_add_executable(BenchBackgroundModel src/program/BenchBackgroundModel.cpp
LINK_LIBRARIES SEFramework SEImplementation ${Boost_LIBRARIES})
elements_add_executable(BenchVariablePsfStack src/program/BenchVariablePsfStack.cpp
LINK_LIBRARIES SEFramework ${Boost_LIBRARIES})

#===============================================================================
# Declare the Boost tests here
Expand Down
136 changes: 136 additions & 0 deletions SEBenchmarks/src/program/BenchVariablePsfStack.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,136 @@
/** Copyright © 2019-2025 Université de Genève, LMU Munich - Faculty of Physics, IAP-CNRS/Sorbonne Université
*
* This library is free software; you can redistribute it and/or modify it under
* the terms of the GNU Lesser General Public License as published by the Free
* Software Foundation; either version 3.0 of the License, or (at your option)
* any later version.
*
* This library is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this library; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/

/**
* @file src/program/BenchVariablePsfStack.cpp
* @date 06/27/25
* @author marc schefer
*/

#include <map>
#include <string>
#include <random>

#include <boost/program_options.hpp>
#include <boost/timer/timer.hpp>
#include "ElementsKernel/ProgramHeaders.h"
#include "ElementsKernel/Real.h"
#include "SEFramework/Psf/VariablePsfStack.h"

namespace po = boost::program_options;
namespace timer = boost::timer;
using namespace SourceXtractor;

static Elements::Logging logger = Elements::Logging::getLogger("BenchVariablePsfStack");

class BenchVariablePsfStack : public Elements::Program {
private:
std::default_random_engine random_generator;
std::uniform_real_distribution<double> random_dist{0.0, 1000.0};

public:

po::options_description defineSpecificProgramOptions() override {
po::options_description options{};
options.add_options()
("iterations", po::value<int>()->default_value(100000), "Number of getPsf calls to benchmark")
("measures", po::value<int>()->default_value(3), "Number of timing measurements to take")
("fits-file", po::value<std::string>()->default_value(""), "FITS file containing PSF stack");
return options;
}

Elements::ExitCode mainMethod(std::map<std::string, po::variable_value> &args) override {

auto iterations = args["iterations"].as<int>();
auto measures = args["measures"].as<int>();
auto fits_file = args["fits-file"].as<std::string>();

logger.info() << "Benchmarking VariablePsfStack::getPsf() with " << iterations << " iterations";
logger.info() << "Taking " << measures << " timing measurements";

// Initialize VariablePsfStack with FITS file if provided, otherwise nullptr
std::shared_ptr<CCfits::FITS> fitsPtr = nullptr;
if (!fits_file.empty()) {
try {
fitsPtr = std::make_shared<CCfits::FITS>(fits_file);
logger.info() << "Using FITS file: " << fits_file;
} catch (const std::exception& e) {
logger.error() << "Failed to load FITS file '" << fits_file << "': " << e.what();
return Elements::ExitCode::DATAERR;
}
} else {
logger.error() << "No FITS file provided";
return Elements::ExitCode::USAGE;
}

try {
VariablePsfStack psfStack(fitsPtr);

logger.info() << "VariablePsfStack loaded successfully with " << psfStack.getNumberOfPsfs() << " PSFs";
logger.info() << "PSF size: " << psfStack.getWidth() << "x" << psfStack.getHeight();
logger.info() << "Pixel sampling: " << psfStack.getPixelSampling();

std::cout << "Iterations,Measurement,Time_nanoseconds" << std::endl;

for (int m = 0; m < measures; ++m) {
logger.info() << "Measurement " << (m + 1) << "/" << measures;

timer::cpu_timer timer;
timer.stop();

// Prepare test values for getPsf calls
std::vector<std::vector<double>> testValues;
testValues.reserve(iterations);

for (int i = 0; i < iterations; ++i) {
testValues.push_back({random_dist(random_generator), random_dist(random_generator)});
}

// Start timing
timer.start();

for (int i = 0; i < iterations; ++i) {
try {
auto psf = psfStack.getPsf(testValues[i]);
// Prevent compiler optimization by using the result
volatile auto width = psf->getWidth();
(void)width; // Suppress unused variable warning
} catch (const std::exception& e) {
// Expected to fail with nullptr, but we still measure the timing
// until the exception is thrown
}
}

timer.stop();

auto elapsed_ns = timer.elapsed().wall;
std::cout << iterations << "," << (m + 1) << "," << elapsed_ns << std::endl;

logger.info() << "Time for " << iterations << " calls: " << (elapsed_ns / 1e9) << " seconds";
logger.info() << "Average time per call: " << (elapsed_ns / iterations) << " nanoseconds";
}

} catch (const std::exception& e) {
logger.error() << "Error initializing VariablePsfStack: " << e.what();
return Elements::ExitCode::DATAERR;
}

return Elements::ExitCode::OK;
}
};

MAIN_FOR(BenchVariablePsfStack)
2 changes: 0 additions & 2 deletions SEFramework/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
CMAKE_MINIMUM_REQUIRED(VERSION 2.8.5)

#===============================================================================
# Load elements_subdir macro here
# Examples:
Expand Down
24 changes: 24 additions & 0 deletions SEFramework/SEFramework/CoordinateSystem/CoordinateSystem.h
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,30 @@ struct ImageCoordinate {

ImageCoordinate() : m_x(0), m_y(0) {}
ImageCoordinate(double x, double y) : m_x(x), m_y(y) {}

ImageCoordinate operator*(double scalar) const {
return ImageCoordinate(m_x * scalar, m_y * scalar);
}

ImageCoordinate operator+(const ImageCoordinate& other) const {
return ImageCoordinate(m_x + other.m_x, m_y + other.m_y);
}

ImageCoordinate& operator+=(const ImageCoordinate& other) {
m_x += other.m_x;
m_y += other.m_y;
return *this;
}

ImageCoordinate operator-(const ImageCoordinate& other) const {
return ImageCoordinate(m_x - other.m_x, m_y - other.m_y);
}

ImageCoordinate& operator-=(const ImageCoordinate& other) {
m_x -= other.m_x;
m_y -= other.m_y;
return *this;
}
};

class CoordinateSystem {
Expand Down
7 changes: 5 additions & 2 deletions SEFramework/SEFramework/FITS/FitsImageSource.h
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ using Euclid::FilePool::FileHandler;
class FitsImageSource : public ImageSource, public std::enable_shared_from_this<ImageSource> {
public:

static std::shared_ptr<FileManager> getFileManager(unsigned int max_open_files = 500);

/**
* Constructor
Expand All @@ -57,14 +58,14 @@ class FitsImageSource : public ImageSource, public std::enable_shared_from_this<
*/
explicit FitsImageSource(const std::string& filename, int hdu_number = 0,
ImageTile::ImageType image_type = ImageTile::AutoType,
std::shared_ptr<FileManager> manager = FileManager::getDefault());
std::shared_ptr<FileManager> manager = getFileManager());

FitsImageSource(const std::string& filename, int width, int height,
ImageTile::ImageType image_type,
const std::shared_ptr<CoordinateSystem> coord_system = nullptr,
bool append = false,
bool empty_primary = false,
std::shared_ptr<FileManager> manager = FileManager::getDefault());
std::shared_ptr<FileManager> manager = getFileManager());

virtual ~FitsImageSource() = default;

Expand Down Expand Up @@ -137,6 +138,8 @@ class FitsImageSource : public ImageSource, public std::enable_shared_from_this<
ImageTile::ImageType m_image_type;

int m_current_layer;

static std::shared_ptr<FileManager> s_file_manager;
};

}
Expand Down
2 changes: 1 addition & 1 deletion SEFramework/SEFramework/Output/OutputRegistry.h
Original file line number Diff line number Diff line change
Expand Up @@ -169,7 +169,7 @@ class OutputRegistry {
return converter(source.getProperty<PropertyType>(i));
};
}
Euclid::Table::Row::cell_type operator()(const SourceInterface& source) {
Euclid::Table::Row::cell_type operator()(const SourceInterface& source) const {
return m_convert_func(source, index);
}
std::size_t index = 0;
Expand Down
Loading
Loading