added RM file with User Guide
This commit is contained in:
3
.idea/StagePerformaceDocu.iml
generated
3
.idea/StagePerformaceDocu.iml
generated
@@ -8,4 +8,7 @@
|
||||
<orderEntry type="jdk" jdkName="Python 3.13 (StagePerformaceDocu)" jdkType="Python SDK" />
|
||||
<orderEntry type="sourceFolder" forTests="false" />
|
||||
</component>
|
||||
<component name="PackageRequirementsSettings">
|
||||
<option name="removeUnused" value="true" />
|
||||
</component>
|
||||
</module>
|
||||
@@ -1,5 +0,0 @@
|
||||
{
|
||||
"meas_scripts_dir": 'C:\Users\berti_r\Python_Projects\metrology\metrology'
|
||||
"meas_scripts_dir_local": r"C:\Users\berti_r\Python_Projects\StagePerformaceDocu\Scripts"
|
||||
"config_path": r"C:\Users\berti_r\Python_Projects\StagePerformaceDocu\Config\config.json"
|
||||
}
|
||||
72
README.md
72
README.md
@@ -0,0 +1,72 @@
|
||||
<h1>User Guide</h1>
|
||||
This Project has three main Components:
|
||||
<p></p>
|
||||
|
||||
<ol>
|
||||
<li>Taking Measurements</li>
|
||||
<li>Analyse the Data</li>
|
||||
<li>Results and Documentation</li>
|
||||
</ol>
|
||||
|
||||
<h3> Taking a measurement</h3>
|
||||
For all measurments working with the standard TCMC Lib the notbook
|
||||
Measurements offers a simple interface. My TwinCat project for that can be found under:_____
|
||||
|
||||
<p>Requierments:</p>
|
||||
<ol>
|
||||
<li> TwinCat Project setup acording to ESS dokumentation</li>
|
||||
<li> All libraryies installed (requirents.txt)</li>
|
||||
<li> Static paths on top of every file set</li>
|
||||
<li> Correct AMS-net Id for PLC set in metrology_functions (line52)</li>
|
||||
<li>Using the microscope X02DA-PG-USB:cam1 </li>
|
||||
<li> The X-Axis needs to be linked to the reference Axis 2</li>
|
||||
</ol>
|
||||
If another microscope is used which can use the same epics interface, the ID can be changed in the AD.py file
|
||||
<p>Location of static Paths:</p>
|
||||
<ol>
|
||||
<li> Y_Axis_Meas (line 31,36,39,55)</li>
|
||||
<li> myutility (line 58)</li>
|
||||
<li> metrology_functions (line 13-16)</li>
|
||||
</ol>
|
||||
|
||||
|
||||
<p>Meaurement types suprted by the Notebook:</p>
|
||||
<ol>
|
||||
<li> Image Test</li>
|
||||
<li> Static short term</li>
|
||||
<li> Static long term</li>
|
||||
<li> Repetability</li>
|
||||
<li> Repability motors of</li>
|
||||
</ol>
|
||||
|
||||
<h3>Y-Axis Measurements </h3>
|
||||
The used file to execute the measurement is the Y_AxisMeas.py
|
||||
|
||||
For the Y-Axis a new interface over ADS was needed. To minimize the required time for Testing
|
||||
the Y-Axis was developed with as little cohesion to the other measurement scripts as possible.
|
||||
On the beckhof side no TCMC/ESS lib was used. The interface consists of functions of the Beckhof Motion Liba linked to
|
||||
variables and some custom functions for communicating states. The communication was done with the ADS protocol
|
||||
writing/reading from GVLs. The project can be found under: _______
|
||||
|
||||
<p>Requirements:</p>
|
||||
<ol>
|
||||
<li> Custom TwinCat Project on PLC from:______</li>
|
||||
<li> All libraries installed (requirents.txt)</li>
|
||||
<li> Static paths adjusted in Y_Axis_Meas.py</li>
|
||||
<li> Correct AMS-net Id for PLC set in metrology_functions (line52)</li>
|
||||
<li> Using the microscope X02DA-PG-USB:cam1 </li>
|
||||
<li> Vertical Axis are linked to reference Axis 1 and 4 </li>
|
||||
</ol>
|
||||
|
||||
<h3> Analyzing new Data </h3>
|
||||
|
||||
For analyzing new data the notebook Measurements Analysis offers some functionalities.
|
||||
The temperature measurement needs to be added manually. In generally the newest measurement is selected by default.
|
||||
If no "conf_YearMoDa.json" is generated automatically with the measurement it must be copied from another measurement and
|
||||
the name needs to be adjusted. Especially important is the pixel size variable.
|
||||
|
||||
<h3> Results </h3>
|
||||
|
||||
Overall result of the measurements can be found in the Results notebook.
|
||||
Intermediate results are Documented in MessberichtXXXXXX notebooks where also a quick overview of the controller tuning
|
||||
process can be found.
|
||||
@@ -310,7 +310,7 @@ if __name__ == "__main__":
|
||||
#plc.write_by_name("GVL.StopCmd", False, pyads.PLCTYPE_BOOL)
|
||||
#moveAbsolut(plc, 0, 37.68, 3)
|
||||
#executeCmd(plc)
|
||||
cyclic_meas(plc,[30,37.68],[5,25],100)
|
||||
cyclic_meas(plc,[30,37.68],[5,25 ],100)
|
||||
#time.sleep(3)
|
||||
disableAxis(plc)
|
||||
gearout(plc)
|
||||
@@ -8,9 +8,13 @@ import sys
|
||||
import scipy.ndimage as spnd
|
||||
import threading as th
|
||||
from scipy.optimize import curve_fit
|
||||
from skimage.io import imshow
|
||||
|
||||
from utils import get_datestr, get_timestr
|
||||
|
||||
config_path = r"C:\Users\berti_r\Python_Projects\StagePerformaceDocu\Config\config.json" #Path to the config file which has the parameters for the next measurement
|
||||
library_path = r"C:\Users\berti_r\Python_Projects\templates\motion_libs" #Path to the motion function lib (ESS based)
|
||||
measurement_mov_path = r"C:\Users\berti_r\Python_Projects\StagePerformaceDocu\Config\measurement.json"
|
||||
workdir = \
|
||||
os.path.expanduser(rf'C:\Users\berti_r\Python_Projects\StagePerformaceDocu\data\data{get_datestr()}_alignment_tests')
|
||||
#error chatchign and hard code catch stuff
|
||||
|
||||
def check_path(path_str):
|
||||
@@ -21,30 +25,24 @@ def check_path(path_str):
|
||||
print(f"Path exists: {path_str}")
|
||||
except FileNotFoundError as e:
|
||||
print(f"Error: {e}")
|
||||
config_path = r"C:\Users\berti_r\Python_Projects\StagePerformaceDocu\Config\config.json"
|
||||
|
||||
check_path(config_path)
|
||||
|
||||
|
||||
|
||||
library_path = r"C:\Users\berti_r\Python_Projects\templates\motion_libs"
|
||||
check_path(library_path)
|
||||
sys.path.append(library_path)
|
||||
measurement_mov_path = r"C:\Users\berti_r\Python_Projects\StagePerformaceDocu\Config\measurement.json"
|
||||
check_path(measurement_mov_path)
|
||||
|
||||
import motionFunctionsLib as mfl # ToDo: comment out when using torque test
|
||||
from PIL import Image, ImageDraw
|
||||
import numpy as np
|
||||
from image_analysis import image_center_of_mass
|
||||
from utils import get_datestr, get_timestr
|
||||
|
||||
import ad
|
||||
import myutility as myu
|
||||
import cv2
|
||||
import json
|
||||
import shutil
|
||||
|
||||
workdir = \
|
||||
os.path.expanduser(rf'C:\Users\berti_r\Python_Projects\StagePerformaceDocu\data\data{get_datestr()}_alignment_tests')
|
||||
|
||||
if not os.path.exists(workdir):
|
||||
os.makedirs(workdir)
|
||||
|
||||
@@ -175,12 +173,6 @@ def __process_img(img , retimg=0):
|
||||
|
||||
x = popt[1]
|
||||
y = popt[2]
|
||||
#result , path = gradient_ascent(img, (x_gues, y_gues))
|
||||
#x,y = result
|
||||
#y,x = np.unravel_index(np.argmax(z), z.shape)
|
||||
"""ret1, th1 = cv2.threshold(z, 40, 1, cv2.THRESH_BINARY)
|
||||
z = z * th1
|
||||
x, y = image_center_of_mass(th1, plot=False, verbose=False)"""
|
||||
if retimg:
|
||||
return x,y,z
|
||||
return x, y
|
||||
@@ -294,117 +286,7 @@ def run_repeatability_series(
|
||||
del camera
|
||||
|
||||
|
||||
def run_repeatability_series_K(
|
||||
motor_pv_prefix=0, ntries=100, save_images=True, run_analysis=False):
|
||||
# improv
|
||||
exit(-1)
|
||||
ntries = init_nr_of_cycles()
|
||||
print(f"started with {ntries} cycles")
|
||||
if os.getenv("EPICS_CA_ADDR_LIST") is not None:
|
||||
pass
|
||||
else:
|
||||
os.environ["EPICS_CA_ADDR_LIST"] = "129.129.181.64"
|
||||
|
||||
camera = ad.AD()
|
||||
pixel_size = 1.1
|
||||
|
||||
savedir = os.path.join(workdir,
|
||||
f'{get_timestr()}_repeatibility_{motor_pv_prefix}')
|
||||
safe_meas_settings(savedir)
|
||||
savefile = os.path.join(savedir,
|
||||
f'repeatibility_{motor_pv_prefix}.dat')
|
||||
os.makedirs(savedir)
|
||||
camera.start()
|
||||
|
||||
# enable axis clean up later
|
||||
|
||||
axis1.setAcceleration(5.0)
|
||||
axis1.setDeceleration(5.0)
|
||||
axis1.setVelocity(3)
|
||||
axis1.disableAxis()
|
||||
sleep(1)
|
||||
axis1.enableAxis()
|
||||
|
||||
|
||||
sleep(1)
|
||||
|
||||
axis4.setAcceleration(5.0)
|
||||
axis4.setDeceleration(5.0)
|
||||
axis4.setVelocity(3)
|
||||
|
||||
axis4.disableAxis()
|
||||
sleep(1)
|
||||
axis4.enableAxis()
|
||||
sleep(1)
|
||||
|
||||
# --------------------------------------load coordinates from file-----------------------
|
||||
x_coordinates_json = myu.load_object(measurement_mov_path)
|
||||
x_coordinates = x_coordinates_json.get('std_test_mov')
|
||||
wait_x_json = myu.load_object(measurement_mov_path)
|
||||
wait_x = wait_x_json.get('std_test_wait')
|
||||
print("WaitPattern: ",wait_x)
|
||||
print("movPattern",x_coordinates)
|
||||
start1 = axis1.getActPos()
|
||||
print("start1",start1)
|
||||
print("target1",start1+x_coordinates[0])
|
||||
start4 = axis4.getActPos()
|
||||
|
||||
for i in range(ntries):
|
||||
# ---------------------------------------------move------------------------------------------
|
||||
# add multithreading for simultanious movement of y and x axis
|
||||
for mov, wait in zip(x_coordinates, wait_x):
|
||||
t1 = start1+mov
|
||||
print("t1",t1)
|
||||
while axis1.getMovingStatus() or axis4.getMovingStatus():
|
||||
print("waiting on axis")
|
||||
axis4.moveAbsolute(start4+(mov))
|
||||
axis1.moveAbsolute(t1)
|
||||
sleep(0.05)
|
||||
|
||||
|
||||
sleep(wait)
|
||||
start_pos_rbv = 4 # ????
|
||||
meas_pos_rbv = 5 # ????
|
||||
# ---------------------------------------------capture------------------------------------------
|
||||
x_array = []
|
||||
y_array = []
|
||||
for nr_img in range(10):
|
||||
sleep(0.1)
|
||||
im = camera.get_image()
|
||||
sleep(0.1)
|
||||
|
||||
if (1 == init_image_processing_yes_no()):
|
||||
|
||||
com_x_tmp, com_y_tmp = __process_img(im)
|
||||
else:
|
||||
com_x_tmp, com_y_tmp = image_center_of_mass(im, plot=False, verbose=False)
|
||||
x_array.append(com_x_tmp)
|
||||
y_array.append(com_y_tmp)
|
||||
com_x = np.average(x_array)
|
||||
com_y = np.average(y_array)
|
||||
|
||||
data_str = " {:6d} {:18f} {:18f} {:8.3f} {:8.3f} {:14.3f}\n".format(
|
||||
i, start_pos_rbv, meas_pos_rbv, com_x, com_y, time.time())
|
||||
print(data_str, end='')
|
||||
# -------------------------------------------Save----------------------------------------------------
|
||||
with open(savefile, 'a') as fh:
|
||||
fh.write(data_str)
|
||||
|
||||
if save_images:
|
||||
imobj = Image.fromarray(im)
|
||||
imfile = os.path.join(savedir,
|
||||
f'im_{i:05d}.tif')
|
||||
imobj.save(imfile)
|
||||
|
||||
# --------------------------------------------analyse----------------------------------------------
|
||||
if run_analysis:
|
||||
print("")
|
||||
analyze_repeatability(savefile, pixel_size=pixel_size, units='um')
|
||||
# -----------------------------------------cleanup-----------------------------------------
|
||||
|
||||
axis2.disableAxis()
|
||||
camera.stop()
|
||||
del camera
|
||||
|
||||
|
||||
def run_repeatability_series_motor_off(
|
||||
@@ -452,8 +334,8 @@ def run_repeatability_series_motor_off(
|
||||
for mov, wait in zip(x_coordinates, wait_x):
|
||||
axis2.moveRelativeAndWait(mov)
|
||||
sleep(wait)
|
||||
start_pos_rbv = 4 # ????
|
||||
meas_pos_rbv = 5 # ????
|
||||
start_pos_rbv = 4 # <-- only for perceiving the original formating of the measurement file
|
||||
meas_pos_rbv = 5 # <-- only for perceiving the original formating of the measurement file
|
||||
axis2.disableAxis()
|
||||
# ---------------------------------------------capture------------------------------------------
|
||||
x_array = []
|
||||
@@ -577,11 +459,7 @@ def analyze_repeatability(input_file, pixel_size, units='um'):
|
||||
'Y-neg', p2v_y_neg, rms_y_neg, sigma_y_neg, 3*sigma_y_neg))
|
||||
|
||||
print(result_str)
|
||||
"""
|
||||
result_file = os.path.splitext(input_file)[0] + "_results.dat"
|
||||
with open(result_file, 'w') as fh:
|
||||
fh.write(result_str)
|
||||
print(f"Results saved in: {result_file:s}")"""
|
||||
|
||||
|
||||
def plot_repeatability(
|
||||
ax, index, com, mean, p2v, rms, pos_mask, neg_mask):
|
||||
@@ -650,6 +528,7 @@ def camera_thread_function( img_queue):
|
||||
if os.getenv("EPICS_CA_ADDR_LIST") is not None:
|
||||
pass
|
||||
else:
|
||||
print("EPICS_CA_ADDR_LIST environment variable not set, if it fails after that change IP in metrology_functions.py line 532")
|
||||
os.environ["EPICS_CA_ADDR_LIST"] = "129.129.181.64"
|
||||
|
||||
camera = ad.AD()
|
||||
|
||||
7848
notebooks/Results.html
Normal file
7848
notebooks/Results.html
Normal file
File diff suppressed because one or more lines are too long
@@ -0,0 +1,15 @@
|
||||
numpy~=2.2.6
|
||||
plumbum~=1.9.0
|
||||
pyads~=3.5.0
|
||||
matplotlib~=3.10.3
|
||||
scipy~=1.16.0
|
||||
opencv-python~=4.12.0.88
|
||||
pillow~=11.3.0
|
||||
scikit-learn~=1.7.1
|
||||
scikit-image~=0.25.2
|
||||
pandas~=2.3.1
|
||||
seaborn~=0.13.2
|
||||
ipywidgets~=8.1.7
|
||||
ipython~=9.4.0
|
||||
webcolors~=24.11.1
|
||||
tifffile~=2025.6.11
|
||||
Reference in New Issue
Block a user