Why doesn't NumericType implement Comparable?

Just wondering: how come RealType, a subtype of NumericType, implements Comparable, but ```NumericType`` itself doesn’t?

If NumericType implemented Comparable then NumericComposite would also have to implement Comparable: is there any reason not to?

@axtimwalde @StephanPreibisch @tpietzsch

1 Like

What is greater: ARGB(0, 0, 0, 255) or ARGB(0, 255, 0, 0)? There is no one-dimensional order in multi-dimensional types, e.g. ComplexType is also not Comparable for the same reason.

1 Like

Fair. But for NumericComposite, I’d expect that e.g. if any of the elements is greater than any of the given elements, then it’s greater. One could also consider the vector length. In this case, ARGB(0, 0, 0, 255) or ARGB(0, 255, 0, 0) have the same length. I understand these are opinionated choices and non-obvious and therefore likely best avoided.

A related question then: is there a sensible way to collapse a NumericComposite? E.g. if you express a 3D volume as a 2D of vectors, how can one easily apply the max to each composite pixel to do a max projection?

With a converter:

maxProjection = Converters.convert(
  composite,
  (a, b) -> {
    double max = -Double.MAX_VALUE;
    for (int i = 0; i < length; ++i) {
      final double value = a.get(i).getRealDouble();
      if (value > max)
        max = value;
    }
    b.setReal(max);
  },
  new DoubleType());

(plusminus some typos…)

Also, NumericComposite is a Composite of NumericType, i.e. each scalar is already not Comparable. I believe you mean RealComposite, but I also agree that even there the assumption that the Composite spans an Euclidean space where amplitude is the dimension for Comparable is a bit too narrow. A multi-dimensional Comparable with multi-dimensional return type would be better, but we do not currently have this. On the other hand, I believe you can do what you want with the above Converter or something similar. I wrote it for a concrete DoubleType but that is not required because RealComposite.get(int) returns RealType which is Comparable, at that level you could do it.

Thanks, it is clear. I was hoping, though, for an elegant approach where NumericType or RealType math can be applied for the reduction, a là ```RealType::add``, so that I never have to write a consumer anonymous class or a loop.

With such an approach, Views.collapse would be the map, and Converters.convert??? would be the reduce, to e.g. trivially max project a 3D stack into a 2D image.

As a side note, the Comparable javadoc states that “It is strongly recommended (though not required) that natural orderings be consistent with equals.”. For example, using vector length would mean that
ARGB(0, 0, 0, 255) and ARGB(0, 255, 0, 0) are considered equal by compareTo but not by equals. In my opinion, that would be too “surprising”. I think an explicit LengthComparator or something like that would be preferable for that.

2 Likes

Thanks @tpietzsch, that makes sense.

For the ARGB example, the opinionated view could be to e.g. acquire a split view of the channels with Converters.argbChannels, then Views.collapse it to a NumericComposite, then do the max projection or whatever operation, now that each channel has been conceptually transformed to merely an entry into each pixel’s vector.

Just for completeness: Views.collapseReal(...) collapses to a RealComposite which would be the right thing to do for Converters.argbChannels.