[PIPE2D-689] Vector version of DetectorMap.findPoint fails Created: 22/Dec/20  Updated: 08/Mar/22  Resolved: 02/Feb/21

Status: Done
Project: DRP 2-D Pipeline
Component/s: None
Affects Version/s: None
Fix Version/s: None

Type: Story Priority: Normal
Reporter: rhl Assignee: price
Resolution: Done Votes: 0
Labels: None
Remaining Estimate: Not Specified
Time Spent: Not Specified
Original Estimate: Not Specified

Issue Links:
Relates
relates to DAMD-130 Change wavelength columns from 32-bit... Done
Story Points: 3
Sprint: 2DDRP-2021 A
Reviewers: hassan

 Description   

Using the weekly,

dataId = dict(visit=47, arm="r", spectrograph=1)
pfsArm = butler.get("pfsArm", dataId)
detMap = butler.get("detectorMap", dataId)

detMap.findPoint(pfsArm.fiberId[0], pfsArm.wavelength[0][0])    # succeeds
detMap.findPoint(pfsArm.fiberId[0], pfsArm.wavelength[0][0:2])  # fails

generates the error:

TypeError: findPoint(): incompatible function arguments. The following argument types are supported:
    1. (self: pfs.drp.stella.DetectorMap.DetectorMap, fiberId: int, wavelength: float) -> lsst.geom.Point2D
    2. (self: pfs.drp.stella.DetectorMap.DetectorMap, fiberId: int, wavelength: ndarray::Array<float, 1, 1>) -> ndarray::Array<float, 2, 1>
    3. (self: pfs.drp.stella.DetectorMap.DetectorMap, fiberId: ndarray::Array<int, 1, 1>, wavelength: ndarray::Array<float, 1, 1>) -> ndarray::Array<float, 2, 1>

Invoked with: <pfs.drp.stella.SplinedDetectorMap.SplinedDetectorMap object at 0x2b3b8add2928>, 2, array([620.33496, 620.4214 ], dtype=float32)


 Comments   
Comment by price [ 22/Dec/20 ]

I think this is working as expected.

The solution is:

>>> detMap.findPoint(int(pfsArm.fiberId[0]), pfsArm.wavelength[0][0:2].astype(np.float32))
array([[          nan,           nan],
       [4.0264922e+03, 1.0000000e+00]], dtype=float32)

There were two problems:
1. pfsArm.fiberId[0] is an np.uint64, which isn't recognised as an `int`.
2. pfsArm.wavelength[0][0:2].dtype is dtype('>f4'), which isn't recognised as np.float32.

Comment by rhl [ 22/Dec/20 ]

I'm reopening this.  If you can't pass the arrays in a PfsArm to a DetectorMap then something in the API needs to be fixed.

 

Comment by rhl [ 24/Dec/20 ]

And I don't think that the cast to int is necessary.

Comment by price [ 05/Jan/21 ]

OK, then I think we need to do a couple of things:

1. Convert arrays on read (byte swap, cast) in datamodel.
2. Ensure all pybind APIs in drp_stella use consistent types.

An alternative would be to add more pybind overloads for float and double arrays, but that doesn't catch byte-swapping, and I'm concerned that the number of combinations might make maintenance difficult. I guess it might be possible to add automatic translations between float and double arrays in the pybind layer, but that goes against the ndarray package's philosophy of only doing explicit conversions (because of the potential for silent memory and CPU inefficiency).

I propose to use double for all arrays (pixel position, flux, wavelength and associated errors) instead of single-precision float. float would give us ~6 decimal digits of precision, and I'm afraid that that's getting a little tight for wavelengths (dispersion is 0.04 nm/pixel for m, I believe our centroids are good to around a 1/100 of a pixel, so we need a precision of 0.04/100 = 4e-4; precision of {float}} for values between between 2^9 and 2^10 is 2^(9-23) ~ 6e-5, which is getting a bit close for comfort). We could mix and match by using double for wavelengths and float for fluxes, but I think a desire for consistency and the fact that arrays default to double in numpy encourages us to always use double for arrays.

Comment by price [ 30/Jan/21 ]

Implemented the above. detMap.findPoint(pfsArm.fiberId[0], pfsArm.wavelength[0][0:2]) now works out-of-the-box.

Comment by price [ 02/Feb/21 ]

Merged to master.

Generated at Sat Feb 10 15:56:32 JST 2024 using Jira 8.3.4#803005-sha1:1f96e09b3c60279a408a2ae47be3c745f571388b.