[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: |
|
||||||||
| 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: |
| 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. 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. |