Usage of UnitVector in D0: Based on code in lxr browser as of 8/3/00: A search for the identifier comes up with 107 files. Of these, 60 are in the ZOOM files themselves and can thus be ignored. In the remaining 47 files, the word UnitVector comes up 95 times (some files are copies of others). I also examined code in the latest test release I could find: t01.08.00 muo_hits MDTGeometryHit.cpp unchanged in use of UV new MDTGeometryHit_t.cpp no change needed PDTGeometryHit.cpp unchanged in use of UV new PDTGeometryHit_t.cpp no change needed components GeometryXform.cpp unchanged in use of UV muo_segment seems to be gone; muo_segmentreco does not contain any UV visualign seems to be gone muo_data An approach to changing the code -------------------------------- Just in general, if we eliminate UnitVector (UV) from the package, I might suggest typedefing UnitVector as SpaceVector, as a sort of code-level documentation fo the assertion that "this guy has length 1", and leave the word UnitVector where it appears. Of course, now that UV would not be guaranteed to have length 1, one has to make good on the promise that these do have length 1. For illustration purposes, if code would need to change I will assume this approach would be used; but one could equally well (once the changes are made) replace UnitVector with SpaceVector everywhere in the new code if having a "UnitVector" class without the guarantee of unit length is worrisome. Efficiency issue ---------------- Due to not using UnitVectorin other places.... ARE WE SURE THAT WHAT COMES IN IS A UV? OF COURSE NOT, there is converter from SV to UV. SO we keep having to normalize... 3-component constructor of UV is already not efficient... --- SmtResidual --- Efficiency: constructor taking directions along the measurement and the track requires two normalizations; along just the measurement that constructor requires only one. The apparent normalizatoin when forming the angle to get a Rotation is spurious since if you just use d.angle(X_HAT), the normalization implied by that is balanced by not having to do UnitVector dHat (d). The normalizations represent a small fraction of the other work needed. --- Segment --- Efficiency: constructor from UnitVector Requires normalization. suggestion of making the changes, but leaving the name UV. I will put in the class whcih right now is just typedef but eventually will at least have unit() method return *this. alternative: private inheritance; keep UV class in ZOOM area, unless CLHEP wants it. --- Geometry Xform --- The constructor [109] has a const UV uaxis initialized off axis. Since axis is a SV, this would have to be initialized off axis.unit(). 109 const UnitVector uaxis(axis); --> const UnitVector uaxis(axis.unit()); getAxis() [262] returns a UV computed from 3 components which DO NOT necessarily make a unit vector without normalization. Since it returns a UV, we would have to take care of this: 274 return UnitVector(e1,e2,e3); %% --> return UnitVector(e1,e2,e3).unit(); UnitVector (now SV) has a 3-component constructor. In the header, no change necessary. UnitVector is mentioned as the return type of getAxis; that can change to SV if desired. Efficiency: No change (constructing UV (SV) is same as SV.unit()) --- ScanCoordShifter --- This forms a Unitvector from theGeometryXform->get_axis(). Assuming the get_axis() method of GeometryXform has been vetted, no change necessary. --- GeometryAddressManager --- Line 136 is UnitVector uv=gxf.get_axis(); Assuming the get_axis() method of GeometryXform has been vetted, no change necessary. --- BaseAligner --- 58-59 UnitVector uv0=trans_rot0.empty() ? UnitVector(): UnitVector (Float8(trans_rot0[3]),Float8(trans_rot0[4]), Float8(trans_rot0[5])); %% ----> UnitVector uv0=trans_rot0.empty() ? Z_HAT: UnitVector (Float8(trans_rot0[3]),Float8(trans_rot0[4]), Float8(trans_rot0[5])).unit(); 58-59 UnitVector uv=trans_rot.empty() ? UnitVector(): UnitVector (Float8(trans_rot[3]),Float8(trans_rot[4]), Float8(trans_rot[5])); %% ----> UnitVector uv=trans_rot.empty() ? Z_HAT: UnitVector (Float8(trans_rot[3]),Float8(trans_rot[4]), Float8(trans_rot[5])).unit(); The SV default constructor is different than that for UV, thus the change to Z_HAT. I prefer to use Z_HAT but you could use UnitVector(0,0,1). Efficiency: No change (constructing UV (SV) is same as SV.unit()) --- SmtResidual --- Two signatures rely on a UnitVector. Whith the above changes this reliance is relieved. So in the header, no changes needed. In the implementation, there is a bit of a headache, in that u and v are assumed to be unit vectors and used in multiple places. The consequence is that it would be best to normalize these once and for all. (Yes, we can do better than that in terms of efficiency, but I have no wish to risk introducing more math - with some small chance of mistake - into the code.) 30-32 SmtResidual::SmtResidual(const int detectorID, const SpaceVector s0, const UnitVector u, const Float8 sigmaS, const SpaceVector t0, const UnitVector v, const Float8 sigmaT) ----> SmtResidual::SmtResidual(const int detectorID, const SpaceVector s0, const UnitVector uu, const Float8 sigmaS, const SpaceVector t0, const UnitVector vu, const Float8 sigmaT) insert at line 50 UnitVector u = uu.unit(); UnitVector v = vv.unit(); 71-72 UnitVector dHat(d); Float8 angle = acos(X_HAT.dot(dHat)); ----> UnitVector dHat(d.unit()); Float8 angle = acos(X_HAT.dot(dHat)); or simply, ----> Float8 angle = d.angle(X_HAT); 81-83 SmtResidual::SmtResidual(const int detectorID, const SpaceVector t0, const UnitVector v, const Float8 sigmaT, const SpaceVector s0, const MatrixD hiterror) ----> SmtResidual::SmtResidual(const int detectorID, const SpaceVector t0, const UnitVector vv, const Float8 sigmaT, const SpaceVector s0, const MatrixD hiterror) insert at line 86 UnitVector v = vv.unit(); and by the way, dividing by v.dot(v) is a waste of time. Efficiency: constructor taking directions along the measurement and the track requires two normalizations; along just the measurement that constructor requires only one. The apparent normalizatoin when forming the angle to get a Rotation is spurious since if you just use d.angle(X_HAT), the normalization implied by that is balanced by not having to do UnitVector dHat (d). The normalizations represent a small fraction of the other work needed. --- Segment --- Constructor (point, direction) takes a UV as direction. If UV is the same as SV, a user can pass a non-unit vector here. Since the direction stored as _vx, _vy, _vz of a Segment constructed via this constructor might be assumed to be of unit length, this needs to be vetted. 25-27 _vx = direction.x(); _vy = direction.y(); _vz = direction.z(); ----> UnitVector unitd = direction.unit(); _vx = unitd.x(); _vy = unitd.y(); _vz = unitd.z(); This might not be strictly necessary, as notice the next constructor takes three arbitrary cartesian coordinates to use as _vx, _vy, _vz, but better safe. Header requires no change. Efficiency: constructor from UnitVector Requires normalization. --- PDTGeometryHit --- Header has UV getWireDirection(). No change needed in header but we must ensure that this method returns a vector of length 1. The implementation of GetVwireDirection has a minor bug: If MuoGeometer::get_instance()->getPosition fails, an ELerror is issued and if this is ignored, the oreintation is zero-ed. A step later one forms a unit vector from that orientation; that will fail so a ZMexception will be ZMthrown by the UV constructor. Fix this: substitute for lines 75-77 return Z_HAT; Now assuming you did get an orientation, of course we need to normalize it: 80 return UnitVector(orientation[0], orientation[1], orientation[2]); --> return UnitVector(orientation[0], orientation[1], orientation[2]).unit(); Other usages in implementation (line 58, 85) need no changes; they just use getWireDirection(). Efficiency: No change (constructing UV (SV) is same as SV.unit()) --- MDTGeometryHit --- Exactly the same issues as for PDTGeometryHit: Header needs no change; implementation has same minor bug (should return Z_HAT around line 94); and same return issue: 97 return UnitVector(orientation[0], orientation[1], orientation[2]); --> return UnitVector(orientation[0], orientation[1], orientation[2]).unit(); In the test class, no change needed: A UV is initialized from 3 cartesian coordinates, but they are 0,1,0 which is fine. Efficiency: No change (constructing UV (SV) is same as SV.unit()) --- MDTHitAdaptor --- The same issues as for MDTGeometryHit, except that the minor bug is different: Now when getPosition fails, getWireOrientation() tries constructing the UnitVector from three leftover numbers on the stack (orientation). But this will be fixed when the author vets to use ErrorLog anyway. Header needs no change; and same return issue: 69 return UnitVector(orientation[0], orientation[1], orientation[2]); --> return UnitVector(orientation[0], orientation[1], orientation[2]).unit(); Efficiency: No change (constructing UV (SV) is same as SV.unit()) --- PDTHitAdaptor --- The same issues as for MDTHitAdaptor: Header needs no change; and same return issue: 65 return UnitVector(orientation[0], orientation[1], orientation[2]); --> return UnitVector(orientation[0], orientation[1], orientation[2]).unit(); Efficiency: No change (constructing UV (SV) is same as SV.unit()) --- WireHitAdaptor --- From the header, looks like the same issues as per MDTHitAdaptor. But... >>> Note - I could not find the implementation for this header. <<< --- MDTHitRep --- The usage is UnitVector wiredirection = _hit.getWireDirection(); where _hit is an MDTGeometryHit. Since getWireDirection() will return a vector of length 1, no changes are needed. --- PDTHitRep --- The usage is UnitVector wiredirection = _hit.getWireDirection(); where _hit is a PDTGeometryHit. Since getWireDirection() will return a vector of length 1, no changes are needed. --- TPV --- >>> Note - I could not find the implementation for this header. <<< --- UnitVector.h --- This could need some thought, as the class goes away. Easiest might be to substitute: 29 #pragma classalias zmpv::UnitVector UnitVector; --> #pragma classalias zmpv::SpaceVector UnitVector; Or, more likely, this entire file disappears. --- FPSDetectorDisplay --- Only uses UnitVector via getAxisVector call. So assuming GeometryXform has been vetted, no change needed here. --- Toyz -- This uses Unitvector in two places: 515 UnitVector p1Hat(**ptrk1); --> UnitVector p1Hat(**ptrk1.unit()); 529 UnitVector p2Hat(**ptrk2); --> UnitVector p2Hat(**ptrk2.unit()); However, this would be part of ZOOM's task anyway since we ought to take responsibility for keeping Toyz in shape. --- smtGeomDisplay --- Usage on line 249 is OIK unchanged since Rotation::axis() returns a unit vector. Usage on line 431 is OIK unchanged since Rotation::axis() returns a unit vector. Usage on line 544 is OIK unchanged since Rotation::axis() returns a unit vector. --- visualign_t --- Uses the (theta, phi) constructor for UnitVector 3 times. Each 35,37,39 UnitVector u1(90, DEGREES, 75, DEGREES); UnitVector u2(90, DEGREES, 105, DEGREES); UnitVector v(0, DEGREES, 90, DEGREES); -------> UnitVector u1(1.0, 90, DEGREES, 75, DEGREES); UnitVector u2(1.0, 90, DEGREES, 105, DEGREES); UnitVector v(1.0, 0, DEGREES, 90, DEGREES); Efficency: Insignificant change (3 multiplies by the 1.0 argument). --- MuoHitDisplay --- This defines a local UnitVector named unit, which is always set by lines like [198] unit = mdthit.getWireOrientation(); Since those methods return normalized vectors, no changes are needed when unit becomes a SpaceVector. --- MDTChannelAdaptor --- 81 UnitVector wireor(orientation[0], orientation[1], orientation[2]); (this is at line 82 in the version in data/, line 81 in raw/) add a line after line 82: wireor.setR(1.0); Currently, wireor IS NOT USED so naively this change is not necessary. However, I assume that the reason it is set is because future code in this routine will indeed use it, in which case for safety it had better be normalized. Efficency: Since orientation is not known to be a unit vector, the normalization would be done anyway (by UnitVector constructor in the original concept) so no efficiency change. --- twrite_pv --- This uses UnitVector purely to test whether (2,0,0) gets properly intialized to (1,0,0) and whether UnitVector outputs properly. To get identical behavior, 50 t->uv1 = UnitVector (2, 0, 0); --> t->uv1 = UnitVector (2, 0, 0).unit(); --- tzmtypes --- This only takes sizeof (UnitVector) and would remain unchanged.