SharedCalculation_of_HPF_FiberPositions.ipynbOpen in CoCalc
Initial version of Scenario 2

How to calculate HPF's fiber positions on HET

-Incase of any doubt, drop me an email (Joe Ninan)

# Library of functions we will use later in this calculation.
# Execute this cell in the beginning, by pressing Shift+Enter

import numpy as np
from scipy.optimize import leastsq
######################################################
### Calculation of transformation matrix
#### Constrained transformation matrix where scaling in x and y is same.

def ScaleMatrix(Scale):
    ScaleMatrix = np.matrix([[Scale,0,0],
                             [0,Scale,0],
                             [0,0,1]])
    return ScaleMatrix

def TranslateMatrix(TranX,TranY):
    TranslateMatrix = np.matrix([[1,0,TranX],
                                 [0,1,TranY],
                                 [0,0,1]])
    return TranslateMatrix

def RotMatrix(theta):
    RotMatrix = np.matrix([[np.cos(theta),-np.sin(theta),0],
                           [np.sin(theta),np.cos(theta),0],
                           [0,0,1]])
    return RotMatrix

def ReflectYMatrix():
    ReflectYMatrix = np.matrix([[1,0,0],
                                [0,-1,0],
                                [0,0,1]])
    return ReflectYMatrix

def ReflectXMatrix():
    ReflectXMatrix = np.matrix([[-1,0,0],
                                [0,1,0],
                                [0,0,1]])
    return ReflectXMatrix

###################################
# Error functions to fit the pramaeters of transformation matrix

# Function to fit the Translate*Rotate*Scale transformation
def error_funcTRS(p,OldCoords,NewCoords):
    """ Error function to fit the coordinate where parameters are p=[Scale,theta,TranX,TranY]
    which will transform OldCoords to NewCoords
    Fitted transformation is TRS: Translate*Rotate*Scale """
    RS = np.matmul(RotMatrix(p[1]),ScaleMatrix(p[0]))
    TRS = np.matmul(TranslateMatrix(p[2],p[3]),RS)
    TransformCoords = np.matmul(TRS,OldCoords)
    return np.array(TransformCoords.flatten() - NewCoords.flatten())[0]

# Function to fit the Translate*Rotate*Scale*ParityFlipY transformation
def error_funcTRSP(p,OldCoords,NewCoords):
    """ Error function to fit the coordinate where parameters are p=[Scale,theta,TranX,TranY]
    which will transform OldCoords to NewCoords
    Fitted transformation is TRSP: Translate*Rotate*Scale*ParityFlipY"""
    SP = np.matmul(ScaleMatrix(p[0]),ReflectYMatrix())
    RSP = np.matmul(RotMatrix(p[1]),SP)
    TRSP = np.matmul(TranslateMatrix(p[2],p[3]),RSP)
    TransformCoords = np.matmul(TRSP,OldCoords)
    return np.array(TransformCoords.flatten() - NewCoords.flatten())[0]

Scenario 1: Everything from scratch

When: This is when you suspect the HPF's fiber puck inserted in the HET's focal plane has moved with respect to BIB, LRS2 etc..

Things to do:

  1. Measure the cCFB and sCFB positions in in ACAM
  2. Calculate all of the HPF fiber positions in the fplane.txt file
  3. Calculate the offsets in X & Y coordinates for moving from cCFB to science fibers.
  4. Calculate the ACAM pixel coordinates for all the fibers.

Step 1: Measure the cCFB and sCFB positions in ACAM

  1. Use the previous estimate of the ACAM coordaintes to bring the star inside cCFB
  2. Guide the telescope using a guide probe and offset it to bring the star to the center of cCFB. (You cannot guide on cCFB unless the orientation is constrained later)
  3. Once the star is at the center of cCFB of HPF_ACQM, and guiding smoothly on the guide probe. Insert the ACAM and wait for it to stabilise before taking exposure.
  4. Take a few exposures, and then retract the ACAM. Make sure star is still at the center of cCFB
  5. Repeate the procedure of inserting the ACAM, taking images, retreive,reinsert..
  6. Average the centriods to get a good accurate ACAM pixel position of cCFB.
  7. Do the same for sCFB and get its pixel coordinates on ACAM.

Step 2: Calculate all of the HPF fiber positions in the fplane.txt file

  1. Get the latest ACAM pixel positions of BIB, LRS2R, and LRS2B from https://het.as.utexas.edu:8001/trac/WFUCommissioning/wiki/NightOperations/Commissioning/Results
  2. Get the fplane.tx coordinates of BIB, LRS2R, and LRS2B from fplane.txt file
  3. Fits a linear transformation matrix to transform ACAM pixel coordinates to fplane.txt coordinates
import matplotlib.pyplot as plt
#HPF fiber head fiber positions in telecentric lens images
CentroidCoords = {'cir2': (273.45298734501097, 270.7847529387491),
                  'cir3': (336.04330942778, 222.2177477751225),
                  'cir1': (222.25408901265263, 333.5099840115954),
                  'cir6': (793.7851982362772, 688.9766017329656),
                  'cir4': (680.1842052725259, 800.6668579582121),
                  'cir5': (744.1546788398894, 752.2047326301424),
                  'oct4': (774.8631863343908, 305.7149638147935),
                  'oct2': (298.5672272093679, 773.1045874545131),
                  'oct3': (717.8617085355628, 248.97764755048598),
                  'cCFB': (641.7590850208674, 378.2411130588114),
                  'oct1': (241.7727067933783, 715.9757709056951),
                  'sCFB': (373.99530838383396, 644.5011001356886)}

##### Now do the calculation for ACAM coordinates
PixelCoords = np.matrix([[CentroidCoords['cCFB'][0],CentroidCoords['sCFB'][0]],
                         [CentroidCoords['cCFB'][1],CentroidCoords['sCFB'][1]],
                         [1,1]])

ACAMcoords = np.matrix([[148.0,219.0],
                        [254.8,179.5],
                        [1,1]])

p0 = [0.1,1,1,1]
pTRS,iter = leastsq(error_funcTRS,p0,args=(PixelCoords,ACAMcoords))
print(pTRS)

RS = np.matmul(RotMatrix(pTRS[1]),ScaleMatrix(pTRS[0]))
TRS = np.matmul(TranslateMatrix(pTRS[2],pTRS[3]),RS)
print(TRS)

# We chose TRS instead of TRSP since TRS matches the BIB and IMHP orientaiton
ACAMCoordTRS = {}
for fiber in CentroidCoords:
    ACAMCoordTRS[fiber] = np.matmul(TRS,np.matrix([[CentroidCoords[fiber][0]],[CentroidCoords[fiber][1]],[1]]))
    print('{0} : {1:.1f} {2:.1f}'.format(fiber,ACAMCoordTRS[fiber][0,0],ACAMCoordTRS[fiber][1,0]))
    plt.plot(ACAMCoordTRS[fiber][0,0],ACAMCoordTRS[fiber][1,0],'o')
    plt.text(ACAMCoordTRS[fiber][0,0],ACAMCoordTRS[fiber][1,0],fiber+ ' ({0:.1f},{1:.1f})'.format(ACAMCoordTRS[fiber][0,0],ACAMCoordTRS[fiber][1,0]))
plt.xlabel('X (pixel)')
plt.ylabel('Y (pixel)')
plt.title('ACAM pixels')
plt.show()



### ACAM to fplane.txt transformation
# We shall use BIB, LRS2R, LRS2B to fit the transform.

ACAMbilrlbCoords = np.matrix([[461.16,744.5,741.8],
                              [404.63,581.5,213.3],
                              [1,1,1]])

SkybilrlbCoords = np.matrix([[3.3,49.8,-49.8],
                             [-73.2,-151.3,-148.7],
                             [1,1,1]])

p0 = [0.1,1,1,1]
pTRS,iter = leastsq(error_funcTRS,p0,args=(ACAMbilrlbCoords,SkybilrlbCoords))
print(pTRS)

RS = np.matmul(RotMatrix(pTRS[1]),ScaleMatrix(pTRS[0]))
TRS = np.matmul(TranslateMatrix(pTRS[2],pTRS[3]),RS)
print(TRS)

#  Transformation of all the coordinates to fplane.txt Sky coords from ACAM pixels  
print ('TRS: BIB, LRS2R, LRS2B in fplane:', np.matmul(TRS, ACAMbilrlbCoords))
# TRS was found to match correctly
print ('TRS: cCFB, sCFB in fplane:', np.matmul(TRS, ACAMcoords))
###############################################
#  Transformation of all the coordinates

# TRS matches the BIB and IMHP orientaiton
for fiber in ACAMCoordTRS:
    SkyCoordTRS = np.matmul(TRS,np.matrix([[ACAMCoordTRS[fiber][0,0]],[ACAMCoordTRS[fiber][1,0]],[1]]))
    print('{0} : {1:.1f} {2:.1f}'.format(fiber,SkyCoordTRS[0,0],SkyCoordTRS[1,0]))
    plt.plot(SkyCoordTRS[0,0],SkyCoordTRS[1,0],'o')
    plt.text(SkyCoordTRS[0,0],SkyCoordTRS[1,0],fiber+ ' ({0:.1f},{1:.1f})'.format(SkyCoordTRS[0,0],SkyCoordTRS[1,0]))
plt.title('fplane.txt')
plt.xlabel('X (arcsec)')
plt.ylabel('Y (arcsec)')
plt.show()


[ -2.74075066e-01 -3.21991544e-02 3.27136387e+02 3.52750187e+02] [[ -2.73932999e-01 -8.82346050e-03 3.27136387e+02] [ 8.82346050e-03 -2.73932999e-01 3.52750187e+02] [ 0.00000000e+00 0.00000000e+00 1.00000000e+00]] oct4 : 112.2 275.8 cir6 : 103.6 171.0 cir3 : 233.1 294.8 cCFB : 148.0 254.8 oct3 : 128.3 290.9 cir5 : 116.7 153.3 cir4 : 133.7 139.4 oct2 : 238.5 143.6 oct1 : 254.6 158.8 sCFB : 219.0 179.5 cir2 : 249.8 281.0 cir1 : 263.3 263.4
[ -0.27143363 1.5526728 -104.21083054 53.73980234] [[ -4.91906601e-03 2.71389056e-01 -1.04210831e+02] [ -2.71389056e-01 -4.91906601e-03 5.37398023e+01] [ 0.00000000e+00 0.00000000e+00 1.00000000e+00]] TRS: BIB, LRS2R, LRS2B in fplane: [[ 3.33284685 49.93966109 -49.97250798] [ -73.40437657 -151.16978701 -148.62583645] [ 1. 1. 1. ]] TRS: cCFB, sCFB in fplane: [[-35.78892075 -56.57377038] [ 12.32084398 -6.57737335] [ 1. 1. ]] cir4 : -67.0 16.8 cir6 : -58.3 24.8 oct4 : -29.9 21.9 cCFB : -35.8 12.3 oct3 : -25.9 17.5 cir5 : -63.2 21.3 oct2 : -66.4 -11.7 cir3 : -25.3 -11.0 oct1 : -62.4 -16.1 sCFB : -56.6 -6.6 cir2 : -29.2 -15.4 cir1 : -34.0 -19.0

Scenario 2: Update the ACAM coordinates after an IHMP take down and IFU install

When: This is when there is only an overall shift to correct after IHMP take down and IFU re-install

Things to do:

  1. Get the old ACAM pixels positions of BIB, LRS2R, and LRS2B
  2. Get the latest ACAM pixel positions of BIB, LRS2R, and LRS2B from https://het.as.utexas.edu:8001/trac/WFUCommissioning/wiki/NightOperations/Commissioning/Results
  3. Fit a linear transformation from the old pixel coordinates to new pixel coordinates
  4. Apply the transformation to old HPF acam pixel positions to obtain new pixel coordinates
# Step 1: 
# Old BIB, LRS2R, LRS2B pixel coordinates in ACAM  (Date: October 2017)

#OldACAM_b_lr_lb_Coords = np.matrix([[452.6, 744.5, 741.8],
#                                    [402.6, 581.5, 213.3],
#                                    [1,     1,     1]])

OldACAM_b_lr_lb_Coords = np.matrix([[461.16, 744.5, 741.8],
                                    [404.63, 581.5, 213.3],
                                    [1,     1,     1]])


# Step 2:
# New BIB, LRS2R, LRS2B pixel coordinates in ACAM  (Date: 27th January 2018)

NewACAM_b_lr_lb_Coords = np.matrix([[458.41, 742.79, 740.75],
                                    [398.65, 578.99, 210.23],
                                    [1,     1,     1]])


# Step 3:
# Fit TRS linear transformtion
p0 = [1,0,0,0]
pTRS,iter = leastsq(error_funcTRS,p0,args=(OldACAM_b_lr_lb_Coords,NewACAM_b_lr_lb_Coords))
print('Scale = {0},theta ={1},TranX ={2},TranY={3}'.format(*pTRS))

print('Transformation matrix')
RS = np.matmul(RotMatrix(pTRS[1]),ScaleMatrix(pTRS[0]))
TRS = np.matmul(TranslateMatrix(pTRS[2],pTRS[3]),RS)
print(TRS)
print('Residue/Error in the fitted transform (PredictedNewCoords - NewCoords). This is a consistence check')
print(np.matmul(TRS,OldACAM_b_lr_lb_Coords)-NewACAM_b_lr_lb_Coords)

# Step 4
# Apply the transformation to old coordinates to obtain new ACAM coordinates

#(Date: October 2017)
OldACAM_cCFB_sCFB_HRsci_HEsci = np.matrix([[148.0,219.0,128.3,112.2],
                                           [254.8,179.5,290.9,275.8],
                                           [1,     1,    1,    1]])

print('New Corrdinates of Central CFB, Side CFB, HR  and HE science fibers')
print(np.matmul(TRS,OldACAM_cCFB_sCFB_HRsci_HEsci))

Scale = 1.002868101230477,theta =0.006012141442238229,TranX =-1.2761448921104395,TranY=-8.906754443102646 Transformation matrix [[ 1.00284998e+00 -6.02934855e-03 -1.27614489e+00] [ 6.02934855e-03 1.00284998e+00 -8.90675444e+00] [ 0.00000000e+00 0.00000000e+00 1.00000000e+00]] Residue/Error in the fitted transform (PredictedNewCoords - NewCoords). This is a consistence check [[ 0.34849498 -0.95040355 0.60190765] [ 1.00692594 -0.2506431 -0.7562837 ] [ 0. 0. 0. ]] New Corrdinates of Central CFB, Side CFB, HR and HE science fibers [[ 145.60937362 217.2657319 125.6355696 109.58072814] [ 247.51176316 172.42524368 283.59586915 268.35576199] [ 1. 1. 1. 1. ]]