Skip to content

Commit 7c1834f

Browse files
authored
Merge pull request #636 from astrorama/fix/modfit_bad_coords
Fix infinite value in model fitting
2 parents e35f96d + e95897c commit 7c1834f

6 files changed

Lines changed: 99 additions & 80 deletions

File tree

SEFramework/src/lib/CoordinateSystem/WCS.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -255,8 +255,8 @@ ImageCoordinate WCS::worldToImage(WorldCoordinate world_coordinate) const {
255255
int ret_val = wcss2p(&wcs_copy, 1, 1, wc_array, &phi, &theta, ic_array, pc_array, &status);
256256
if (ret_val != WCSERR_SUCCESS) {
257257
logger.warn() << "Bad worldToImage from RA/Dec: " << wc_array[0] << "/" << wc_array[1];
258-
pc_array[0] = -std::numeric_limits<double>::infinity();
259-
pc_array[1] = -std::numeric_limits<double>::infinity();
258+
pc_array[0] = -10000000.0;
259+
pc_array[1] = -10000000.0;
260260
}
261261
wcsfree(&wcs_copy);
262262
return ImageCoordinate(pc_array[0] - 1, pc_array[1] - 1); // -1 as fits standard coordinates start at 1

SEImplementation/SEImplementation/Plugin/MeasurementFrameRectangle/MeasurementFrameRectangle.h

Lines changed: 19 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -39,51 +39,45 @@ class MeasurementFrameRectangle: public Property {
3939
virtual ~MeasurementFrameRectangle() = default;
4040

4141
explicit MeasurementFrameRectangle(bool bad_projection):
42-
m_min_coord{-1, -1}, m_max_coord{-1, -1}, m_min_coord_image{-1, -1},
43-
m_max_coord_image{-1, -1}, m_bad_projection{bad_projection} {}
42+
m_min_coord{-1, -1}, m_max_coord{-1, -1}, m_bad_projection{bad_projection}, m_is_valid{false} {}
4443

45-
MeasurementFrameRectangle(PixelCoordinate min_coord, PixelCoordinate max_coord,
46-
ImageCoordinate min_coord_image, ImageCoordinate max_coord_image):
47-
m_min_coord(min_coord), m_max_coord(max_coord),
48-
m_min_coord_image(min_coord_image), m_max_coord_image(max_coord_image), m_bad_projection{false} {
44+
MeasurementFrameRectangle(ImageCoordinate min_coord, ImageCoordinate max_coord):
45+
m_min_coord(min_coord), m_max_coord(max_coord), m_bad_projection{false}, m_is_valid{true} {
4946
assert(min_coord.m_x <= max_coord.m_x && min_coord.m_y <= max_coord.m_y);
50-
assert(min_coord_image.m_x <= max_coord_image.m_x && min_coord_image.m_y <= max_coord_image.m_y);
5147
}
5248

53-
PixelCoordinate getTopLeft() const {
54-
assert(m_max_coord.m_x >= 0);
49+
ImageCoordinate getTopLeft() const {
5550
return m_min_coord;
5651
}
5752

58-
PixelCoordinate getBottomRight() const {
59-
assert(m_max_coord.m_x >= 0);
53+
ImageCoordinate getBottomRight() const {
6054
return m_max_coord;
6155
}
6256

63-
int getWidth() const {
64-
if (m_max_coord.m_x < 0)
65-
return 0;
66-
return m_max_coord.m_x - m_min_coord.m_x + 1;
57+
double getWidth() const {
58+
return m_max_coord.m_x - m_min_coord.m_x;
6759
}
6860

69-
int getHeight() const {
70-
if (m_max_coord.m_x < 0)
71-
return 0;
72-
return m_max_coord.m_y - m_min_coord.m_y + 1;
61+
double getHeight() const {
62+
return m_max_coord.m_y - m_min_coord.m_y;
7363
}
7464

75-
std::tuple<ImageCoordinate, ImageCoordinate> getImageRect() const {
76-
return std::make_tuple(m_min_coord_image, m_max_coord_image);
65+
bool isBadProjection() const {
66+
return m_bad_projection;
7767
}
7868

79-
bool badProjection() const {
80-
return m_bad_projection;
69+
bool isValid() const {
70+
return m_is_valid;
71+
}
72+
73+
bool isEmpty() const {
74+
return getWidth() <= 0.0 || getHeight() <= 0.0;
8175
}
8276

8377
private:
84-
PixelCoordinate m_min_coord, m_max_coord;
85-
ImageCoordinate m_min_coord_image, m_max_coord_image;
78+
ImageCoordinate m_min_coord, m_max_coord;
8679
bool m_bad_projection;
80+
bool m_is_valid;
8781
};
8882

8983
} // end SourceXtractor

SEImplementation/src/lib/Plugin/FlexibleModelFitting/FlexibleModelFittingIterativeTask.cpp

Lines changed: 21 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -74,8 +74,13 @@ FlexibleModelFittingIterativeTask::~FlexibleModelFittingIterativeTask() {
7474
}
7575

7676
PixelRectangle FlexibleModelFittingIterativeTask::getUnclippedFittingRect(SourceInterface& source, int frame_index) const {
77-
ImageCoordinate min_coord, max_coord;
78-
std::tie(min_coord, max_coord) = source.getProperty<MeasurementFrameRectangle>(frame_index).getImageRect();
77+
auto& measurement_frame_rectangle = source.getProperty<MeasurementFrameRectangle>(frame_index);
78+
if (!measurement_frame_rectangle.isValid() || measurement_frame_rectangle.isEmpty()) {
79+
return PixelRectangle();
80+
}
81+
82+
ImageCoordinate min_coord = measurement_frame_rectangle.getTopLeft();
83+
ImageCoordinate max_coord = measurement_frame_rectangle.getBottomRight();
7984

8085
if (m_window_type == WindowType::ROTATED_ELLIPSE) {
8186
auto ellipse = getFittingEllipse(source, frame_index);
@@ -85,7 +90,7 @@ PixelRectangle FlexibleModelFittingIterativeTask::getUnclippedFittingRect(Source
8590
return getEllipseRect(ellipse);
8691
}
8792

88-
if (max_coord.m_x - min_coord.m_x <= 0 || max_coord.m_y - min_coord.m_y <= 0) {
93+
if ((max_coord.m_x - min_coord.m_x <= 0.0) || (max_coord.m_y - min_coord.m_y <= 0.0)) {
8994
return PixelRectangle();
9095
} else {
9196
auto min = min_coord;
@@ -126,15 +131,19 @@ PixelRectangle FlexibleModelFittingIterativeTask::getUnclippedFittingRect(Source
126131
max.m_y = min.m_y + size;
127132
}
128133

129-
auto min_pc = PixelCoordinate(static_cast<int>(min.m_x + 0.5), static_cast<int>(min.m_y + 0.5));
130-
auto max_pc = PixelCoordinate(static_cast<int>(max.m_x + 0.5), static_cast<int>(max.m_y + 0.5));
134+
auto min_pc = PixelCoordinate(static_cast<int>(min.m_x), static_cast<int>(min.m_y));
135+
auto max_pc = PixelCoordinate(static_cast<int>(max.m_x), static_cast<int>(max.m_y));
131136

132137
return PixelRectangle(min_pc, max_pc);
133138
}
134139
}
135140

136141
PixelRectangle FlexibleModelFittingIterativeTask::clipFittingRect(PixelRectangle fitting_rect,
137142
SourceInterface& source, int frame_index) const {
143+
if (fitting_rect.getWidth() <= 0 || fitting_rect.getHeight() <= 0) {
144+
return PixelRectangle();
145+
}
146+
138147
const auto& frame_info = source.getProperty<MeasurementFrameInfo>(frame_index);
139148

140149
auto min = fitting_rect.getTopLeft();
@@ -522,15 +531,15 @@ std::shared_ptr<VectorImage<SeFloat>> FlexibleModelFittingIterativeTask::createD
522531
auto deblend_image = VectorImage<SeFloat>::create(rect.getWidth(), rect.getHeight());
523532
index = 0;
524533
for (auto& src : group) {
525-
if (index != source_index) {
526-
auto frame_model = createFrameModel(src, pixel_scale, parameter_manager, frame, rect);
527-
auto final_stamp = frame_model.getImage();
534+
if (index != source_index && isFrameValid(src, frame->getFrameNb())) {
535+
auto frame_model = createFrameModel(src, pixel_scale, parameter_manager, frame, rect);
536+
auto final_stamp = frame_model.getImage();
528537

529-
for (int y = 0; y < final_stamp->getHeight(); ++y) {
530-
for (int x = 0; x < final_stamp->getWidth(); ++x) {
531-
deblend_image->at(x, y) += final_stamp->at(x, y);
532-
}
538+
for (int y = 0; y < final_stamp->getHeight(); ++y) {
539+
for (int x = 0; x < final_stamp->getWidth(); ++x) {
540+
deblend_image->at(x, y) += final_stamp->at(x, y);
533541
}
542+
}
534543
}
535544
index++;
536545
}

SEImplementation/src/lib/Plugin/MeasurementFrameRectangle/MeasurementFrameRectangleTask.cpp

Lines changed: 31 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -44,9 +44,14 @@ void MeasurementFrameRectangleTask::computeProperties(SourceInterface& source) c
4444
auto width = detection_group_stamp.getWidth();
4545
auto height = detection_group_stamp.getHeight();
4646

47+
if (width <= 0 || height <= 0) {
48+
// No valid stamp, set the property to an empty rectangle
49+
source.setIndexedProperty<MeasurementFrameRectangle>(m_instance, false);
50+
return;
51+
}
52+
4753
// Transform the 4 corner coordinates from detection image
4854
ImageCoordinate coord1, coord2, coord3, coord4;
49-
bool bad_coordinates = false;
5055
try {
5156
coord1 = measurement_frame_coordinates->worldToImage(
5257
detection_frame_coordinates->imageToWorld(ImageCoordinate(stamp_top_left.m_x, stamp_top_left.m_y)));
@@ -58,7 +63,8 @@ void MeasurementFrameRectangleTask::computeProperties(SourceInterface& source) c
5863
detection_frame_coordinates->imageToWorld(ImageCoordinate(stamp_top_left.m_x, stamp_top_left.m_y + height)));
5964
}
6065
catch (const InvalidCoordinatesException&) {
61-
bad_coordinates = true;
66+
source.setIndexedProperty<MeasurementFrameRectangle>(m_instance, true);
67+
return;
6268
}
6369

6470
// Determine the min/max coordinates
@@ -67,27 +73,32 @@ void MeasurementFrameRectangleTask::computeProperties(SourceInterface& source) c
6773
auto max_x = std::max(coord1.m_x, std::max(coord2.m_x, std::max(coord3.m_x, coord4.m_x)));
6874
auto max_y = std::max(coord1.m_y, std::max(coord2.m_y, std::max(coord3.m_y, coord4.m_y)));
6975

70-
PixelCoordinate min_coord, max_coord;
71-
min_coord.m_x = int(min_x);
72-
min_coord.m_y = int(min_y);
73-
max_coord.m_x = int(max_x) + 1;
74-
max_coord.m_y = int(max_y) + 1;
75-
76-
// The full boundaries may lie outside of the frame
77-
if (bad_coordinates || max_coord.m_x < 0 || max_coord.m_y < 0 ||
78-
min_coord.m_x >= measurement_frame_info.getWidth() || min_coord.m_y >= measurement_frame_info.getHeight()) {
79-
source.setIndexedProperty<MeasurementFrameRectangle>(m_instance, bad_coordinates);
76+
// test for nans
77+
if (std::isnan(min_x) || std::isnan(min_y) || std::isnan(max_x) || std::isnan(max_y)) {
78+
source.setIndexedProperty<MeasurementFrameRectangle>(m_instance, true);
79+
return;
8080
}
81+
82+
// test for infinite values
83+
if (std::isinf(min_x) || std::isinf(min_y) || std::isinf(max_x) || std::isinf(max_y)) {
84+
source.setIndexedProperty<MeasurementFrameRectangle>(m_instance, true);
85+
return;
86+
}
87+
8188
// Clip the coordinates to fit the available image
82-
else {
83-
min_coord.m_x = std::max(0, min_coord.m_x);
84-
min_coord.m_y = std::max(0, min_coord.m_y);
85-
max_coord.m_x = std::min(measurement_frame_info.getWidth() - 1, max_coord.m_x);
86-
max_coord.m_y = std::min(measurement_frame_info.getHeight() - 1, max_coord.m_y);
87-
88-
source.setIndexedProperty<MeasurementFrameRectangle>(
89-
m_instance, min_coord, max_coord, ImageCoordinate(min_x, min_y), ImageCoordinate(max_x, max_y));
89+
min_x = std::max(0.0, min_x);
90+
min_y = std::max(0.0, min_y);
91+
max_x = std::min(static_cast<double>(measurement_frame_info.getWidth() - 1), max_x);
92+
max_y = std::min(static_cast<double>(measurement_frame_info.getHeight() - 1), max_y);
93+
94+
if (max_x <= min_x || max_y <= min_y) {
95+
// No valid rectangle, set the property to an empty rectangle
96+
source.setIndexedProperty<MeasurementFrameRectangle>(m_instance, false);
97+
return;
9098
}
99+
100+
source.setIndexedProperty<MeasurementFrameRectangle>(
101+
m_instance, ImageCoordinate(min_x, min_y), ImageCoordinate(max_x, max_y));
91102
}
92103

93104
} // SEImplementation namespace

SEImplementation/src/lib/Plugin/MeasurementFrameRectangle/MeasurementFrameRectangleTaskNoDetect.cpp

Lines changed: 25 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,6 @@ void MeasurementFrameRectangleTaskNoDetect::computeProperties(SourceInterface& s
3838
const auto& world_centroid = source.getProperty<WorldCentroid>();
3939
const auto& assoc_mode = source.getProperty<AssocMode>();
4040

41-
bool bad_coordinates = false;
4241
ImageCoordinate coord1, coord2, coord3, coord4;
4342
try {
4443
auto w = assoc_mode.getRefFramePixelWidth();
@@ -55,7 +54,8 @@ void MeasurementFrameRectangleTaskNoDetect::computeProperties(SourceInterface& s
5554
reference_frame_coordinates->imageToWorld(ImageCoordinate(c.m_x + w, c.m_y + h)));
5655
}
5756
catch (const InvalidCoordinatesException&) {
58-
bad_coordinates = true;
57+
source.setIndexedProperty<MeasurementFrameRectangle>(m_instance, true);
58+
return;
5959
}
6060

6161
// Determine the min/max coordinates
@@ -64,27 +64,32 @@ void MeasurementFrameRectangleTaskNoDetect::computeProperties(SourceInterface& s
6464
auto max_x = std::max(coord1.m_x, std::max(coord2.m_x, std::max(coord3.m_x, coord4.m_x)));
6565
auto max_y = std::max(coord1.m_y, std::max(coord2.m_y, std::max(coord3.m_y, coord4.m_y)));
6666

67-
PixelCoordinate min_coord, max_coord;
68-
min_coord.m_x = int(min_x);
69-
min_coord.m_y = int(min_y);
70-
max_coord.m_x = int(max_x) + 1;
71-
max_coord.m_y = int(max_y) + 1;
72-
73-
// The full boundaries may lie outside of the frame
74-
if (bad_coordinates || max_coord.m_x < 0 || max_coord.m_y < 0 ||
75-
min_coord.m_x >= measurement_frame_info.getWidth() || min_coord.m_y >= measurement_frame_info.getHeight()) {
76-
source.setIndexedProperty<MeasurementFrameRectangle>(m_instance, bad_coordinates);
67+
// test for nans
68+
if (std::isnan(min_x) || std::isnan(min_y) || std::isnan(max_x) || std::isnan(max_y)) {
69+
source.setIndexedProperty<MeasurementFrameRectangle>(m_instance, true);
70+
return;
7771
}
72+
73+
// test for infinite values
74+
if (std::isinf(min_x) || std::isinf(min_y) || std::isinf(max_x) || std::isinf(max_y)) {
75+
source.setIndexedProperty<MeasurementFrameRectangle>(m_instance, true);
76+
return;
77+
}
78+
7879
// Clip the coordinates to fit the available image
79-
else {
80-
min_coord.m_x = std::max(0, min_coord.m_x);
81-
min_coord.m_y = std::max(0, min_coord.m_y);
82-
max_coord.m_x = std::min(measurement_frame_info.getWidth() - 1, max_coord.m_x);
83-
max_coord.m_y = std::min(measurement_frame_info.getHeight() - 1, max_coord.m_y);
84-
85-
source.setIndexedProperty<MeasurementFrameRectangle>(
86-
m_instance, min_coord, max_coord, ImageCoordinate(min_x, min_y), ImageCoordinate(max_x, max_y));
80+
min_x = std::max(0.0, min_x);
81+
min_y = std::max(0.0, min_y);
82+
max_x = std::min(static_cast<double>(measurement_frame_info.getWidth() - 1), max_x);
83+
max_y = std::min(static_cast<double>(measurement_frame_info.getHeight() - 1), max_y);
84+
85+
if (max_x <= min_x || max_y <= min_y) {
86+
// No valid rectangle, set the property to an empty rectangle
87+
source.setIndexedProperty<MeasurementFrameRectangle>(m_instance, false);
88+
return;
8789
}
90+
91+
source.setIndexedProperty<MeasurementFrameRectangle>(
92+
m_instance, ImageCoordinate(min_x, min_y), ImageCoordinate(max_x, max_y));
8893
}
8994

9095
} // SEImplementation namespace

SEImplementation/src/lib/Plugin/SourceFlags/SourceFlagsSourceTask.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ void SourceFlagsSourceTask::computeProperties(SourceInterface &source) const {
3939
source_flag |= Flags::SATURATED * source.getProperty<SaturateFlag>(instance).getSaturateFlag();
4040
source_flag |= Flags::BOUNDARY * source.getProperty<BoundaryFlag>(instance).getBoundaryFlag();
4141
source_flag |= Flags::BLENDED * source.getProperty<BlendedFlag>().getBlendedFlag();
42-
if (source.getProperty<MeasurementFrameRectangle>(instance).badProjection()) {
42+
if (source.getProperty<MeasurementFrameRectangle>(instance).isBadProjection()) {
4343
source_flag |= Flags::BAD_PROJECTION;
4444
}
4545
}

0 commit comments

Comments
 (0)