loadsub 'StitchDeclares.scr' !StitchSubs.scr ! 01/09/97 mdc Combined all the subroutines of stitching into one file ! 06/16/97 mdc Major Mods ! 08/16/97 mdc Added Annulus Stitch, only runs on Metropro v 7.1.15 or later, ! but wont hurt. Also added error checking on the getting of IDs, ! and handle controls and attributes not available in Adv Text App. ! 08/25/97 mdc Added auto focus/tilt subroutine ! 10/08/97 mdc modified to work with new UserStitch and UserZip ! 07/17/2002 PAL Added code so there is always an error handler ! 09/26/2002 PAL Added "goto exit" commands when GET_IDS and GET_ZIP_CNTRLS complete ! with no errors. ! 10/24/2002 CHI Added checks for active x, y, or z axis. ! 02/18/2003 PAL Centralized the error handler. ! Added DO_DIALOG routine. ! Ignore error when moving stages in EXIT_STITCH ! Removed unused routines. ! Added move and get stage routine that ignore errors. ! ! +-----------------------------------------------------------------------------------------+ ! ! | Sub SETROWCOL() | ! ! | Determines the number of Rows and Columns needed for the stitch. | ! ! | Optimizes the row count, column count and overlap. | ! ! | | ! ! | In Parameters: | ! ! | g_StitchType | ! ! | g_XSize | ! ! | g_XCameraSize | ! ! | g_XIncrement | ! ! | g_YSize | ! ! | g_YCameraSize | ! ! | g_YIncrement | ! ! | g_Overlap | ! ! | | ! ! | Out Parameters: | ! ! | g_ColCount | ! ! | g_RowCount | ! ! | g_Overlap | ! ! | | ! ! | Local Variables: | ! ! | l_nTemp | ! ! | l_XOverlap | ! ! | l_YOverlap | ! ! | | ! ! | Procedures Called: | ! ! | | ! ! | Algorithm: | ! ! | 1. Initialize row and column count to 1. | ! ! | 2. Calculate the number of columns, amount of overlap and how far to move the stage | ! ! | to get to the next column. | ! ! | A. Check for X-Diminsion fitting in one column. | ! ! | B. for non X & Y Stitching... | ! ! | i. g_XSize already has an extra g_XCameraSize in it. Calculate the number | ! ! | of columns needed for a given overlap. Make sure the entire width is | ! ! | covered. | ! ! | C. for X & Y Stitching... | ! ! | i. Play with the number of columns until the amount of overlap is more | ! ! | than or equal to what the user set it to. This is the same as saying | ! ! | that the increment is less than or equal to something. | ! ! | 3. Calculate the number of rows, amount of overlap and how far to move the stage to | ! ! | get to the next column. Done the same way as columns. | ! ! | 4. Average X and Y overlaps for display purposes. | ! ! +-----------------------------------------------------------------------------------------+ ! SETROWCOL: ! ! g_XSize and g_YSize are the total dimensions in the 2 diff positions. ! the total dimension is one window larger. ! for g_ColCount and g_RowCount we need to add 1 to add the extra window ! g_ColCount = 1 g_RowCount = 1 if (g_XSize <= g_XCameraSize) then goto DOROWS ! if there is only one col if (g_StitchType <> XYStitch) then ! All types of stitching except for X & Y Stitching g_ColCount = ((g_XSize - g_XCameraSize) / g_XIncrement) + 1 l_nTemp = int(g_ColCount) if (g_ColCount > l_nTemp) then g_ColCount = l_nTemp + 1 if ((g_ColCount * g_XIncrement) < (g_XSize - g_XCameraSize)) then g_ColCount = g_ColCount + 1 else ! X & Y Stitching is done differently l_XOverlap = g_XCameraSize - g_XIncrement g_ColCount = int((g_XSize - l_XOverlap) / g_XIncrement) if (g_ColCount = 1) then g_ColCount = g_ColCount + 1 ! 2 columns, but overlap big CHKCOLOVRLP: ! determine how much to add to existing overlap g_XIncrement = g_XCameraSize * ((100 - g_Overlap) / 100) l_nTemp = ((g_XSize - l_XOverlap) - (g_ColCount * g_XIncrement)) / (g_ColCount - 1) g_XIncrement = g_XIncrement + l_nTemp ! chk for overlap >= what was set (was 10) if (g_XIncrement <= (g_XCameraSize * ((100 - g_Overlap) / 100))) then goto DOROWS ! overlap was too small re-calc g_ColCount = g_ColCount + 1 goto CHKCOLOVRLP endif DOROWS: if (g_YSize <= g_YCameraSize) then goto SETRCEXIT if (g_StitchType <> XYStitch) then g_RowCount = ((g_YSize - g_YCameraSize) / g_YIncrement) + 1 l_nTemp = int(g_RowCount) if (g_RowCount > l_nTemp) then g_RowCount = l_nTemp + 1 if ((g_RowCount * g_YIncrement) < (g_YSize - g_YCameraSize)) then g_RowCount = g_RowCount + 1 else ! X & Y Stitching is done differently l_YOverlap = g_YCameraSize - g_YIncrement g_RowCount = int((g_YSize - l_YOverlap) / g_YIncrement) if (g_RowCount = 1) then g_RowCount = g_RowCount + 1 ! 2 rows, but overlap big CHKROWOVRLP: ! determine how much to add to existing overlap g_YIncrement = g_YCameraSize * ((100 - g_Overlap) / 100) l_nTemp = ((g_YSize - l_YOverlap) - (g_RowCount * g_YIncrement)) / (g_RowCount - 1) g_YIncrement = g_YIncrement + l_nTemp ! chk for overlap >= 10 if (g_YIncrement <= (g_YCameraSize * ((100 - g_Overlap) / 100))) then goto SETRCEXIT g_RowCount = g_RowCount + 1 ! overlap was too small re-calc goto CHKROWOVRLP endif SETRCEXIT: ! set the overlap to the average of the overlaps for display g_Overlap = 100 if (g_ColCount > 1) then g_Overlap = ((g_XIncrement / g_XCameraSize) * 100) if (g_RowCount > 1) then g_Overlap = (g_Overlap + ((g_YIncrement / g_YCameraSize) * 100)) / 2 g_Overlap = 100 - g_Overlap ! change to overlap return ! +-----------------------------------------------------------------------------------------+ ! ! | Sub CHK_DIMENS() | ! ! | Determine is the dimensions are within the max size. | ! ! | | ! ! | In Parameters: | ! ! | g_XSize | ! ! | g_XCameraSize | ! ! | g_XSizeMax | ! ! | g_YSize | ! ! | g_YCameraSize | ! ! | g_YSizeMax | ! ! | | ! ! | Out Parameters: | ! ! | ret_ChkDims *return value | ! ! | | ! ! | Local Variables: | ! ! | l_msg$ | ! ! | | ! ! | Procedures Called: | ! ! | | ! ! | Algorithm: | ! ! | Why are we addind an extra camera size to the X and Y checks? | ! ! +-----------------------------------------------------------------------------------------+ ! CHK_DIMENS: ret_ChkDims = 0 if (((g_XSize + g_XCameraSize) > g_XSizeMax) or ((g_YSize + g_YCameraSize) > g_YSizeMax)) then ret_ChkDims = DlgError_YesNo l_msg$ = " Dimensions exceed capabilities. \n Do you want to change controls and re-try? " endif if ((g_XSize = 0) and (g_YSize = 0)) then ret_ChkDims = DlgError_OK l_msg$ = " The X or Y dimension is zero, change controls and re-try " endif if (ret_ChkDims > 0) then g_dlgMessage$ = l_msg$ g_dlgStyle = ret_ChkDims gosub DO_DIALOG if (ret_Dialog = DlgOK_Yes) then gosub HALT_SCRIPT endif endif CHK_DIMENS_EXIT: return ! +-----------------------------------------------------------------------------------------+ ! ! | Sub GET_STCH_SIZE() | ! ! | Determine the dimensions of the stitched area. | ! ! | | ! ! | In Parameters: | ! ! | g_Overlap | ! ! | | ! ! | Out Parameters: | ! ! | g_XCameraSize | ! ! | g_XSizeMax | ! ! | g_XIncrement | ! ! | g_YCameraSize | ! ! | g_YSizeMax | ! ! | g_YIncrement | ! ! | | ! ! | Local Variables: | ! ! | lCameraRes | ! ! | | ! ! | Procedures Called: | ! ! | | ! ! | Algorithm: | ! ! +-----------------------------------------------------------------------------------------+ ! GET_STCH_SIZE: resetdata l_CameraRes = getcamres("inches") g_XCameraSize = getcamsizex("inches") g_XSizeMax = 10000 * l_CameraRes g_YCameraSize = getcamsizey("inches") g_YSizeMax = 10000 * l_CameraRes g_XIncrement = g_XCameraSize * ((100 - g_Overlap) / 100) g_YIncrement = g_YCameraSize * ((100 - g_Overlap) / 100) GET_STCH_SIZE_EXIT: return ! +-----------------------------------------------------------------------------------------+ ! ! | Sub SAVE_SEQ() | ! ! | Saves the positions of the measurement relative to the first position. | ! ! | | ! ! | In Parameters: | ! ! | g_bSameSequence | ! ! | g_NumMeas | ! ! | g_XMeasPos() | ! ! | g_YMeasPos() | ! ! | | ! ! | Out Parameters: | ! ! | | ! ! | Local Variables: | ! ! | l_SeqFileName$ | ! ! | l_nTemp | ! ! | #SeqFile | ! ! | | ! ! | Procedures Called: | ! ! | | ! ! | Algorithm: | ! ! | 1. Remove existing sequence file. File name specified by user control. | ! ! | 2. Create new file, each item has its own line: | ! ! | A. Number of Measurements | ! ! | B. X Position relative to first position. | ! ! | C. Y Position relative to first position. | ! ! | D. goto B. | ! ! +-----------------------------------------------------------------------------------------+ ! SAVE_SEQ: if (g_bSaveSequence = 0) then goto SAVESEQEXIT l_SeqFileName$ = getval$(g_idStchSeqFileCntl) if (g_bUNIX = 1) then l_nTemp = execute("rm -f " & l_SeqFileName$) else l_nTemp = execute("erase /f /q " & l_SeqFileName$) endif assign @SeqFile to l_SeqFileName$ "w" if (g_NumMeas < 1) then goto SAVESEQEXIT output @SeqFile; val$(g_NumMeas) for l_nTemp = 1 to g_NumMeas output @SeqFile; val$(g_XMeasPos(l_nTemp) - g_XMeasPos(1)) output @SeqFile; val$(g_YMeasPos(l_nTemp) - g_YMeasPos(1)) next l_nTemp assign @SeqFile to "" SAVESEQEXIT: return ! +-----------------------------------------------------------------------------------------+ ! ! | Sub GET_IDS() | ! ! | Gets the IDs for controls and attributes. | ! ! | | ! ! | In Parameters: | ! ! | | ! ! | Out Parameters: | ! ! | g_idStchMeasNumAttr g_idStchColsAttr g_idStchRowsAttr | ! ! | g_idStchOvrlpPerAttr g_idStchXSizeAttr g_idStchYSizeAttr | ! ! | g_idStchRAMRqdAttr g_idStchRAMAvailAttr g_idStchTypeCntl | ! ! | g_idStitchFileID g_idStchShMeasCntl g_idStchMeasErrCntl | ! ! | g_idStchStProcStsCntl g_idStchMvmntCntl g_idStchFocusCntl | ! ! | g_idStchTiltCntl g_idStchSeqFileCntl g_idStchSaveSeqFileCntl | ! ! | g_idStchPrDataCntl g_idStchAvgOvrlpCntl g_idStchDiagCntl | ! ! | g_idStchAutoLdMskCntl g_idStchMskFileCntl g_idStchColsCntl | ! ! | g_idStchRowsCntl g_idStchOvrlpPerCntl g_idStchXSizeCntl | ! ! | g_idStchYSizeCntl g_idStchInRadCntl g_idStchOutRadCntl | ! ! | g_idStchRemIntens g_idZipLOvrlpPerCntl g_idZipLXSizeCntl | ! ! | g_idZipLYSizeCntl g_idZipUOvrlpPerCntl g_idZipUXSizeCntl | ! ! | g_idZipUYSizeCntl g_idZipDistCntl g_idZipShowStchSurfCntl | ! ! | g_idZipUXOffCntl g_idZipUYOffCntl g_idZipStProcStsCntl | ! ! | g_idZipLSeqFileCntl g_idZipUSeqFileCntl g_idZipUseLSeqFileCntl | ! ! | g_idZipUseUSeqFileCntl g_idZipLLgtLvlCntl g_idZipULgtLvlCntl | ! ! | g_idZipMaskCntl g_idZipMaskFileCntl g_idZipFileID | ! ! | g_idZipRemIntens g_idPhaseResCntl g_idAutoFocusCntl | ! ! | g_idAutoTiltCntl g_idLgtLvlCntl g_idSavePrDataID | ! ! | | ! ! | Local Variables: | ! ! | ret_Dialog | ! ! | | ! ! | Procedures Called: | ! ! | | ! ! | Algorithm: | ! ! | g_idSavePrDataID is not present is all applications; it may be zero. | ! ! +-----------------------------------------------------------------------------------------+ ! GET_IDS: g_idStchMeasNumAttr = getid("attributes/stitch/MeasurementStatus") g_idStchColsAttr = getid("attributes/stitch/NCols") g_idStchRowsAttr = getid("attributes/stitch/NRows") g_idStchOvrlpPerAttr = getid("attributes/stitch/Overlap(%)") g_idStchXSizeAttr = getid("attributes/stitch/SizeX") g_idStchYSizeAttr = getid("attributes/stitch/SizeY") g_idStchRAMRqdAttr = getid("attributes/stitch/RAM Required") g_idStchRAMAvailAttr = getid("attributes/stitch/RAM Available") g_idStchTypeCntl = getid("controls/stitch/Type") g_idStitchFileID = getid("Controls/Stitch/StitchFile") g_idStchShMeasCntl = getid("controls/stitch/DisplayMeasurements") g_idStchMeasErrCntl = getid("controls/stitch/FailureAction") g_idStchStProcStsCntl = getid("controls/stitch/StoreProcessStats") !g_idStchLogReportsCntl = getid("controls/stitch/logreports") g_idStchMvmntCntl = getid("controls/stitch/ScanningSeq") g_idStchFocusCntl = getid("controls/stitch/autofocus") g_idStchTiltCntl = getid("controls/stitch/autotilt") g_idStchSeqFileCntl = getid("controls/stitch/SeqFile") g_idStchSaveSeqFileCntl = getid("controls/stitch/AutoSaveSeq") g_idStchPrDataCntl = getid("controls/stitch/StitchProcessedData") g_idStchAvgOvrlpCntl = getid("controls/stitch/AverageOverlapRegions") g_idStchDiagCntl = getid("controls/stitch/Diagnostics") g_idStchAutoLdMskCntl = getid("controls/stitch/AutoLoadMasks") g_idStchMskFileCntl = getid("controls/stitch/MasksFile") g_idStchColsCntl = getid("controls/stitch/NCols") g_idStchRowsCntl = getid("controls/stitch/NRows") g_idStchOvrlpPerCntl = getid("controls/stitch/Overlap(%)") g_idStchXSizeCntl = getid("controls/stitch/SizeX") g_idStchYSizeCntl = getid("controls/stitch/SizeY") g_idStchInRadCntl = getid("controls/stitch/InnerRadius") g_idStchOutRadCntl = getid("controls/stitch/OuterRadius") g_idStchRemIntens = getid("controls/stitch/Remove Intensity data") g_idZipLOvrlpPerCntl = getid("controls/ZipStitch/LowerOverlap(%)") g_idZipLXSizeCntl = getid("controls/ZipStitch/LowerSizeX") g_idZipLYSizeCntl = getid("controls/ZipStitch/LowerSizeY") g_idZipUOvrlpPerCntl = getid("controls/ZipStitch/UpperOverlap(%)") g_idZipUXSizeCntl = getid("controls/ZipStitch/UpperSizeX") g_idZipUYSizeCntl = getid("controls/ZipStitch/UpperSizeY") g_idZipDistCntl = getid("controls/ZipStitch/ZipDistance") g_idZipShowStchSurfCntl = getid("controls/ZipStitch/DisplayStitchedSurfaces") g_idZipUXOffCntl = getid("controls/ZipStitch/UpperOffsetX") g_idZipUYOffCntl = getid("controls/ZipStitch/UpperOffsetY") g_idZipStProcStsCntl = getid("controls/ZipStitch/StoreProcessStats") g_idZipLSeqFileCntl = getid("controls/ZipStitch/LowerSeqFile") g_idZipUSeqFileCntl = getid("controls/ZipStitch/UpperSeqFile") g_idZipUseLSeqFileCntl = getid("controls/ZipStitch/UseLowerSeqFile") g_idZipUseUSeqFileCntl = getid("controls/ZipStitch/UseUpperSeqFile") g_idZipLLgtLvlCntl = getid("controls/ZipStitch/LowerLightLevelOffset") g_idZipULgtLvlCntl = getid("controls/ZipStitch/UpperLightLevelOffset") g_idZipMaskCntl = getid("controls/ZipStitch/AutoLoadMasks") g_idZipMaskFileCntl = getid("controls/ZipStitch/MasksFile") g_idZipFileID = getid("Controls/ZipStitch/ZipFile") g_idZipRemIntens = getid("controls/ZipStitch/Remove Intensity data") g_idPhaseResCntl = getid("controls/PhaseProcessing/PhaseRes") g_idAutoFocusCntl = getid("controls/Focus/Focus") g_idAutoTiltCntl = getid("controls/autotilt/autotilt") g_idLgtLvlCntl = getid("controls/Acquisition/LightLevelPct") ! Surface Wavefront Map does not exist in all apps, this is used in savedata g_IgnoreError = g_IgnoreError + 1 on error gosub RESUME_NEXT g_idSavePrDataID = 0 g_idSavePrDataID = getid("SurfaceWavefrontMap") g_IgnoreError = g_IgnoreError - 1 if ( g_IgnoreError = 0 ) then on error goto CENTRAL_ERROR_HANDLER goto GET_IDS_EXIT GET_IDS_EXIT: return ! +-----------------------------------------------------------------------------------------+ ! ! | Sub GET_ZIP_CNTRLS() | ! ! | Gets the values of controls and attributes used by Zip. | ! ! | | ! ! | In Parameters: | ! ! | | ! ! | Out Parameters: | ! ! | ZXSize() | ! ! | ZYSize() | ! ! | ZOvrlp() | ! ! | ZLgtLvlOff() | ! ! | g_ZipDistance | ! ! | PhaseRes | ! ! | UseSeqFile() | ! ! | AutoLoadZipMask | ! ! | zipXOffset | ! ! | zipYOffset | ! ! | l_idStitchFile | ! ! | g_StitchFile$ | ! ! | ZipShowStch | ! ! | ZipFn$ | ! ! | tmpStchTilt | ! ! | ZRemIntens | ! ! | | ! ! | Local Variables: | ! ! | | ! ! | Procedures Called: | ! ! | | ! ! | Algorithm: | ! ! +-----------------------------------------------------------------------------------------+ ! GET_ZIP_CNTRLS: ZXSize(1) = getval(g_idZipLXSizeCntl, "in") ZXSize(2) = getval(g_idZipUXSizeCntl, "in") ZYSize(1) = getval(g_idZipLYSizeCntl, "in") ZYSize(2) = getval(g_idZipUYSizeCntl, "in") ZOvrlp(1) = getval(g_idZipLOvrlpPerCntl, "") ZOvrlp(2) = getval(g_idZipUOvrlpPerCntl, "") ZLgtLvlOff(1) = getval(g_idZipLLgtLvlCntl, "") ZLgtLvlOff(2) = getval(g_idZipULgtLvlCntl, "") g_ZipDistance = getval(g_idZipDistCntl, "in") PhaseRes = getval(g_idPhaseResCntl, "") UseSeqFile(1) = getval(g_idZipUseLSeqFileCntl, "") UseSeqFile(2) = getval(g_idZipUseUSeqFileCntl, "") AutoLoadZipMask = getval(g_idZipMaskCntl, "") zipXOffset = getval(g_idZipUXOffCntl, "in") zipYOffset = getval(g_idZipUYOffCntl, "in") l_idStitchFile = getid("controls/stitch/stitchfile") g_StitchFile$ = getval$(l_idStitchFile) ZipShowStch = getval(g_idZipShowStchSurfCntl, "") ZipFn$ = getval$(g_idZipFileID) tmpStchTilt = getval(g_idStchTiltCntl, "") ZRemIntens = getval(g_idZipRemIntens, "") goto GET_ZIP_CNTRLS_EXIT GET_ZIP_CNTRLS_EXIT: return ! +-----------------------------------------------------------------------------------------+ ! ! | Sub GET_XY() | ! ! | Gets the current X and Y positions. | ! ! | | ! ! | In Parameters: | ! ! | g_StitchType | ! ! | | ! ! | Out Parameters: | ! ! | X *return value | ! ! | Y *return value | ! ! | | ! ! | Local Variables: | ! ! | ret_Dialog | ! ! | | ! ! | Procedures Called: | ! ! | STAGE_ERROR (error routine) | ! ! | | ! ! | Algorithm: | ! ! | 1. if Manual Stage Stitch, do nothing. | ! ! | 2. Get current X and Y positions. | ! ! | * Possible improvement: Prompt user to enter X and Y coordinates in order to | ! ! | centralize the collection of X & Y coordinates. | ! ! +-----------------------------------------------------------------------------------------+ ! GET_XY: g_StageProcess = 1 GetXYErrorSet = 0 if (g_StitchType = ManualStageStitch) then goto END_GET_XY ! don't do this for manual stages x_axis_active = isaxisactive('X') if ( x_axis_active <> 1 ) then ! Cause an error to invoke the error handler ok = 1 / 0 endif y_axis_active = isaxisactive('Y') if ( y_axis_active <> 1 ) then ! Cause an error to invoke the error handler ok = 1 / 0 endif tmp_x_pos = getxpos tmp_y_pos = getypos goto END_GET_XY END_GET_XY: g_StageProcess = 0 return ! +-----------------------------------------------------------------------------------------+ ! ! | Sub GET_XY_NO_ERROR() | ! ! | Gets the current X and Y positions. Ignores any errors. | ! ! | | ! ! | In Parameters: | ! ! | g_StitchType | ! ! | | ! ! | Out Parameters: | ! ! | X *return value | ! ! | Y *return value | ! ! | | ! ! | Local Variables: | ! ! | ret_Dialog | ! ! | | ! ! | Procedures Called: | ! ! | STAGE_ERROR (error routine) | ! ! | | ! ! | Algorithm: | ! ! | 1. if Manual Stage Stitch, do nothing. | ! ! | 2. Get current X and Y positions. | ! ! | * Possible improvement: Prompt user to enter X and Y coordinates in order to | ! ! | centralize the collection of X & Y coordinates. | ! ! +-----------------------------------------------------------------------------------------+ ! GET_XY_NO_ERROR: g_StageProcess = 1 g_IgnoreError = g_IgnoreError + 1 on error gosub RESUME_NEXT GetXYErrorSet = 0 if (g_StitchType = ManualStageStitch) then goto END_GET_XY_NO_ERROR ! don't do this for manual stages tmp_x_pos = 0 tmp_y_pos = 0 if ( isaxisactive('X') <> 1 ) then goto END_GET_XY_NO_ERROR if ( isaxisactive('Y') <> 1 ) then goto END_GET_XY_NO_ERROR tmp_x_pos = getxpos tmp_y_pos = getypos END_GET_XY_NO_ERROR: g_StageProcess = 0 g_IgnoreError = g_IgnoreError - 1 if ( g_IgnoreError = 0 ) then on error goto CENTRAL_ERROR_HANDLER return ! +-----------------------------------------------------------------------------------------+ ! ! | Sub MOVE_XY() | ! ! | Moves the current X and Y positions. | ! ! | | ! ! | In Parameters: | ! ! | g_StitchType | ! ! | X | ! ! | Y | ! ! | | ! ! | Out Parameters: | ! ! | | ! ! | Local Variables: | ! ! | ret_Dialog | ! ! | | ! ! | Procedures Called: | ! ! | STAGE_ERROR (error routine) | ! ! | | ! ! | Algorithm: | ! ! | 1. if Manual Stage Stitch, do nothing. | ! ! | 2. Move current X and Y positions. | ! ! | * Possible improvement: Prompt user to move X and Y coordinates in order to | ! ! | centralize the movement of X & Y axes. | ! ! +-----------------------------------------------------------------------------------------+ ! MOVE_XY: g_StageProcess = 1 MoveXYErrorSet = 0 if (g_StitchType = ManualStageStitch) then goto END_MOVE_XY ! don't do this for manual stages movexy(tmp_x_pos, tmp_y_pos) goto END_MOVE_XY END_MOVE_XY: g_StageProcess = 0 return ! +-----------------------------------------------------------------------------------------+ ! ! | Sub MOVE_XY_NO_ERROR() | ! ! | Moves the current X and Y positions. Ignores any errors. | ! ! | | ! ! | In Parameters: | ! ! | g_StitchType | ! ! | X | ! ! | Y | ! ! | | ! ! | Out Parameters: | ! ! | | ! ! | Local Variables: | ! ! | ret_Dialog | ! ! | | ! ! | Procedures Called: | ! ! | STAGE_ERROR (error routine) | ! ! | | ! ! | Algorithm: | ! ! | 1. if Manual Stage Stitch, do nothing. | ! ! | 2. Move current X and Y positions. | ! ! | * Possible improvement: Prompt user to move X and Y coordinates in order to | ! ! | centralize the movement of X & Y axes. | ! ! +-----------------------------------------------------------------------------------------+ ! MOVE_XY_NO_ERROR: g_StageProcess = 1 g_IgnoreError = g_IgnoreError + 1 on error gosub RESUME_NEXT MoveXYErrorSet = 0 if (g_StitchType = ManualStageStitch) then goto END_MOVE_XY_NO_ERROR ! don't do this for manual stages movexy(tmp_x_pos, tmp_y_pos) END_MOVE_XY_NO_ERROR: g_StageProcess = 0 g_IgnoreError = g_IgnoreError - 1 if ( g_IgnoreError = 0 ) then on error goto CENTRAL_ERROR_HANDLER return ! +-----------------------------------------------------------------------------------------+ ! ! | Sub GET_Z() | ! ! | Gets the current Z position. | ! ! | | ! ! | In Parameters: | ! ! | g_StitchType | ! ! | | ! ! | Out Parameters: | ! ! | Z *return value | ! ! | | ! ! | Local Variables: | ! ! | ret_Dialog | ! ! | | ! ! | Procedures Called: | ! ! | STAGE_ERROR (error routine) | ! ! | | ! ! | Algorithm: | ! ! | 1. if Manual Stage Stitch, do nothing. | ! ! | 2. Get current Z position. | ! ! | * Possible improvement: Prompt user to enter Z coordinate in order to centralize | ! ! | the collection of Z coordinate. | ! ! +-----------------------------------------------------------------------------------------+ ! GET_Z: g_StageProcess = 1 GetZErrorSet = 0 if (g_StitchType = ManualStageStitch) then goto END_GET_Z ! don't do this for manual stages if ( isaxisactive('Z') <> 1 ) then tmp_z_pos = 0 goto END_GET_Z endif tmp_z_pos = getzpos goto END_GET_Z END_GET_Z: g_StageProcess = 0 return ! +-----------------------------------------------------------------------------------------+ ! ! | Sub GET_Z_NO_ERROR() | ! ! | Gets the current Z position. Ignores any errors. | ! ! | | ! ! | In Parameters: | ! ! | g_StitchType | ! ! | | ! ! | Out Parameters: | ! ! | Z *return value | ! ! | | ! ! | Local Variables: | ! ! | ret_Dialog | ! ! | | ! ! | Procedures Called: | ! ! | STAGE_ERROR (error routine) | ! ! | | ! ! | Algorithm: | ! ! | 1. if Manual Stage Stitch, do nothing. | ! ! | 2. Get current Z position. | ! ! | * Possible improvement: Prompt user to enter Z coordinate in order to centralize | ! ! | the collection of Z coordinate. | ! ! +-----------------------------------------------------------------------------------------+ ! GET_Z_NO_ERROR: g_StageProcess = 1 g_IgnoreError = g_IgnoreError + 1 on error gosub RESUME_NEXT GetZErrorSet = 0 if (g_StitchType = ManualStageStitch) then goto END_GET_Z_NO_ERROR ! don't do this for manual stages if ( isaxisactive('Z') <> 1 ) then tmp_z_pos = 0 goto END_GET_Z_NO_ERROR endif tmp_z_pos = getzpos END_GET_Z_NO_ERROR: g_StageProcess = 0 g_IgnoreError = g_IgnoreError - 1 if ( g_IgnoreError = 0 ) then on error goto CENTRAL_ERROR_HANDLER return ! +-----------------------------------------------------------------------------------------+ ! | ! | Gets the encoder position on the z-axis. ! | ! | ! +-----------------------------------------------------------------------------------------+ GET_Z_ENCODER: g_StageProcess = 1 if ( isaxisactive('A') <> 1 ) then tmp_ze_pos = 0 goto END_GET_Z_ENCODER endif tmp_ze_pos = getpos('A', 1) END_GET_Z_ENCODER: g_StageProcess = 0 return ! +-----------------------------------------------------------------------------------------+ ! ! | Sub MOVE_Z() | ! ! | Moves the current Z position. | ! ! | | ! ! | In Parameters: | ! ! | g_StitchType | ! ! | tmp_z_pos | ! ! | | ! ! | Out Parameters: | ! ! | | ! ! | Local Variables: | ! ! | ret_Dialog | ! ! | | ! ! | Procedures Called: | ! ! | STAGE_ERROR (error routine) | ! ! | | ! ! | Algorithm: | ! ! | 1. if Manual Stage Stitch, do nothing. | ! ! | 2. Move current Z position. | ! ! | * Possible improvement: Prompt user to move Z coordinate in order to centralize the | ! ! | movement of Z axes. | ! ! +-----------------------------------------------------------------------------------------+ ! MOVE_Z: g_StageProcess = 1 MoveZErrorSet = 0 if (g_StitchType = ManualStageStitch) then goto END_MOVE_Z ! don't do this for manual stages movez(tmp_z_pos) goto END_MOVE_Z END_MOVE_Z: g_StageProcess = 0 return ! +-----------------------------------------------------------------------------------------+ ! ! | Sub MOVE_Z_NO_ERROR() | ! ! | Moves the current Z position. Ignores any errors. | ! ! | | ! ! | In Parameters: | ! ! | g_StitchType | ! ! | tmp_z_pos | ! ! | | ! ! | Out Parameters: | ! ! | | ! ! | Local Variables: | ! ! | ret_Dialog | ! ! | | ! ! | Procedures Called: | ! ! | STAGE_ERROR (error routine) | ! ! | | ! ! | Algorithm: | ! ! | 1. if Manual Stage Stitch, do nothing. | ! ! | 2. Move current Z position. | ! ! | * Possible improvement: Prompt user to move Z coordinate in order to centralize the | ! ! | movement of Z axes. | ! ! +-----------------------------------------------------------------------------------------+ ! MOVE_Z_NO_ERROR: g_StageProcess = 1 g_IgnoreError = g_IgnoreError + 1 on error gosub RESUME_NEXT MoveZErrorSet = 0 if (g_StitchType = ManualStageStitch) then goto END_MOVE_Z_NO_ERROR ! don't do this for manual stages movez(tmp_z_pos) END_MOVE_Z_NO_ERROR: g_StageProcess = 0 g_IgnoreError = g_IgnoreError - 1 if ( g_IgnoreError = 0 ) then on error goto CENTRAL_ERROR_HANDLER return ! +-----------------------------------------------------------------------------------------+ ! ! | Sub HAVE_MOTORIZED_Z() | ! ! | Checks to see if there is a motorized Z stage. | ! ! | | ! ! | In Parameters: | ! ! | | ! ! | Out Parameters: | ! ! | ret_MotorZ | ! ! | | ! ! | Local Variables: | ! ! | l_nTemp | ! ! | | ! ! | Procedures Called: | ! ! | | ! ! | Algorithm: | ! ! | 1. Say we don't have motorized Z stage. | ! ! | 2. Try to get the current position of the Z stage. | ! ! | 3. if no error occured, say we have a motorized Z stage. | ! ! +-----------------------------------------------------------------------------------------+ ! HAVE_MOTORIZED_Z: ! assume we will get an error ret_MotorZ = 0 on error goto END_HAVE_MOTORIZED_Z l_nTemp = getzpos ! no error .. we're golden ret_MotorZ = 1 END_HAVE_MOTORIZED_Z: if ( g_IgnoreError = 0 ) then on error goto CENTRAL_ERROR_HANDLER else on error gosub RESUME_NEXT endif return ! +-----------------------------------------------------------------------------------------+ ! ! | Sub STCH_INIT() | ! ! | Initializes variables used for stitching. | ! ! | | ! ! | In Parameters: | ! ! | | ! ! | Out Parameters: | ! ! | g_Direction | ! ! | g_bFirstAutoFocus | ! ! | g_RetryCount | ! ! | g_CoordFile$ | ! ! | g_MPBinDir$ | ! ! | g_LogFile$ | ! ! | g_StitchType | ! ! | g_bFit | ! ! | g_MeasureMessage$ | ! ! | g_XStart | ! ! | g_YStart | ! ! | g_XPos(1) | ! ! | g_YPos(1) | ! ! | g_ZPos(1) | ! ! | g_Overlap | ! ! | g_bShowMesaurement | ! ! | g_OnStitchMeasureError | ! ! | g_bSaveProcessedData | ! ! | g_bAverageOverlap | ! ! | g_ColCount | ! ! | g_RowCount | ! ! | g_XSize | ! ! | g_YSize | ! ! | g_bDiagnostic | ! ! | g_FocusType | ! ! | g_TiltType | ! ! | g_bSaveSequence | ! ! | tmpFocus | ! ! | tmpTilt | ! ! | g_InnerRadius | ! ! | g_OuterRadius | ! ! | g_bRemoveIntensity | ! ! | g_StitchFileName$ | ! ! | g_DoStitch | ! ! | g_ReturnWhenDone | ! ! | g_HaveData | ! ! | | ! ! | Local Variables: | ! ! | l_NumPos | ! ! | z_start | ! ! | ret_Dialog | ! ! | | ! ! | Procedures Called: | ! ! | GET_IDS | ! ! | GET_STCH_TYPE | ! ! | GET_XY | ! ! | GET_Z | ! ! | HALT_SCRIPT (error routine) | ! ! | | ! ! | Algorithm: | ! ! +-----------------------------------------------------------------------------------------+ ! STCH_INIT: gosub CLEAR_USER_ABORT gosub GET_XY g_XStart = tmp_x_pos g_YStart = tmp_y_pos gosub GET_Z z_start = tmp_z_pos g_XPos(1) = g_XStart g_YPos(1) = g_YStart g_ZPos(1) = z_start l_NumPos = 1 g_Direction = 1 g_bFirstAutoFocus = 1 g_RetryCount = 0 g_DoStitch = 0 g_ReturnWhenDone = 1 g_HaveData = 0 resetdata g_CoordFile$ = g_TempDir$ & g_PathSep$ & "coords.crd" g_MPBinDir$ = getbindir$ & g_PathSep$ ! place to where executable lives g_LogFile$ = "stitch.log" gosub GET_IDS gosub GET_STCH_TYPE g_bFit = 1 ! default, do a fit over the stitch surfaces g_MesaureMessage$ = " " setstr(g_idStchMeasNumAttr, g_MesaureMessage$) setnum(g_idStchColsAttr, 0, "") setnum(g_idStchRowsAttr, 0, "") setnum(g_idStchXSizeAttr, 0, "in") setnum(g_idStchYSizeAttr, 0, "in") ! ! GET ALL THE CONTROL VALUES ! g_Overlap = getval(g_idStchOvrlpPerCntl, "") ! 10 ! set to minimum g_bShowMesaurement = getval(g_idStchShMeasCntl, "") g_OnStitchMeasureError = getval(g_idStchMeasErrCntl, "") g_bSaveProcessedData = getval(g_idStchPrDataCntl, "") g_bAverageOverlap = getval(g_idStchAvgOvrlpCntl, "") ! NOTE: Save Processed data ONLY works if Show Individual Measurements is on !if (g_bSaveProcessedData = 1) then setnum(g_idStchShMeasCntl, 1, "") ! 9-19-00 ALD ! Cannot stich processed data if display measurements is off. ! Put up error message and quit stitching. if (g_bSaveProcessedData = 1) and (g_bShowMesaurement = 0) then g_dlgMessage$ = " Stitching Error. \n Cannot stitch processed data with \n Show Measurement control off. " g_dlgStyle = DlgError_OK gosub DO_DIALOG gosub HALT_SCRIPT endif g_ColCount = getval(g_idStchColsCntl, "") g_RowCount = getval(g_idStchRowsCntl, "") g_XSize = getval(g_idStchXSizeCntl, "in") g_YSize = getval(g_idStchYSizeCntl, "in") g_bDiagnostic = getval(g_idStchDiagCntl, "") g_FocusType = getval(g_idStchFocusCntl, "") g_TiltType = getval(g_idStchTiltCntl, "") g_bSaveSequence = getval(g_idStchSaveSeqFileCntl, "") tmpFocus = getval(g_idAutoFocusCntl, "") tmpTilt = getval(g_idAutoTiltCntl, "") g_InnerRadius = getval(g_idStchInRadCntl, "in") g_OuterRadius = getval(g_idStchOutRadCntl, "in") g_bRemoveIntensity = getval(g_idStchRemIntens, "") g_StitchFileName$ = getval$(g_idStitchFileID) goto STCH_INIT_EXIT STCH_INIT_EXIT: return ! +-----------------------------------------------------------------------------------------+ ! ! | Sub GET_STCH_TYPE() | ! ! | Gets the type of stitching from the user control. | ! ! | | ! ! | In Parameters: | ! ! | g_idStchTypeCntl | ! ! | | ! ! | Out Parameters: | ! ! | | ! ! | Local Variables: | ! ! | | ! ! | return Type: | ! ! | g_StitchType. Number 1 - 8. | ! ! | | ! ! | Procedures Called: | ! ! | | ! ! | Algorithm: | ! ! | | ! ! +-----------------------------------------------------------------------------------------+ ! GET_STCH_TYPE: g_idStchTypeCntl = getid("controls/stitch/Type") g_StitchType = getval(g_idStchTypeCntl, "") GET_STCH_TYPE_EXIT: return ! +-----------------------------------------------------------------------------------------+ ! ! | Sub CREATE_TMP_DIR() | ! ! | Creates or cleans a stitching temp directory. | ! ! | | ! ! | In Parameters: | ! ! | g_TempDir$ | ! ! | | ! ! | Out Parameters: | ! ! | | ! ! | Local Variables: | ! ! | | ! ! | Procedures Called: | ! ! | CLEAN_TMP_DIR | ! ! | | ! ! | Algorithm: | ! ! | 1. Remove old stitch temp directory. | ! ! | 2. Create new stitch temp directory. | ! ! +-----------------------------------------------------------------------------------------+ ! CREATE_TMP_DIR: gosub CLEAN_TMP_DIR l_nTemp = execute("mkdir " & g_TempDir$) ! create dir CREATE_TMP_DIR_EXIT: return ! +-----------------------------------------------------------------------------------------+ ! ! | Sub CLEAN_TMP_DIR() | ! ! | Removes the old stitching temp directory. | ! ! | | ! ! | In Parameters: | ! ! | g_TempDir$ | ! ! | | ! ! | Out Parameters: | ! ! | | ! ! | Local Variables: | ! ! | l_idStitchFile | ! ! | l_FileName$ | ! ! | l_nTemp | ! ! | | ! ! | Procedures Called: | ! ! | | ! ! | Algorithm: | ! ! | 1. Remove stitch file. | ! ! | 2. Remove all files in the directory. | ! ! | 3. Remove the directory. | ! ! +-----------------------------------------------------------------------------------------+ ! CLEAN_TMP_DIR: l_idStitchFile = getid("controls/stitch/StitchFile") l_FileName$ = getval$(l_idStitchFile) if (g_bUNIX = 1) then l_nTemp = execute("rm -f " & l_FileName$) ! remove the old stitch file l_nTemp = execute("rm -f " & g_TempDir$ & "/*") ! remove all the files in the temp dir else l_nTemp = execute("erase /f /q " & l_FileName$) ! remove the old stitch file l_nTemp = execute("erase /f /q " & g_TempDir$ & "\\*.*") ! remove all the files in the temp dir endif CLEAN_TMP_DIR_EXIT: return ! +-----------------------------------------------------------------------------------------+ ! ! | Sub READ_SEQ() | ! ! | Reads a sequence file. | ! ! | | ! ! | In Parameters: | ! ! | g_idStchSeqFileCntl | ! ! | | ! ! | Out Parameters: | ! ! | g_NumMeas | ! ! | g_XPos() | ! ! | g_YPos() | ! ! | | ! ! | Local Variables: | ! ! | X | ! ! | Y | ! ! | l_SeqFileName$ | ! ! | #SeqFile | ! ! | l_sTemp$ | ! ! | | ! ! | Procedures Called: | ! ! | | ! ! | Algorithm: | ! ! | Sequence files contain the number of positions and the positions relative to the | ! ! | first position. Each number is on a seperate line: | ! ! | A. Number of Measurements | ! ! | B. X Position relative to first position. | ! ! | C. Y Position relative to first position. | ! ! | D. goto B. | ! ! | | ! ! | 1. Get the current position. | ! ! | 2. read the file adding the current position to the positions read from the file. | ! ! +-----------------------------------------------------------------------------------------+ ! READ_SEQ: gosub GET_XY X = tmp_x_pos Y = tmp_y_pos l_SeqFileName$ = getval$(g_idStchSeqFileCntl) assign @SeqFile to l_SeqFileName$ "r" enter @SeqFile; l_sTemp$ g_NumMeas = val(l_sTemp$) for l_nTemp = 1 to g_NumMeas enter @SeqFile; l_sTemp$ g_XPos(l_nTemp) = val(l_sTemp$) + X enter @SeqFile; l_sTemp$ g_YPos(l_nTemp) = val(l_sTemp$) + Y next l_nTemp assign @SeqFile to "" READ_SEQ_EXIT: return ! +-----------------------------------------------------------------------------------------+ ! ! | Sub SET_STCH_LOCS() | ! ! | Determine the locations for measurements based on Row and Count Column Count | ! ! | | ! ! | In Parameters: | ! ! | g_isStitchMvmntCntl | ! ! | g_ColCount | ! ! | g_RowCount | ! ! | g_XStart | ! ! | g_YStart | ! ! | g_XEnd | ! ! | g_YEnd | ! ! | g_XIncrement | ! ! | g_YIncrement | ! ! | g_StitchType | ! ! | | ! ! | Out Parameters: | ! ! | g_StageMovement | ! ! | g_XPos() | ! ! | g_YPos() | ! ! | g_Direction | ! ! | | ! ! | Local Variables: | ! ! | tmp_x_pos | ! ! | tmp_y_pos | ! ! | l_NumPos | ! ! | Index | ! ! | | ! ! | Procedures Called: | ! ! | | ! ! | Algorithm: | ! ! | 1. Setup for first row. | ! ! | 2. Determine Raster or Serpintine movement | ! ! | 3. Serpintine | ! ! | A. for each row, set the columns. | ! ! | B. Every time the start or end of the row is reached, increment the row and | ! ! | change directions. | ! ! | 4. Raster | ! ! | A. for each row and column, set the positions. | ! ! +-----------------------------------------------------------------------------------------+ ! SET_STCH_LOCS: tmp_x_pos = 1 tmp_y_pos = 1 l_NumPos = 1 g_StageMovement = getval(g_idStchMvmntCntl, "") ! 1 is Rast, 2 is Serp if (g_StageMovement = SerpintineMove) then goto START_SERP_LOOP goto START_RAST_LOOP START_SERP_LOOP: if ((tmp_x_pos > g_ColCount) or (tmp_x_pos = 0)) then goto INC_Y g_XPos(l_NumPos) = g_XStart + ((tmp_x_pos - 1) * g_XIncrement) g_YPos(l_NumPos) = g_YStart + ((tmp_y_pos - 1) * g_YIncrement) ! want to get meas right at endif doing start end stitch if ((tmp_x_pos = g_ColCount) and (g_StitchType = StartEndStitch)) then g_XPos(l_NumPos) = g_XEnd if ((tmp_y_pos = g_RowCount) and (g_StitchType = StartEndStitch)) then g_YPos(l_NumPos) = g_YEnd tmp_x_pos = tmp_x_pos + g_Direction l_NumPos = l_NumPos + 1 goto START_SERP_LOOP INC_Y: tmp_x_pos = tmp_x_pos - g_Direction ! to put x back tmp_y_pos = tmp_y_pos + 1 g_Direction = 0 - g_Direction !switch direction (serpentine pattern) if (tmp_y_pos > g_RowCount) then goto SET_STCH_EXIT goto START_SERP_LOOP START_RAST_LOOP: Index = 1 for tmp_y_pos = 1 to g_RowCount for tmp_x_pos = 1 to g_ColCount g_XPos(Index) = g_XStart + ((tmp_x_pos - 1) * g_XIncrement) g_YPos(Index) = g_YStart + ((tmp_y_pos - 1) * g_YIncrement) ! want to get meas right at endif doing start end stitch if ((tmp_x_pos = g_ColCount) and (g_StitchType = StartEndStitch)) then g_XPos(Index) = g_XEnd if ((tmp_y_pos = g_RowCount) and (g_StitchType = StartEndStitch)) then g_YPos(Index) = g_YEnd Index = Index + 1 next tmp_x_pos next tmp_y_pos SET_STCH_EXIT: return ! +-----------------------------------------------------------------------------------------+ ! ! | Sub CREATE_COORDF() | ! ! | Writes coordinates and file names to the Coordinate File. | ! ! | | ! ! | In Parameters: | ! ! | g_CoordFile$ | ! ! | g_NumMeas | ! ! | g_bDiagnostic | ! ! | g_bAverageOverlap | ! ! | g_bFit | ! ! | g_bRemoveIntensity | ! ! | g_XMeasPos() | ! ! | g_YMeasPos() | ! ! | g_ZMeasPos() | ! ! | g_StitchFileName$ | ! ! | g_TempDir$ | ! ! | | ! ! | Out Parameters: | ! ! | | ! ! | Local Variables: | ! ! | #CoorFile | ! ! | l_nTemp | ! ! | l_FileName$ | ! ! | | ! ! | Procedures Called: | ! ! | | ! ! | Algorithm: | ! ! | 1. Save specific control values for stitching program. | ! ! | 2. Save location of .DAT file. | ! ! | 3. Save X, Y & Z positions for .DAT file. | ! ! | 4. goto 2. | ! ! | 5. Save file name of stitched data. | ! ! +-----------------------------------------------------------------------------------------+ ! CREATE_COORDF: assign @CoorFile to g_CoordFile$ "w" output @CoorFile; "* Zygo Stitching Coord File Version 3" output @CoorFile; val$(g_NumMeas) & " # number of input files " output @CoorFile; val$(g_bDiagnostic) & " # diagnostic flag " ! write value for diagnotics output @CoorFile; val$(g_bAverageOverlap) & " # average overlap flag " ! write value for averaging overlap regions output @CoorFile; val$(g_bFit) & " # fit surfaces flag " ! write value for doing a fit of all surfaces (this is set to 1) output @CoorFile; val$(g_bRemoveIntensity) & " # remove Intensity data flag " ! write value for removing intensity data from the output data for l_nTemp = 1 to g_NumMeas l_FileName$ = g_TempDir$ & g_PathSep$ & "stch" & val$(l_nTemp) & ".dat" output @CoorFile; l_FileName$ output @CoorFile; val$(g_XMeasPos(l_nTemp)) & " " & val$(g_YMeasPos(l_nTemp)) & " " & val$(g_ZMeasPos(l_nTemp)) & " # x y and z position in inches " next l_nTemp output @CoorFile; g_StitchFileName$ assign @CoorFile to "" CREATE_COORDF_EXIT: return ! +-----------------------------------------------------------------------------------------+ ! ! | Sub UPDATE_CNTRLS() | ! ! | Update stitching controls and attributes. | ! ! | | ! ! | In Parameters: | ! ! | g_idStchRowsAttr | ! ! | g_idStchRowsCntl | ! ! | g_idStchColsAttr | ! ! | g_idStchColsCntl | ! ! | g_idStchOvrlpPerAttr | ! ! | g_idStchXSizeAttr | ! ! | g_idStchXSizeCntl | ! ! | g_idStchYSizeAttr | ! ! | g_idStchYSizeCntl | ! ! | g_idStchMeasNumAttr | ! ! | | ! ! | Out Parameters: | ! ! | | ! ! | Procedures Called: | ! ! | | ! ! | Local Variables: | ! ! | | ! ! | Algorithm: | ! ! +-----------------------------------------------------------------------------------------+ ! UPDATE_CNTRLS: ! update Metropro controls setnum(g_idStchRowsAttr, g_RowCount, "") setnum(g_idStchRowsCntl, g_RowCount, "") setnum(g_idStchColsAttr, g_ColCount, "") setnum(g_idStchColsCntl, g_ColCount, "") setnum(g_idStchOvrlpPerAttr, g_Overlap, "") setnum(g_idStchXSizeAttr, g_XSize, "in") setnum(g_idStchXSizeCntl, g_XSize, "in") setnum(g_idStchYSizeAttr, g_YSize, "in") setnum(g_idStchYSizeCntl, g_YSize, "in") setstr(g_idStchMeasNumAttr, g_MesaureMessage$) UPDATE_CNTRLS_EXIT: return ! +-----------------------------------------------------------------------------------------+ ! ! | Sub GET_OS() | ! ! | Determine the operating system. | ! ! | | ! ! | In Parameters: | ! ! | | ! ! | Out Parameters: | ! ! | g_bUNIX | ! ! | | ! ! | Local Variables: | ! ! | l_sTemp$ | ! ! | | ! ! | Procedures Called: | ! ! | | ! ! | Algorithm: | ! ! +-----------------------------------------------------------------------------------------+ ! GET_OS: ! sets g_bUNIX based on Operating System l_sTemp$ = getosname$ ! determine operating system if (l_sTemp$ = "HPUX") then g_bUNIX = 1 g_PathSep$ = "/" else g_bUNIX = 0 g_PathSep$ = "\\" endif GET_OS_EXIT: return ! +-----------------------------------------------------------------------------------------+ ! ! | Sub GET_RADII() | ! ! | Determine the center point for annulus stitching. | ! ! | | ! ! | In Parameters: | ! ! | g_XCameraSize | ! ! | g_OuterRadius | ! ! | | ! ! | Out Parameters: | ! ! | CenterX | ! ! | CenterY | ! ! | g_XStart | ! ! | g_YStart | ! ! | g_XSize | ! ! | g_YSize | ! ! | | ! ! | Local Variables: | ! ! | ret_Dialog | ! ! | X | ! ! | Y | ! ! | T_Out_X | ! ! | T_Out_Y | ! ! | | ! ! | Procedures Called: | ! ! | GET_XY | ! ! | | ! ! | Algorithm: | ! ! | Since we know the Outer Radius, all we need from the user is the location of the | ! ! | top of the outer circle. From that, we are able to calculate the center of the | ! ! | circle and set the size and start position. | ! ! +-----------------------------------------------------------------------------------------+ ! GET_RADII: g_dlgMessage$ = " Position at Top Center of Outer Radius " g_dlgStyle = DlgNormal_OK gosub DO_DIALOG gosub GET_XY X = tmp_x_pos Y = tmp_y_pos T_Out_X = X + g_XCameraSize / 2 T_Out_Y = Y CenterX = T_Out_X CenterY = T_Out_Y + g_OuterRadius g_XStart = CenterX - g_OuterRadius g_YStart = CenterY - g_OuterRadius g_XSize = (g_OuterRadius * 2) g_YSize = (g_OuterRadius * 2) GET_RADII_EXIT: return ! +-----------------------------------------------------------------------------------------+ ! ! | Sub UPDATE_LOCS() | ! ! | Determine which of the locations will have data when using Annulus Stitching. | ! ! | | ! ! | In Parameters: | ! ! | g_XPos() | ! ! | g_YPos() | ! ! | KeepWin | ! ! | g_NumMeas | ! ! | | ! ! | Out Parameters: | ! ! | g_XPos() | ! ! | g_YPos() | ! ! | xout() | ! ! | yout() | ! ! | xtmp | ! ! | ytmp | ! ! | g_NumMeas | ! ! | | ! ! | Local Variables: | ! ! | l_nTemp | ! ! | OutIndex | ! ! | | ! ! | Procedures Called: | ! ! | TEST_OVERLAP | ! ! | FIND_NEIGHBOORS | ! ! | | ! ! | Algorithm: | ! ! | 1. for each position, gosub TEST_OVERLAP to see if it covers part of the circle | ! ! | defined by g_InnerRadius, g_OuterRadius, CenterX and CenterY. | ! ! | 2. if the position covers part of the circle, save it in the next arry index | ! ! | (specified by OutIndex). | ! ! | 3. Use FIND_NEIGHBORS to traverse the circle in a counter clockwise direction. | ! ! | 4. Copy the positions into g_XPos() and g_YPos() arrays. | ! ! +-----------------------------------------------------------------------------------------+ ! UPDATE_LOCS: ! remove those locs w/o data OutIndex = 1 for l_nTemp = 1 to g_NumMeas xtmp = g_XPos(l_nTemp) ytmp = g_YPos(l_nTemp) gosub TEST_OVERLAP if (KeepWin = 1) then ! window was good, keep it xout(OutIndex) = xtmp yout(OutIndex) = ytmp OutIndex = OutIndex + 1 endif next l_nTemp ! update num of meas g_NumMeas = OutIndex - 1 ! set up sequence to traverse from one loc to closest neighboor counter clockwise gosub FIND_NEIGHBOORS ! copy new locs back into g_XPos and g_YPos for l_nTemp = 1 to g_NumMeas g_XPos(l_nTemp) = xout(l_nTemp) g_YPos(l_nTemp) = yout(l_nTemp) next l_nTemp UPDATE_LOCS_EXIT: return ! +-----------------------------------------------------------------------------------------+ ! ! | Sub FIND_NEIGHBOORS() | ! ! | Takes all the locations and sets them up so that we traverse in a counter clockwise | ! ! | order from neighboor to neighboor. Note in equation x is negated, this is to | ! ! | handle the fact that stage coords in x increase in the opposite direction then | ! ! | cartesion coords for annulus stitching. | ! ! | | ! ! | In Parameters: | ! ! | xout() | ! ! | yout() | ! ! | | ! ! | Out Parameters: | ! ! | xout() | ! ! | yout() | ! ! | | ! ! | Local Variables: | ! ! | xmin | ! ! | xmax | ! ! | ymin | ! ! | ymax | ! ! | i | ! ! | xorigin | ! ! | yorigin | ! ! | xp | ! ! | yp | ! ! | | ! ! | Procedures Called: | ! ! | | ! ! | Algorithm: | ! ! | 1. Calculate the center of the circle. | ! ! | 2. Convert positions to angles in degrees (0 to 360). | ! ! | 3. Sort angles (and positions) using an insertion sort. | ! ! +-----------------------------------------------------------------------------------------+ ! FIND_NEIGHBOORS: ! ! determine angles deg xmin = xout(1) xmax = xout(1) ymin = yout(1) ymax = yout(1) for i = 2 to g_NumMeas if (xout(i) < xmin) then xmin = xout(i) if (xout(i) > xmax) then xmax = xout(i) if (yout(i) < ymin) then ymin = yout(i) if (yout(i) > ymax) then ymax = yout(i) next i ! now we need to transform the coords so that 0,0 is in the center of the group of coords ! the assumption is made here that the coords are contiguous (a requirement of stitching) xorigin = (xmax + xmin) / 2 yorigin = (ymax + ymin) / 2 for i = 1 to g_NumMeas xp = xout(i) - xorigin yp = yout(i) - yorigin if (xp <> 0) then ! atn2() returns -PI to PI ! ang(i) = atn2(yp, -xp) ! note negation of x ! ! atn2 is not in the ApplyFunc2 part of MetroScript... if (xp = 0) then if (yp < 0) then ang(i) = -90 else ang(i) = 90 endif else ang(i) = atn(yp / -xp) if (-xp < 0) then if (yp < 0) then ang(i) = ang(i) - 180 else ang(i) = ang(i) + 180 endif endif endif else ang(i) = 0 endif if (ang(i) < 0) then ang(i) = ang(i) + 360 next i ! sort positions by angles .. insertion sort for j = 2 to g_NumMeas tmp = ang(j) xtmp = xout(j) ytmp = yout(j) i = j - 1 ANGLOOP: if (i > 0) and (ang(i) > tmp) then ang(i + 1) = ang(i) xout(i + 1) = xout(i) yout(i + 1) = yout(i) i = i - 1 goto ANGLOOP endif ang(i + 1) = tmp xout(i + 1) = xtmp yout(i + 1) = ytmp next j !gosub TEST_OVERLAP FIND_NEIGHBOORS_EXIT: return ! +-----------------------------------------------------------------------------------------+ ! ! | Sub TEST_OVERLAP() | ! ! | Determine if the given window will have data in it for annulus stitching. | ! ! | | ! ! | In Parameters: | ! ! | xtmp | ! ! | ytmp | ! ! | g_XCameraSize | ! ! | g_YCameraSize | ! ! | CenterX | ! ! | CenterY | ! ! | g_InnerRadius | ! ! | g_OuterRadius | ! ! | | ! ! | Out Parameters: | ! ! | KeepWin *return value | ! ! | | ! ! | Local Variables: | ! ! | dx | ! ! | dy | ! ! | raduisul | ! ! | raduisur | ! ! | raduisll | ! ! | raduisur | ! ! | | ! ! | Procedures Called: | ! ! | | ! ! | Algorithm: | ! ! | 1. Calculate the distance from the center point to the four corners of the | ! ! | measurement. | ! ! | 2. Do not keep window if all corners are inside the inner radius or outside the | ! ! | outer radius. | ! ! +-----------------------------------------------------------------------------------------+ ! TEST_OVERLAP: KeepWin = 1 ! upper left of window dx = xtmp + g_XCameraSize - CenterX dy = ytmp - CenterY radiusul = sqrt(dx * dx + dy * dy) ! upper right of window dx = xtmp - CenterX dy = ytmp - CenterY radiusur = sqrt(dx * dx + dy * dy) ! lower left of window dx = xtmp + g_XCameraSize - CenterX dy = ytmp + g_YCameraSize - CenterY radiusll = sqrt(dx * dx + dy * dy) ! lower right of window dx = xtmp - CenterX dy = ytmp + g_YCameraSize - CenterY radiuslr = sqrt(dx * dx + dy * dy) ! are all corners inside of the Inner Radius ? if ((radiusul < g_InnerRadius) and (radiusur < g_InnerRadius) and (radiusll < g_InnerRadius) and (radiuslr < g_InnerRadius)) then KeepWin = 0 goto TEST_OVERLAP_EXIT endif ! are all corners outside of the Outer Radius ? if ((radiusul > g_OuterRadius) and (radiusur > g_OuterRadius) and (radiusll > g_OuterRadius) and (radiuslr > g_OuterRadius)) then KeepWin = 0 goto TEST_OVERLAP_EXIT endif TEST_OVERLAP_EXIT: return ! +-----------------------------------------------------------------------------------------+ ! ! | Sub SET_FOCUS_TILT() | ! ! | Sets the Auto Focus and Auto Tilt controls. | ! ! | | ! ! | In Parameters: | ! ! | g_FocusType | ! ! | g_TiltType | ! ! | g_idAutoFocusCntl | ! ! | g_idAutoTiltCntl | ! ! | g_bFirstAutoFocus | ! ! | | ! ! | Out Parameters: | ! ! | g_bFirstAutoFocus | ! ! | | ! ! | Local Variables: | ! ! | | ! ! | Procedures Called: | ! ! | | ! ! | Algorithm: | ! ! | Sets or clears the Auto Focus and Tilt controls based on g_FocusType and g_TiltType | ! ! | First time flag for "First Time Only" types. | ! ! +-----------------------------------------------------------------------------------------+ ! SET_FOCUS_TILT: ! set auto focus if (g_FocusType = 1) then setnum(g_idAutoFocusCntl, 0, "") if (g_FocusType = 2) and (g_bFirstAutoFocus = 1) then setnum(g_idAutoFocusCntl, 1, "") if (g_FocusType = 2) and (g_bFirstAutoFocus <> 1) then setnum(g_idAutoFocusCntl, 0, "") if (g_FocusType = 3) then setnum(g_idAutoFocusCntl, 1, "") ! set auto tilt if (g_TiltType = 1) then setnum(g_idAutoTiltCntl, 0, "") if (g_TiltType = 2) and (g_bFirstAutoFocus = 1) then setnum(g_idAutoTiltCntl, 1, "") if (g_TiltType = 2) and (g_bFirstAutoFocus <> 1) then setnum(g_idAutoTiltCntl, 0, "") ! no longer the first time g_bFirstAutoFocus = 0 SET_FOCUS_TILT_EXIT: return ! +-----------------------------------------------------------------------------------------+ ! ! | Sub CHK_DISK_SIZE() | ! ! | Verifies that there is enough disk space to store the stitch data files. | ! ! | Update RAM Required and RAM Available Attributes. | ! ! | | ! ! | In Parameters: | ! ! | g_ColCount | ! ! | g_RowCount | ! ! | | ! ! | Out Parameters: | ! ! | ret_ChkDiskSize *return value | ! ! | | ! ! | Local Variables: | ! ! | x_cam_siz | ! ! | y_cam_siz | ! ! | meas_size | ! ! | total_rqd | ! ! | total_available | ! ! | l_msg$ | ! ! | ret_Dialog | ! ! | Total_RAM_Rqd | ! ! | RAM_Avail | ! ! | | ! ! | Procedures Called: | ! ! | | ! ! | Algorithm: | ! ! | Calculate the number of bytes: | ! ! | - each pixel takes 6 bytes (4 phase + 2 intensity) | ! ! | - 834 file header | ! ! | - g_ColCount * g_RowCount files .. should be NumMeas for Annulus? | ! ! +-----------------------------------------------------------------------------------------+ ! CHK_DISK_SIZE: ret_ChkDiskSize = 0 x_cam_siz = getcamsizex("") y_cam_siz = getcamsizey("") ! each pixel takes 4 bytes for phase data and 2 bytes for intensity data (6 total) meas_size = (x_cam_siz * y_cam_siz * 6) ! now add the size of the header (834 bytes) meas_size = meas_size + 834 ! total is meas_size * number of measurements total_rqd = meas_size * g_ColCount * g_RowCount ! now compare size needed with size available total_avail = getdiskfree("") ! check this disk if (total_rqd >= total_avail) then ret_ChkDiskSize = 1 g_dlgMessage$ = " The disk space required exceeds capacity, \n" g_dlgMessage$ = g_dlgMessage$ & " KBytes Required: " & val$(total_rqd / 1000) & " \n" g_dlgMessage$ = g_dlgMessage$ & " KBytes Available: " & val$(total_avail / 1000) & " \n" g_dlgMessage$ = g_dlgMessage$ & " Stitching Aborted " g_dlgStyle = DlgError_OK gosub DO_DIALOG endif ! now update Stitch RAM Attributes Total_RAM_Rqd = total_rqd * 2 RAM_Avail = getramsize setnum(g_idStchRAMRqdAttr, Total_RAM_Rqd, "") setnum(g_idStchRAMAvailAttr, RAM_Avail, "") CHK_DISK_SIZE_EXIT: return ! +-----------------------------------------------------------------------------------------+ ! ! | Sub CHK_USER_ABORT() | ! ! | Checks to see if the escape key was pressed. | ! ! | | ! ! | In Parameters: | ! ! | | ! ! | Out Parameters: | ! ! | g_bUserAbort *return value | ! ! | | ! ! | Local Variables: | ! ! | ret_Dialog | ! ! | | ! ! | Procedures Called: | ! ! | | ! ! | Algorithm: | ! ! +-----------------------------------------------------------------------------------------+ ! CHK_USER_ABORT: g_bUserAbort = 0 if (trim$(errm$) = "Processing aborted.") then g_bUserAbort = 1 ! Delete the old file if (g_bUNIX = 1) then l_nTemp = execute("rm -f UserAbort" ) else l_nTemp = execute("erase /f /q UserAbort" ) endif ! Create the new file assign @fpUserAbort to "UserAbort" "w" assign @fpUserAbort to "" else g_IgnoreError = g_IgnoreError + 1 on error gosub RESUME_NEXT ! Get a new error message l_nTemp = 1 / 0 ! Try to open the file assign @fpUserAbort to "UserAbort" "r" if ( trim$(errm$) = "Cannot open 'UserAbort' for mode 'r': No such file or directory" ) then g_bUserAbort = 0 else g_bUserAbort = 1 endif assign @fpUserAbort to "" g_IgnoreError = g_IgnoreError - 1 if ( g_IgnoreError = 0 ) then on error goto CENTRAL_ERROR_HANDLER endif return ! +-----------------------------------------------------------------------------------------+ ! ! | Sub CLEAR_USER_ABORT() | ! ! | Clears the "Processing aborted" message by putting a new error message in its place | ! ! | | ! ! | In Parameters: | ! ! | | ! ! | Out Parameters: | ! ! | | ! ! | Local Variables: | ! ! | l_nTemp | ! ! | | ! ! | Procedures Called: | ! ! | | ! ! | Algorithm: | ! ! +-----------------------------------------------------------------------------------------+ ! CLEAR_USER_ABORT: g_IgnoreError = g_IgnoreError + 1 on error gosub RESUME_NEXT if (g_bUNIX = 1) then l_nTemp = execute("rm -f UserAbort" ) else l_nTemp = execute("erase /f /q UserAbort" ) endif l_nTemp = 1 / 0 g_IgnoreError = g_IgnoreError - 1 if ( g_IgnoreError = 0 ) then on error goto CENTRAL_ERROR_HANDLER return ! +-----------------------------------------------------------------------------------------+ ! ! | Sub READ_COORDF() | ! ! | Reads a coordinate file. | ! ! | | ! ! | In Parameters: | ! ! | g_CoordFile$ | ! ! | | ! ! | Out Parameters: | ! ! | g_NumMeas | ! ! | g_bDiagnostic | ! ! | g_bAverageOverlap | ! ! | g_bFit | ! ! | g_bRemoveIntensity | ! ! | g_XMeasPos() | ! ! | g_YMeasPos() | ! ! | g_StitchFileName$ | ! ! | | ! ! | Local Variables: | ! ! | l_sTemp$ | ! ! | #CoorFile | ! ! | i | ! ! | | ! ! | Procedures Called: | ! ! | | ! ! | Algorithm: | ! ! | 1. read specific control values for stitching program. | ! ! | 2. read location of .DAT file. | ! ! | 3. read X & Y positions for .DAT file. | ! ! | 4. goto 2. | ! ! | 5. read file name of stitched data. | ! ! +-----------------------------------------------------------------------------------------+ ! !READ_COORDF: ! assign @CoorFile to g_CoordFile$ "r" ! enter @CoorFile; l_sTemp$ ! title line ! enter @CoorFile; l_sTemp$ ! number of input files ! g_NumMeas = val(l_sTemp$) ! enter @CoorFile; l_sTemp$ ! diagnostic flag ! g_bDiagnostic = val(l_sTemp$) ! enter @CoorFile; l_sTemp$ ! average overlap flag ! g_bAverageOverlap = val(l_sTemp$) ! enter @CoorFile; l_sTemp$ ! fit surfaces flag ! g_bFit = val(l_sTemp$) ! enter @CoorFile; l_sTemp$ ! Remove Intensity data flag ! g_bRemoveIntensity = val(l_sTemp$) ! ! for i = 1 to g_NumMeas ! enter @CoorFile; l_sTemp$ ! ignore filename for now ! enter @CoorFile; X, Y, Z ! read coordinates x y and z in inches ! xout(i) = X ! yout(i) = Y ! ! next i ! enter @CoorFile; g_StitchFileName$ ! assign @CoorFile to "" ! !READ_COORDF_EXIT: ! return ! +-----------------------------------------------------------------------------------------+ ! ! | Sub DO_DIALOG() | ! ! | Displays a dialog box using the given inputs. If dialog is an OK dialog, always | ! ! | returns DlgOK_Yes. If dialog is a YES/NO dialog, returns DlgOK_Yes if Yes is | ! ! | clicked or enter is pressed and returns DlgNo if No is clicked or ESC is pressed. | ! ! | | ! ! | In Parameters: | ! ! | g_dlgStyle | ! ! | g_dlgMessage$ | ! ! | | ! ! | Out Parameters: | ! ! | ret_Dialog | ! ! | | ! ! | Local Variables: | ! ! | | ! ! | Procedures Called: | ! ! | | ! ! | Algorithm: | ! ! +-----------------------------------------------------------------------------------------+ ! DO_DIALOG: ! Get the current user abort status gosub CHK_USER_ABORT old_bUserAbort = g_bUserAbort ! Set the default return value if ( (g_dlgStyle = DlgNormal_OK) or (g_dlgStyle = DlgError_OK) or (g_dlgStyle = DlgWarning_OK) ) then ret_Dialog = DlgOK_Yes else ret_Dialog = DlgNo endif ! Display the dialog g_IgnoreError = g_IgnoreError + 1 on error gosub RESUME_NEXT ret_Dialog = dialog( g_dlgMessage$, g_dlgStyle ) g_IgnoreError = g_IgnoreError - 1 if ( g_IgnoreError = 0 ) then on error goto CENTRAL_ERROR_HANDLER ! Check for ESC gosub CHK_USER_ABORT if ( (old_bUserAbort = 0) and (g_bUserAbort <> 0) ) then ! Clear the user abort message gosub CLEAR_USER_ABORT endif return ! +-----------------------------------------------------------------------------------------+ ! ! | Sub HALT_SCRIPT() | ! ! | Forces the script to stop. | ! ! | | ! ! | In Parameters: | ! ! | | ! ! | Out Parameters: | ! ! | | ! ! | Local Variables: | ! ! | | ! ! | Procedures Called: | ! ! | | ! ! | Algorithm: | ! ! +-----------------------------------------------------------------------------------------+ ! HALT_SCRIPT: end ! +-----------------------------------------------------------------------------------------+ ! ! | Sub RESUME_NEXT() | ! ! | Essentially ignores errors. | ! ! +-----------------------------------------------------------------------------------------+ ! RESUME_NEXT: error return