Commit 13360453 authored by Dominique Piche's avatar Dominique Piche

add automatic source position calculator

parent f3d858f6
......@@ -2,6 +2,7 @@ import socket
import sys
import time
from threading import Timer
import os
import numpy as np
......@@ -178,7 +179,7 @@ class MecaRobot:
is written in a file.
"""
self.is_tracking = True
self.data = open('tracking_data.txt', 'w+')
self.data = open(os.path.join(current_path, 'Data/tracking_data.txt'), 'w+')
self.data.write('Time [s], TRF position [mm]')
self.data.write('\n')
self.start_time = time.time()
......
......@@ -49,14 +49,22 @@ class MecaRobotForDosimetry(MecaRobot):
self.number_of_scintillators = len(scintillators_positions)
self.source_position = source_position
if analog_input_channels is not None:
self.number_of_input_channels = len(analog_input_channels)
if analog_output_channels is not None:
self.number_of_output_channels = len(analog_output_channels)
# Connecting to the NI_DAQ board
if measure_with_nidaq:
self.daq_board = DAQ_Volt_Tracking(daq_path_number=daq_path_number,
input_channels=analog_input_channels,
output_channels=analog_output_channels,
number_of_measures_per_position=10000)
number_of_measures_per_position=1000)
self.daq_board.start()
self.source_offset = np.array([0, 0, 0])
# Setting the last scintillator as the tool reference frame (TRF).
self.run('SetTRF', [scintillators_positions[-1], 0, 4.5, 0, -90, 0])
......@@ -68,6 +76,13 @@ class MecaRobotForDosimetry(MecaRobot):
self.is_tracking = True
current_path = os.getcwd()
with open(os.path.join(current_path, 'Data/general_info.txt'), 'w+') as file:
file.write('Date and time : ')
file.write(time.strftime("%Y-%m-%d %H:%M:%S"))
file.write('\nSource position : ')
file.write(np.array2string(self.source_position, separator=',')[1:-1])
file.write('\nApplied source offset : ')
file.write(np.array2string(self.source_offset)[1:-1])
# Creating time file
self.time_file = open(os.path.join(current_path, 'Data/time.txt'), 'w+')
......@@ -94,6 +109,7 @@ class MecaRobotForDosimetry(MecaRobot):
def _track_data(self):
scintillators_positions_relative_to_source = self.get_scintillators_positions_relative_to_source()
scintillators_distance_to_source = np.linalg.norm(scintillators_positions_relative_to_source, axis=1)
scintillators_signal = self.get_scintillators_signal()
# Writing current time in time file
self.time_file.write(str(time.time()-self.start_time) + '\n')
......@@ -110,7 +126,6 @@ class MecaRobotForDosimetry(MecaRobot):
# Writing the scintillators' signal in the signal file
if self.measure_with_nidaq:
scintillators_signal = self.daq_board.read_measure()
self.scintillators_signal_file.write(np.array2string(scintillators_signal, separator=',')[1:-1] + '\n')
def stop_tracking(self):
......@@ -136,6 +151,14 @@ class MecaRobotForDosimetry(MecaRobot):
if self.measure_with_nidaq:
self.daq_board.close()
def get_scintillators_signal(self) -> np.ndarray:
"""
Reads one sample of the NI DAQ board to get the scintillators' signal. Returns every input channel in
an array.
"""
# TODO : add to doc
return self.daq_board.read_measure()
def get_scintillators_positions(self) -> np.ndarray:
"""
Returns an array of the positions of each scintillator in relation to the world reference
......@@ -179,13 +202,84 @@ class MecaRobotForDosimetry(MecaRobot):
def set_source_position(self, source_position_relative_to_TRF: np.ndarray):
"""
Sets the source position. Takes the current source position in relation to the TRF.
Sets the source position. Takes the current source position in relation to the TRF. The user has to ensure the robot is at
a complete stop before running this method.
"""
self.wait_for('3004', 'Did not receive EOM')
pose = self.get_TRF_pose()
TRF_position = pose[0:3]
self.source_position = TRF_position + source_position_relative_to_TRF
def find_source_positions(self):
"""
Automatically finds the source's position by moving along every axis near the source until we get the maximum signal.
This assumes that an estimate of the source position as already been set, as it will move around this poins to find
the maximum.
"""
self.clear_buffer()
x_axis_signal = np.zeros((100,self.number_of_input_channels))
y_axis_signal = np.zeros((100,self.number_of_input_channels))
z_axis_signal = np.zeros((200,self.number_of_input_channels))
# Moving the robot near the source
self.move_position_relative_to_source(np.array([-5,50,0]))
self.move_position_relative_to_source(np.array([-5,15,0]))
self.wait_for('3012', 'Did not receive EOB.')
# Moving alond the x axis
for i in range(100):
self.run('MoveLinRelTRF', [0.1,0,0,0,0,0])
self.wait_for('3012', 'Did not receive EOB')
x_axis_signal[i] = self.get_scintillators_signal()
# Moving the robot near the source
self.move_position_relative_to_source(np.array([-10,50,0]))
self.move_position_relative_to_source(np.array([-50,-5,0]))
self.move_position_relative_to_source(np.array([-15,-5,0]))
self.wait_for('3012', 'Did not receive EOB.')
# Moving along the y axis
for i in range(100):
self.run('MoveLinRelTRF', [0,0.1,0,0,0,0])
self.wait_for('3012', 'Did not receive EOB.')
y_axis_signal[i] = self.get_scintillators_signal()
# Moving the robot near the source
self.move_position_relative_to_source(np.array([-50,-5,0]))
self.move_position_relative_to_source(np.array([0,50,-10]))
self.move_position_relative_to_source(np.array([0,15,-10]))
# Moving along the z-axis
for i in range(200):
self.run('MoveLinRelTRF', [0,0,0.1,0,0,0])
self.wait_for('3012', 'Did not receive EOB.')
z_axis_signal[i] = self.get_scintillators_signal()
self.move_position_relative_to_source(np.array([0,50,-10]))
self.zero_joints()
self.wait_for('3012', 'Did not receive EOB.')
x_max = np.argmax(np.linalg.norm(x_axis_signal, axis=1))*0.1-4.9
y_max = np.argmax(np.linalg.norm(y_axis_signal, axis=1))*0.1-4.9
z_max = np.argmax(np.linalg.norm(z_axis_signal, axis=1))*0.1-9.9
np.savetxt('Data/x_calibration_data.txt', x_axis_signal, delimiter = ',')
np.savetxt('Data/y_calibration_data.txt', y_axis_signal, delimiter = ',')
np.savetxt('Data/z_calibration_data.txt', z_axis_signal, delimiter = ',')
# with open('Data/x_calibration_data.txt', 'w+') as fichier:
# fichier.write(np.array2string(x_axis_signal))
# with open('Data/y_calibration_data.txt', 'w+') as fichier:
# fichier.write(np.array2string(y_axis_signal))
# with open('Data/z_calibration_data.txt', 'w+') as fichier:
# fichier.write(np.array2string(z_axis_signal))
self.source_offset = np.array([x_max, y_max, z_max])
self.source_position = self.source_position + self.source_offset
def move_position_relative_to_source(self, position: np.ndarray):
"""
Moves the lowest scintillator (TRF) to a given position in the form (x,y,z) relative to the source position.
......
......@@ -33,7 +33,8 @@ class DAQ_Volt_Tracking:
self.write_task.ao_channels.add_ao_voltage_chan(channel_name, max_val=1, min_val=0.9999)
Finite_Mode = nidaqmx.constants.AcquisitionType(10178)
self.read_task.timing.cfg_samp_clk_timing(rate=self.sample_rate, samps_per_chan=10000000, sample_mode=Finite_Mode)
Cont_Mode = nidaqmx.constants.AcquisitionType(10123) # Continious acquisition
#self.read_task.timing.cfg_samp_clk_timing(rate=self.sample_rate, samps_per_chan=10000000, sample_mode=Finite_Mode)
self.reader = AnalogMultiChannelReader(self.read_task.in_stream)
self.writer = AnalogMultiChannelWriter(self.write_task.out_stream)
......@@ -47,6 +48,8 @@ class DAQ_Volt_Tracking:
self.writer.write_one_sample(np.ones(self.number_of_output_channels, dtype=np.float64))
def close(self):
#self.writer.write_one_sample(np.zeros(self.number_of_output_channels, dtype=np.float64))
warnings.filterwarnings('error')
# Stoping tasks
try:
......@@ -63,7 +66,7 @@ class DAQ_Volt_Tracking:
def read_measure(self):
# Reading the channels
measure = np.zeros((self.number_of_input_channels, self.number_of_measures_per_position), dtype=np.float64)
self.reader.read_many_sample(measure, number_of_samples_per_channel=self.number_of_measures_per_position, timeout=0.5)
self.reader.read_many_sample(measure, number_of_samples_per_channel=self.number_of_measures_per_position, timeout=10)
# Waiting to ensure the measurement is complete
time.sleep(self.number_of_measures_per_position/self.sample_rate)
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment