Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Tickets/dm 8108 #32

Merged
merged 2 commits into from Apr 26, 2017
Merged

Tickets/dm 8108 #32

merged 2 commits into from Apr 26, 2017

Conversation

natelust
Copy link
Contributor

No description provided.

Copy link
Contributor

@fred3m fred3m left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As a whole I like the changes to the API a lot. I think that the right amount of functionality has been moved to SpanSets to make them very useful objects, and I can think of a lot of places in my code that things will be greatly simplified. Great job Nate!

The main comments I have on this PR are regarding the way certain SpanSet methods return a copy of the original SpanSet as opposed to updating the object in place. This could result in unexpected behavior if a variable s is set to Footprint.spans while sometime later Footprint.spans is updated by a union or clippedTo method, which results in s no longer pointing to Footprint.spans. This is the major disadvantage to making spans a property of Footprint as opposed to having Footprint inherit from SpanSet and adding a few new methods.

I'm also a little curious as to why you changed all of the pointers (PTR(det::Span)) to geom::Span.

spans = src.getFootprint().spans
for child in kids:
spans = spans.union(child.getFootprint().spans)
src.getFootprint().setSpans(spans)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I like the old behavior better in this case, so I'm curious why it was changed. It seems more useful to have SpanSets.union update the SpanSet (spans in this case) in place with (potentially) a list of SpanSets, eliminating the need to execute src.getFootprint().setSpans(spans). Then an afwDetection.union function to take the union of multiple SpanSets without modifying any of them.

foot.setSpans(afwGeom.SpanSet(newSpans))
foot.removeOrphanPeaks()


Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm surprised that clipTo and clipToNonzero are not included in the SpanSet API. Removing empty spans seems like an important feature that is useful outside the deblender, even if it has only been used in this one place in the stack so far.

It's also curious that a working C++ function has been replaced by one in python that will run much slower, especially considering how many Spans will be iterated over to deblend an entire image. Even if there is a good reason to keep this functionality out of afw, I still think this should live in deblendUtils.cc.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Clipped to is a method on a SpanSet. I will evaluate if clipToNonzero should be moved to a different location, which may or may not happen as part of this ticket. I am not sure how I would feel about this being a method on a SpanSet as it really also only makes sense in the context of a specific image and not something geometric, but I could be persuaded one way or the other.
In relation to your speed question, I tweaked the routine to be even faster than the old c++ equivalent.

padim = maskedImage.Factory(tbb)
afwDet.copyWithinFootprintMaskedImage(fpcopy, maskedImage, padim)
fpcopy.spans.clippedTo(maskedImage.getBBox()).copyMaskedImage(maskedImage, padim)

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As a whole I like the API changes in this block, including the implementation of dilate and removeOrphanPeaks. But it seems like SpanSet.clippedTo should modify the SpanSet in place as opposed to requiring Footprint.spans to point to a new object.

return (*sp1 < *sp2);
static bool span_compare(geom::Span const & sp1,
geom::Span const & sp2) {
return (sp1 < sp2);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there a reason this was changed from a pointer? I'm just thinking of very large blends where a span could be a few hundred pixels across. There doesn't seem to be a reason to copy the spans as opposed to pointing to them.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There is no copy being done, it is simply being passed by reference now instead of my pointer. Same effect with less *

foot->getSpans()->setImage(*dist, static_cast<dtype>(1));
++i;
}
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would it be better to use an ordinary for loop as opposed to a range based for loop, since you still need i?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't know in what sense you mean better. From a code efficiency standpoint, it will almost certainly compile out to the same thing. If you mean from a readability standpoint, maybe? If it were a standard for loop it would just move the lines with i in them into the line that declares the loop, and you would then either need to have an iterator object to deference, or use the [] syntax with the vector all over the place. I don't think there is a clear winner, and I preferred how this looked, rather than having a complicated for line. It would be nice if c++ supported enumerations in the range based for loop. Unfortunately we will need to wait until c++ 17 for that I think.

if (strayfoot[i]) {
strayfoot[i]->setSpans(std::make_shared<geom::SpanSet>(straySpans[i]));
}
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this can be moved into the next for loop.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

good catch. I was too focused on fixing the above loop, I didn't look at what was below

const SpanList spans = foot.getSpans();
assert(foot.isNormalized());
auto sfoot = std::make_shared<det::Footprint>();
sfoot->setPeakSchema(foot.getPeaks().getSchema());
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This seems to come up a lot. Why can't the Footprint be initialized with a Schema anymore?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It can, but only if it is also initialized with a SpanSet at the same time. Which I could have done with an empty SpanSet, I am not sure why I didn't, probably because this seemed more readable [make an empty Footprint, set the schema]. The desire was to keep down the number of constructors, but one that only takes a schema may be worth looking into, I will make a note.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I will note that in general this probably will not be an issue in the future as you would do things differently. I was trying to shoehorn the new code in as exactly as I could into the old pattern

tmpSpans.push_back(geom::Span(fy, cx + dxlo, cx + dxhi));
} else {
tmpSpans.push_back(geom::Span(fy, cx + dxhi, cx + dxlo));
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I must be missing something, why is this extra if..else block needed? Line 1129 checks if dxlo<=dxhi, so why would cx+dxlo<=cx+dxhi give a different result?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The old code had: sfoot->addSpan(fy, cx + dxlo, cx + dxhi); in it. addSpans had a check on which was lower and would swap the arguments if they were entered wrong (essentially the same if statements moved here) I was trying to ensure that the behavior of addSpans stayed exactly the same. cx is a signed int, so theoretically it could be negative (a wierd xy0 for the image). This could cause what is lower and higher to flip (though now that I think about it longer, only the the case for cx -dx(lo/hi)). This check could probably be removed for the addition, but I would want someone to verify thatI am right in that, as it would be removing a check we used to have.

tmpSpans.push_back(geom::Span(by, cx - dxlo, cx - dxhi));
} else {
tmpSpans.push_back(geom::Span(by, cx - dxhi, cx - dxlo));
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

See my previous comment for why this if..else block also seems unnecessary to me.

std::shared_ptr<geom::SpanSet> edgeSpans = sfoot->getSpans()->findEdgePixels();
std::vector<geom::Span> tmpSpans;
for (geom::SpanSet::const_iterator ss = edgeSpans->begin();
ss != edgeSpans->end(); ++ss) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this the indentation that clang-format created? It seems a bit hard to read to me.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

no, I don't know what happened there, it didn't even need to be on a different line, changed now

@natelust natelust merged commit e9c9c7e into master Apr 26, 2017
@ktlim ktlim deleted the tickets/DM-8108 branch August 25, 2018 05:49
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
2 participants