From 3679d9c9eca935f32a3303eaad7d9543cccdc691 Mon Sep 17 00:00:00 2001 From: oscarxblanco Date: Sun, 5 Feb 2023 22:30:49 +0100 Subject: [PATCH 01/11] first IdTablePass commit --- pyat/at/lattice/elements.py | 166 +++++++++++++++++++++++++++++++++++- 1 file changed, 165 insertions(+), 1 deletion(-) diff --git a/pyat/at/lattice/elements.py b/pyat/at/lattice/elements.py index 2caca0da3..74262672e 100644 --- a/pyat/at/lattice/elements.py +++ b/pyat/at/lattice/elements.py @@ -11,7 +11,8 @@ from copy import copy, deepcopy from abc import ABC from typing import Optional, Generator, Tuple, List, Iterable - +import io +from scipy.constants import c as clight def _array(value, shape=(-1,), dtype=numpy.float64): # Ensure proper ordering(F) and alignment(A) for "C" access in integrators @@ -1044,6 +1045,169 @@ def __init__(self, family_name: str, lmatp: numpy.ndarray, **kwargs): super().__init__(family_name, Lmatp=lmatp, **kwargs) +class InsertionDevice(Element): + """ + Insertion Device Element. Valid for a parallel electron beam. + + Pascale ELLEAUME, "A New Approach to the Electron Beam Dynamics in + Undulators and Wigglers". EPAC1992 0661. + European Synchrotron Radiation Facility. + BP 220, F-38043 Grenoble, France + """ + _BUILD_ATTRIBUTES = Element._BUILD_ATTRIBUTES + ['Nslice', + 'Filename_in', + 'Energy'] + + def readRadiaFieldMap(self, file_in_name): + """ + Read a RadiaField map and return + """ + with io.open(file_in_name, mode="r", encoding="utf-8") as f: + """ + File, where : + - the first data line is the length in meters + - the second data line is the number of points in the h. plane + - the third data line is the number of points in the v. plane + - each data block comes after a START + - first the horizontal data block, and second the vertical data block + - each block is a table with axes + - comments start with # + """ + ### File example: + # #comment in line 1 + # #comment in line 2 + # Length_in_m + # #comment in line 4 + # Number of points in horizontal plane :nh + # #comment in line 6 + # Number of points in vertical plane :nv + # #comment in line 8 + # START + # pos_point1h pos_point2h ... pos_pointnh + # pos_point1v + # ... horizontal kick_map(nv,nh) + # pos_pointnv + # START + # pos_point1h pos_point2h ... pos_pointnh + # pos_point1v + # ... vertical kick_map(nv,nh) + # pos_pointnv + # (EOL) + + data_lines = 0; # line not starting with '#' + header_lines = 0; # line starting with '#' + block_counter = 0; # START of the hor. map and START of the vert. map + for line in f: + sline = line.split() + if sline[0] == '#': # line is comment + header_lines += 1; + else: + data_lines += 1; + if data_lines == 1: el_length = float(sline[0]); # get the element length + elif data_lines == 2: h_points = int(sline[0]); # get the number of horizontal points + elif data_lines == 3: + # get the number of vertical points + v_points = int(sline[0]); + # initialize element kicks and table_axes + kick_map = np.zeros((v_points,h_points)); + haxis = np.zeros(h_points); + vaxis = np.zeros(v_points); + else: + # read block of data + if sline[0] == "START" or sline[0] == "START\n" : + block_counter += 1; + block_lines = 0; + if block_lines == 1: haxis = sline; + if block_lines > 1: + # minus one due to python index starting at zero + # and minus another one due to the column labels in first line + vaxis[block_lines - 2] = float(sline[0]); + kick_map[block_lines - 2][:] = sline[1:]; + if block_lines > v_points: + block_lines = 0; + if block_counter == 1: + hkickmap = np.copy(kick_map); + table_cols1 = haxis; + table_rows1 = vaxis; + if block_counter == 2: + vkickmap = np.copy(kick_map); + table_cols2 = haxis; + table_rows2 = vaxis; + block_lines += 1; + + + return el_length, hkickmap, vkickmap, table_cols1, table_rows1, table_cols2, table_rows2 + + def sorted_table(self, table_in, sorted_index, order_axis): + # np.asfortranarray makes a copy of contiguous memory positions + table_out = np.copy(table_in); + for i,iis in zip(range(len(sorted_index)), sorted_index): + if order_axis == 'col': table_out[:,i] = table_in[ : ,iis] + if order_axis == 'row': table_out[i,:] = table_in[iis, : ] + table_out2 = np.asfortranarray(table_out) + return table_out2 + + def __init__(self, family_name: str, Nslice: float, Filename_in: str, Energy: float, **kwargs): + """ + Args: + family_name: family name + Nslice: number of slices in ... tracking??? integrator ??? + Filename_in: input filename + Energy: particle energy in GeV + + Default PassMethod: ``IdTablePass`` + """ + # 2023jan18 fix bug with element print + # 2023jan15 first release + # orblancog + ## read the input data + el_length, hkickmap, vkickmap, table_cols1, table_rows1, table_cols2, table_rows2 \ + = self.readRadiaFieldMap(Filename_in); + + ## set to float + table_cols1array = np.array(table_cols1, dtype='float64'); + table_rows1array = np.array(table_rows1, dtype='float64'); + table_cols2array = np.array(table_cols2, dtype='float64'); + table_rows2array = np.array(table_rows2, dtype='float64'); + + ## Reorder table_axes and kick maps + cols1sorted_index = np.argsort(table_cols1array); table_cols1array.sort(); + rows1sorted_index = np.argsort(table_rows1array); table_rows1array.sort(); + cols2sorted_index = np.argsort(table_cols2array); table_cols2array.sort(); + rows2sorted_index = np.argsort(table_rows2array); table_rows2array.sort(); + hkickmap_a = self.sorted_table(hkickmap, cols1sorted_index, 'col'); + hkickmap = self.sorted_table(hkickmap_a, rows1sorted_index, 'row'); + vkickmap_a = self.sorted_table(vkickmap, cols2sorted_index, 'col'); + vkickmap = self.sorted_table(vkickmap_a, rows2sorted_index, 'row'); + + ## Field to kick factors + Brho = 1e9 * Energy/clight + factor = 1/(Brho**2) + xkick = factor * hkickmap + ykick = factor * vkickmap + factor1 = -1/(Brho) + xtable = table_cols1array + ytable = table_rows1array + + ## Create element properties + kwargs.setdefault('PassMethod', 'IdTablePass') + kwargs.setdefault('Filename_in', Filename_in) + kwargs.setdefault('Energy', Energy) + kwargs.setdefault('Nslice', Nslice) + kwargs.setdefault('Length', el_length) + kwargs.setdefault('xkick', xkick) + kwargs.setdefault('ykick', ykick) + kwargs.setdefault('xtable', xtable) + kwargs.setdefault('ytable', ytable) + + ## Set Element inherited properties + # pyat issue #522 + #elem = Element('name', PassMethod='IdTablePass', xkick=x0, ykick=x1, \ + # xtable=x2, ytable=x3, Nslice=x4) + super(InsertionDevice, self).__init__(family_name, **kwargs) + + + def build_class_map(): # Missing class aliases (Bend) global CLASS_MAP From 7dfc1df256605785ed15818a22400e958facce95 Mon Sep 17 00:00:00 2001 From: oscarxblanco Date: Sun, 5 Feb 2023 22:33:53 +0100 Subject: [PATCH 02/11] np is now numpy --- pyat/at/lattice/elements.py | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/pyat/at/lattice/elements.py b/pyat/at/lattice/elements.py index 74262672e..84d0d636e 100644 --- a/pyat/at/lattice/elements.py +++ b/pyat/at/lattice/elements.py @@ -1109,9 +1109,9 @@ def readRadiaFieldMap(self, file_in_name): # get the number of vertical points v_points = int(sline[0]); # initialize element kicks and table_axes - kick_map = np.zeros((v_points,h_points)); - haxis = np.zeros(h_points); - vaxis = np.zeros(v_points); + kick_map = numpy.zeros((v_points,h_points)); + haxis = numpy.zeros(h_points); + vaxis = numpy.zeros(v_points); else: # read block of data if sline[0] == "START" or sline[0] == "START\n" : @@ -1126,11 +1126,11 @@ def readRadiaFieldMap(self, file_in_name): if block_lines > v_points: block_lines = 0; if block_counter == 1: - hkickmap = np.copy(kick_map); + hkickmap = numpy.copy(kick_map); table_cols1 = haxis; table_rows1 = vaxis; if block_counter == 2: - vkickmap = np.copy(kick_map); + vkickmap = numpy.copy(kick_map); table_cols2 = haxis; table_rows2 = vaxis; block_lines += 1; @@ -1139,12 +1139,12 @@ def readRadiaFieldMap(self, file_in_name): return el_length, hkickmap, vkickmap, table_cols1, table_rows1, table_cols2, table_rows2 def sorted_table(self, table_in, sorted_index, order_axis): - # np.asfortranarray makes a copy of contiguous memory positions - table_out = np.copy(table_in); + # numpy.asfortranarray makes a copy of contiguous memory positions + table_out = numpy.copy(table_in); for i,iis in zip(range(len(sorted_index)), sorted_index): if order_axis == 'col': table_out[:,i] = table_in[ : ,iis] if order_axis == 'row': table_out[i,:] = table_in[iis, : ] - table_out2 = np.asfortranarray(table_out) + table_out2 = numpy.asfortranarray(table_out) return table_out2 def __init__(self, family_name: str, Nslice: float, Filename_in: str, Energy: float, **kwargs): @@ -1165,16 +1165,16 @@ def __init__(self, family_name: str, Nslice: float, Filename_in: str, Energy: fl = self.readRadiaFieldMap(Filename_in); ## set to float - table_cols1array = np.array(table_cols1, dtype='float64'); - table_rows1array = np.array(table_rows1, dtype='float64'); - table_cols2array = np.array(table_cols2, dtype='float64'); - table_rows2array = np.array(table_rows2, dtype='float64'); + table_cols1array = numpy.array(table_cols1, dtype='float64'); + table_rows1array = numpy.array(table_rows1, dtype='float64'); + table_cols2array = numpy.array(table_cols2, dtype='float64'); + table_rows2array = numpy.array(table_rows2, dtype='float64'); ## Reorder table_axes and kick maps - cols1sorted_index = np.argsort(table_cols1array); table_cols1array.sort(); - rows1sorted_index = np.argsort(table_rows1array); table_rows1array.sort(); - cols2sorted_index = np.argsort(table_cols2array); table_cols2array.sort(); - rows2sorted_index = np.argsort(table_rows2array); table_rows2array.sort(); + cols1sorted_index = numpy.argsort(table_cols1array); table_cols1array.sort(); + rows1sorted_index = numpy.argsort(table_rows1array); table_rows1array.sort(); + cols2sorted_index = numpy.argsort(table_cols2array); table_cols2array.sort(); + rows2sorted_index = numpy.argsort(table_rows2array); table_rows2array.sort(); hkickmap_a = self.sorted_table(hkickmap, cols1sorted_index, 'col'); hkickmap = self.sorted_table(hkickmap_a, rows1sorted_index, 'row'); vkickmap_a = self.sorted_table(vkickmap, cols2sorted_index, 'col'); From 0bd0d0db6db377cd145f13bc5311808718538ed1 Mon Sep 17 00:00:00 2001 From: oscarxblanco Date: Sun, 5 Feb 2023 22:59:07 +0100 Subject: [PATCH 03/11] fix spacing in import --- pyat/at/lattice/elements.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyat/at/lattice/elements.py b/pyat/at/lattice/elements.py index 84d0d636e..b8a3ba4cf 100644 --- a/pyat/at/lattice/elements.py +++ b/pyat/at/lattice/elements.py @@ -12,7 +12,7 @@ from abc import ABC from typing import Optional, Generator, Tuple, List, Iterable import io -from scipy.constants import c as clight +from scipy.constants import c as clight def _array(value, shape=(-1,), dtype=numpy.float64): # Ensure proper ordering(F) and alignment(A) for "C" access in integrators From db605ecfa339e5d53c2167074f99d42321cdcdea Mon Sep 17 00:00:00 2001 From: oscarxblanco Date: Thu, 9 Feb 2023 15:03:56 +0100 Subject: [PATCH 04/11] restoring elements from master --- pyat/at/lattice/elements.py | 166 +----------------------------------- 1 file changed, 1 insertion(+), 165 deletions(-) diff --git a/pyat/at/lattice/elements.py b/pyat/at/lattice/elements.py index b8a3ba4cf..2caca0da3 100644 --- a/pyat/at/lattice/elements.py +++ b/pyat/at/lattice/elements.py @@ -11,8 +11,7 @@ from copy import copy, deepcopy from abc import ABC from typing import Optional, Generator, Tuple, List, Iterable -import io -from scipy.constants import c as clight + def _array(value, shape=(-1,), dtype=numpy.float64): # Ensure proper ordering(F) and alignment(A) for "C" access in integrators @@ -1045,169 +1044,6 @@ def __init__(self, family_name: str, lmatp: numpy.ndarray, **kwargs): super().__init__(family_name, Lmatp=lmatp, **kwargs) -class InsertionDevice(Element): - """ - Insertion Device Element. Valid for a parallel electron beam. - - Pascale ELLEAUME, "A New Approach to the Electron Beam Dynamics in - Undulators and Wigglers". EPAC1992 0661. - European Synchrotron Radiation Facility. - BP 220, F-38043 Grenoble, France - """ - _BUILD_ATTRIBUTES = Element._BUILD_ATTRIBUTES + ['Nslice', - 'Filename_in', - 'Energy'] - - def readRadiaFieldMap(self, file_in_name): - """ - Read a RadiaField map and return - """ - with io.open(file_in_name, mode="r", encoding="utf-8") as f: - """ - File, where : - - the first data line is the length in meters - - the second data line is the number of points in the h. plane - - the third data line is the number of points in the v. plane - - each data block comes after a START - - first the horizontal data block, and second the vertical data block - - each block is a table with axes - - comments start with # - """ - ### File example: - # #comment in line 1 - # #comment in line 2 - # Length_in_m - # #comment in line 4 - # Number of points in horizontal plane :nh - # #comment in line 6 - # Number of points in vertical plane :nv - # #comment in line 8 - # START - # pos_point1h pos_point2h ... pos_pointnh - # pos_point1v - # ... horizontal kick_map(nv,nh) - # pos_pointnv - # START - # pos_point1h pos_point2h ... pos_pointnh - # pos_point1v - # ... vertical kick_map(nv,nh) - # pos_pointnv - # (EOL) - - data_lines = 0; # line not starting with '#' - header_lines = 0; # line starting with '#' - block_counter = 0; # START of the hor. map and START of the vert. map - for line in f: - sline = line.split() - if sline[0] == '#': # line is comment - header_lines += 1; - else: - data_lines += 1; - if data_lines == 1: el_length = float(sline[0]); # get the element length - elif data_lines == 2: h_points = int(sline[0]); # get the number of horizontal points - elif data_lines == 3: - # get the number of vertical points - v_points = int(sline[0]); - # initialize element kicks and table_axes - kick_map = numpy.zeros((v_points,h_points)); - haxis = numpy.zeros(h_points); - vaxis = numpy.zeros(v_points); - else: - # read block of data - if sline[0] == "START" or sline[0] == "START\n" : - block_counter += 1; - block_lines = 0; - if block_lines == 1: haxis = sline; - if block_lines > 1: - # minus one due to python index starting at zero - # and minus another one due to the column labels in first line - vaxis[block_lines - 2] = float(sline[0]); - kick_map[block_lines - 2][:] = sline[1:]; - if block_lines > v_points: - block_lines = 0; - if block_counter == 1: - hkickmap = numpy.copy(kick_map); - table_cols1 = haxis; - table_rows1 = vaxis; - if block_counter == 2: - vkickmap = numpy.copy(kick_map); - table_cols2 = haxis; - table_rows2 = vaxis; - block_lines += 1; - - - return el_length, hkickmap, vkickmap, table_cols1, table_rows1, table_cols2, table_rows2 - - def sorted_table(self, table_in, sorted_index, order_axis): - # numpy.asfortranarray makes a copy of contiguous memory positions - table_out = numpy.copy(table_in); - for i,iis in zip(range(len(sorted_index)), sorted_index): - if order_axis == 'col': table_out[:,i] = table_in[ : ,iis] - if order_axis == 'row': table_out[i,:] = table_in[iis, : ] - table_out2 = numpy.asfortranarray(table_out) - return table_out2 - - def __init__(self, family_name: str, Nslice: float, Filename_in: str, Energy: float, **kwargs): - """ - Args: - family_name: family name - Nslice: number of slices in ... tracking??? integrator ??? - Filename_in: input filename - Energy: particle energy in GeV - - Default PassMethod: ``IdTablePass`` - """ - # 2023jan18 fix bug with element print - # 2023jan15 first release - # orblancog - ## read the input data - el_length, hkickmap, vkickmap, table_cols1, table_rows1, table_cols2, table_rows2 \ - = self.readRadiaFieldMap(Filename_in); - - ## set to float - table_cols1array = numpy.array(table_cols1, dtype='float64'); - table_rows1array = numpy.array(table_rows1, dtype='float64'); - table_cols2array = numpy.array(table_cols2, dtype='float64'); - table_rows2array = numpy.array(table_rows2, dtype='float64'); - - ## Reorder table_axes and kick maps - cols1sorted_index = numpy.argsort(table_cols1array); table_cols1array.sort(); - rows1sorted_index = numpy.argsort(table_rows1array); table_rows1array.sort(); - cols2sorted_index = numpy.argsort(table_cols2array); table_cols2array.sort(); - rows2sorted_index = numpy.argsort(table_rows2array); table_rows2array.sort(); - hkickmap_a = self.sorted_table(hkickmap, cols1sorted_index, 'col'); - hkickmap = self.sorted_table(hkickmap_a, rows1sorted_index, 'row'); - vkickmap_a = self.sorted_table(vkickmap, cols2sorted_index, 'col'); - vkickmap = self.sorted_table(vkickmap_a, rows2sorted_index, 'row'); - - ## Field to kick factors - Brho = 1e9 * Energy/clight - factor = 1/(Brho**2) - xkick = factor * hkickmap - ykick = factor * vkickmap - factor1 = -1/(Brho) - xtable = table_cols1array - ytable = table_rows1array - - ## Create element properties - kwargs.setdefault('PassMethod', 'IdTablePass') - kwargs.setdefault('Filename_in', Filename_in) - kwargs.setdefault('Energy', Energy) - kwargs.setdefault('Nslice', Nslice) - kwargs.setdefault('Length', el_length) - kwargs.setdefault('xkick', xkick) - kwargs.setdefault('ykick', ykick) - kwargs.setdefault('xtable', xtable) - kwargs.setdefault('ytable', ytable) - - ## Set Element inherited properties - # pyat issue #522 - #elem = Element('name', PassMethod='IdTablePass', xkick=x0, ykick=x1, \ - # xtable=x2, ytable=x3, Nslice=x4) - super(InsertionDevice, self).__init__(family_name, **kwargs) - - - def build_class_map(): # Missing class aliases (Bend) global CLASS_MAP From 504cb37dae0045faa2eb728847b40f7178d6f1b8 Mon Sep 17 00:00:00 2001 From: oscarxblanco Date: Thu, 9 Feb 2023 15:09:21 +0100 Subject: [PATCH 05/11] adds id_table_element.py file --- pyat/at/lattice/id_table_element.py | 165 ++++++++++++++++++++++++++++ 1 file changed, 165 insertions(+) create mode 100644 pyat/at/lattice/id_table_element.py diff --git a/pyat/at/lattice/id_table_element.py b/pyat/at/lattice/id_table_element.py new file mode 100644 index 000000000..d67f2fa9b --- /dev/null +++ b/pyat/at/lattice/id_table_element.py @@ -0,0 +1,165 @@ +import numpy +import io +from scipy.constants import c as clight + +class InsertionDevice(Element): + """ + Insertion Device Element. Valid for a parallel electron beam. + + Pascale ELLEAUME, "A New Approach to the Electron Beam Dynamics in + Undulators and Wigglers". EPAC1992 0661. + European Synchrotron Radiation Facility. + BP 220, F-38043 Grenoble, France + """ + _BUILD_ATTRIBUTES = Element._BUILD_ATTRIBUTES + ['Nslice', + 'Filename_in', + 'Energy'] + + def readRadiaFieldMap(self, file_in_name): + """ + Read a RadiaField map and return + """ + with io.open(file_in_name, mode="r", encoding="utf-8") as f: + """ + File, where : + - the first data line is the length in meters + - the second data line is the number of points in the h. plane + - the third data line is the number of points in the v. plane + - each data block comes after a START + - first the horizontal data block, and second the vertical data block + - each block is a table with axes + - comments start with # + """ + ### File example: + # #comment in line 1 + # #comment in line 2 + # Length_in_m + # #comment in line 4 + # Number of points in horizontal plane :nh + # #comment in line 6 + # Number of points in vertical plane :nv + # #comment in line 8 + # START + # pos_point1h pos_point2h ... pos_pointnh + # pos_point1v + # ... horizontal kick_map(nv,nh) + # pos_pointnv + # START + # pos_point1h pos_point2h ... pos_pointnh + # pos_point1v + # ... vertical kick_map(nv,nh) + # pos_pointnv + # (EOL) + + data_lines = 0; # line not starting with '#' + header_lines = 0; # line starting with '#' + block_counter = 0; # START of the hor. map and START of the vert. map + for line in f: + sline = line.split() + if sline[0] == '#': # line is comment + header_lines += 1; + else: + data_lines += 1; + if data_lines == 1: el_length = float(sline[0]); # get the element length + elif data_lines == 2: h_points = int(sline[0]); # get the number of horizontal points + elif data_lines == 3: + # get the number of vertical points + v_points = int(sline[0]); + # initialize element kicks and table_axes + kick_map = numpy.zeros((v_points,h_points)); + haxis = numpy.zeros(h_points); + vaxis = numpy.zeros(v_points); + else: + # read block of data + if sline[0] == "START" or sline[0] == "START\n" : + block_counter += 1; + block_lines = 0; + if block_lines == 1: haxis = sline; + if block_lines > 1: + # minus one due to python index starting at zero + # and minus another one due to the column labels in first line + vaxis[block_lines - 2] = float(sline[0]); + kick_map[block_lines - 2][:] = sline[1:]; + if block_lines > v_points: + block_lines = 0; + if block_counter == 1: + hkickmap = numpy.copy(kick_map); + table_cols1 = haxis; + table_rows1 = vaxis; + if block_counter == 2: + vkickmap = numpy.copy(kick_map); + table_cols2 = haxis; + table_rows2 = vaxis; + block_lines += 1; + + + return el_length, hkickmap, vkickmap, table_cols1, table_rows1, table_cols2, table_rows2 + + def sorted_table(self, table_in, sorted_index, order_axis): + # numpy.asfortranarray makes a copy of contiguous memory positions + table_out = numpy.copy(table_in); + for i,iis in zip(range(len(sorted_index)), sorted_index): + if order_axis == 'col': table_out[:,i] = table_in[ : ,iis] + if order_axis == 'row': table_out[i,:] = table_in[iis, : ] + table_out2 = numpy.asfortranarray(table_out) + return table_out2 + + def __init__(self, family_name: str, Nslice: float, Filename_in: str, Energy: float, **kwargs): + """ + Args: + family_name: family name + Nslice: number of slices in ... tracking??? integrator ??? + Filename_in: input filename + Energy: particle energy in GeV + + Default PassMethod: ``IdTablePass`` + """ + # 2023jan18 fix bug with element print + # 2023jan15 first release + # orblancog + ## read the input data + el_length, hkickmap, vkickmap, table_cols1, table_rows1, table_cols2, table_rows2 \ + = self.readRadiaFieldMap(Filename_in); + + ## set to float + table_cols1array = numpy.array(table_cols1, dtype='float64'); + table_rows1array = numpy.array(table_rows1, dtype='float64'); + table_cols2array = numpy.array(table_cols2, dtype='float64'); + table_rows2array = numpy.array(table_rows2, dtype='float64'); + + ## Reorder table_axes and kick maps + cols1sorted_index = numpy.argsort(table_cols1array); table_cols1array.sort(); + rows1sorted_index = numpy.argsort(table_rows1array); table_rows1array.sort(); + cols2sorted_index = numpy.argsort(table_cols2array); table_cols2array.sort(); + rows2sorted_index = numpy.argsort(table_rows2array); table_rows2array.sort(); + hkickmap_a = self.sorted_table(hkickmap, cols1sorted_index, 'col'); + hkickmap = self.sorted_table(hkickmap_a, rows1sorted_index, 'row'); + vkickmap_a = self.sorted_table(vkickmap, cols2sorted_index, 'col'); + vkickmap = self.sorted_table(vkickmap_a, rows2sorted_index, 'row'); + + ## Field to kick factors + Brho = 1e9 * Energy/clight + factor = 1/(Brho**2) + xkick = factor * hkickmap + ykick = factor * vkickmap + factor1 = -1/(Brho) + xtable = table_cols1array + ytable = table_rows1array + + ## Create element properties + kwargs.setdefault('PassMethod', 'IdTablePass') + kwargs.setdefault('Filename_in', Filename_in) + kwargs.setdefault('Energy', Energy) + kwargs.setdefault('Nslice', Nslice) + kwargs.setdefault('Length', el_length) + kwargs.setdefault('xkick', xkick) + kwargs.setdefault('ykick', ykick) + kwargs.setdefault('xtable', xtable) + kwargs.setdefault('ytable', ytable) + + ## Set Element inherited properties + # pyat issue #522 + #elem = Element('name', PassMethod='IdTablePass', xkick=x0, ykick=x1, \ + # xtable=x2, ytable=x3, Nslice=x4) + super(InsertionDevice, self).__init__(family_name, **kwargs) + From 607402f418b9ee225bd6a80a59554e1ae3293c1a Mon Sep 17 00:00:00 2001 From: oscarxblanco Date: Thu, 9 Feb 2023 15:10:05 +0100 Subject: [PATCH 06/11] changes element name to IdTable --- pyat/at/lattice/id_table_element.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pyat/at/lattice/id_table_element.py b/pyat/at/lattice/id_table_element.py index d67f2fa9b..9d4b615c4 100644 --- a/pyat/at/lattice/id_table_element.py +++ b/pyat/at/lattice/id_table_element.py @@ -2,7 +2,7 @@ import io from scipy.constants import c as clight -class InsertionDevice(Element): +class IdTable(Element): """ Insertion Device Element. Valid for a parallel electron beam. @@ -161,5 +161,5 @@ def __init__(self, family_name: str, Nslice: float, Filename_in: str, Energy: fl # pyat issue #522 #elem = Element('name', PassMethod='IdTablePass', xkick=x0, ykick=x1, \ # xtable=x2, ytable=x3, Nslice=x4) - super(InsertionDevice, self).__init__(family_name, **kwargs) + super(IdTable, self).__init__(family_name, **kwargs) From add7a735f1f0ce311459e39fdd7a24ee065bcb81 Mon Sep 17 00:00:00 2001 From: oscarxblanco Date: Thu, 9 Feb 2023 15:35:29 +0100 Subject: [PATCH 07/11] first pep8 check --- pyat/at/lattice/id_table_element.py | 154 ++++++++++++++++------------ 1 file changed, 86 insertions(+), 68 deletions(-) diff --git a/pyat/at/lattice/id_table_element.py b/pyat/at/lattice/id_table_element.py index 9d4b615c4..92e4f3688 100644 --- a/pyat/at/lattice/id_table_element.py +++ b/pyat/at/lattice/id_table_element.py @@ -1,7 +1,9 @@ +from .elements import Element import numpy import io from scipy.constants import c as clight + class IdTable(Element): """ Insertion Device Element. Valid for a parallel electron beam. @@ -26,11 +28,12 @@ def readRadiaFieldMap(self, file_in_name): - the second data line is the number of points in the h. plane - the third data line is the number of points in the v. plane - each data block comes after a START - - first the horizontal data block, and second the vertical data block + - first the horizontal data block, and second the + vertical data block - each block is a table with axes - comments start with # """ - ### File example: + # File example: # #comment in line 1 # #comment in line 2 # Length_in_m @@ -51,60 +54,69 @@ def readRadiaFieldMap(self, file_in_name): # pos_pointnv # (EOL) - data_lines = 0; # line not starting with '#' - header_lines = 0; # line starting with '#' - block_counter = 0; # START of the hor. map and START of the vert. map + data_lines = 0 # line not starting with '#' + header_lines = 0 # line starting with '#' + block_counter = 0 # START of the hor.map and START of the vert.map for line in f: sline = line.split() - if sline[0] == '#': # line is comment - header_lines += 1; + if sline[0] == '#': # line is comment + header_lines += 1 else: - data_lines += 1; - if data_lines == 1: el_length = float(sline[0]); # get the element length - elif data_lines == 2: h_points = int(sline[0]); # get the number of horizontal points - elif data_lines == 3: - # get the number of vertical points - v_points = int(sline[0]); + data_lines += 1 + if data_lines == 1: # get the element length + el_length = float(sline[0]) + elif data_lines == 2: # get the number of hor. points + h_points = int(sline[0]) + elif data_lines == 3: # get the number of ver. points + v_points = int(sline[0]) # initialize element kicks and table_axes - kick_map = numpy.zeros((v_points,h_points)); - haxis = numpy.zeros(h_points); - vaxis = numpy.zeros(v_points); + kick_map = numpy.zeros((v_points, h_points)) + haxis = numpy.zeros(h_points) + vaxis = numpy.zeros(v_points) else: # read block of data - if sline[0] == "START" or sline[0] == "START\n" : - block_counter += 1; - block_lines = 0; - if block_lines == 1: haxis = sline; + if sline[0] == "START" or sline[0] == "START\n": + block_counter += 1 + block_lines = 0 + if block_lines == 1: + haxis = sline if block_lines > 1: # minus one due to python index starting at zero - # and minus another one due to the column labels in first line - vaxis[block_lines - 2] = float(sline[0]); - kick_map[block_lines - 2][:] = sline[1:]; + # and minus another one due + # to the column labels in first line + vaxis[block_lines - 2] = float(sline[0]) + kick_map[block_lines - 2][:] = sline[1:] if block_lines > v_points: - block_lines = 0; + block_lines = 0 if block_counter == 1: - hkickmap = numpy.copy(kick_map); - table_cols1 = haxis; - table_rows1 = vaxis; + hkickmap = numpy.copy(kick_map) + table_cols1 = haxis + table_rows1 = vaxis if block_counter == 2: - vkickmap = numpy.copy(kick_map); - table_cols2 = haxis; - table_rows2 = vaxis; - block_lines += 1; - - - return el_length, hkickmap, vkickmap, table_cols1, table_rows1, table_cols2, table_rows2 + vkickmap = numpy.copy(kick_map) + table_cols2 = haxis + table_rows2 = vaxis + block_lines += 1 + return el_length, hkickmap, vkickmap, table_cols1, table_rows1, \ + table_cols2, table_rows2 def sorted_table(self, table_in, sorted_index, order_axis): # numpy.asfortranarray makes a copy of contiguous memory positions - table_out = numpy.copy(table_in); - for i,iis in zip(range(len(sorted_index)), sorted_index): - if order_axis == 'col': table_out[:,i] = table_in[ : ,iis] - if order_axis == 'row': table_out[i,:] = table_in[iis, : ] + table_out = numpy.copy(table_in) + for i, iis in zip(range(len(sorted_index)), sorted_index): + if order_axis == 'col': + table_out[:, i] = table_in[:, iis] + if order_axis == 'row': + table_out[i, :] = table_in[iis, :] table_out2 = numpy.asfortranarray(table_out) return table_out2 - def __init__(self, family_name: str, Nslice: float, Filename_in: str, Energy: float, **kwargs): + def __init__(self, + family_name: str, + Nslice: float, + Filename_in: str, + Energy: float, + **kwargs): """ Args: family_name: family name @@ -117,36 +129,42 @@ def __init__(self, family_name: str, Nslice: float, Filename_in: str, Energy: fl # 2023jan18 fix bug with element print # 2023jan15 first release # orblancog - ## read the input data - el_length, hkickmap, vkickmap, table_cols1, table_rows1, table_cols2, table_rows2 \ - = self.readRadiaFieldMap(Filename_in); + # read the input data + el_length, hkickmap, vkickmap, \ + table_cols1, table_rows1, \ + table_cols2, table_rows2 \ + = self.readRadiaFieldMap(Filename_in) - ## set to float - table_cols1array = numpy.array(table_cols1, dtype='float64'); - table_rows1array = numpy.array(table_rows1, dtype='float64'); - table_cols2array = numpy.array(table_cols2, dtype='float64'); - table_rows2array = numpy.array(table_rows2, dtype='float64'); + # set to float + table_cols1array = numpy.array(table_cols1, dtype='float64') + table_rows1array = numpy.array(table_rows1, dtype='float64') + table_cols2array = numpy.array(table_cols2, dtype='float64') + table_rows2array = numpy.array(table_rows2, dtype='float64') - ## Reorder table_axes and kick maps - cols1sorted_index = numpy.argsort(table_cols1array); table_cols1array.sort(); - rows1sorted_index = numpy.argsort(table_rows1array); table_rows1array.sort(); - cols2sorted_index = numpy.argsort(table_cols2array); table_cols2array.sort(); - rows2sorted_index = numpy.argsort(table_rows2array); table_rows2array.sort(); - hkickmap_a = self.sorted_table(hkickmap, cols1sorted_index, 'col'); - hkickmap = self.sorted_table(hkickmap_a, rows1sorted_index, 'row'); - vkickmap_a = self.sorted_table(vkickmap, cols2sorted_index, 'col'); - vkickmap = self.sorted_table(vkickmap_a, rows2sorted_index, 'row'); + # Reorder table_axes and kick maps + cols1sorted_index = numpy.argsort(table_cols1array) + table_cols1array.sort() + rows1sorted_index = numpy.argsort(table_rows1array) + table_rows1array.sort() + cols2sorted_index = numpy.argsort(table_cols2array) + table_cols2array.sort() + rows2sorted_index = numpy.argsort(table_rows2array) + table_rows2array.sort() + hkickmap_a = self.sorted_table(hkickmap, cols1sorted_index, 'col') + hkickmap = self.sorted_table(hkickmap_a, rows1sorted_index, 'row') + vkickmap_a = self.sorted_table(vkickmap, cols2sorted_index, 'col') + vkickmap = self.sorted_table(vkickmap_a, rows2sorted_index, 'row') - ## Field to kick factors - Brho = 1e9 * Energy/clight - factor = 1/(Brho**2) - xkick = factor * hkickmap - ykick = factor * vkickmap - factor1 = -1/(Brho) - xtable = table_cols1array - ytable = table_rows1array + # Field to kick factors + Brho = 1e9 * Energy/clight + factor = 1.0/(Brho**2) + xkick = factor * hkickmap + ykick = factor * vkickmap + factor1 = -1.0/(Brho) + xtable = table_cols1array + ytable = table_rows1array - ## Create element properties + # Create element properties kwargs.setdefault('PassMethod', 'IdTablePass') kwargs.setdefault('Filename_in', Filename_in) kwargs.setdefault('Energy', Energy) @@ -157,9 +175,9 @@ def __init__(self, family_name: str, Nslice: float, Filename_in: str, Energy: fl kwargs.setdefault('xtable', xtable) kwargs.setdefault('ytable', ytable) - ## Set Element inherited properties + # Set Element inherited properties # pyat issue #522 - #elem = Element('name', PassMethod='IdTablePass', xkick=x0, ykick=x1, \ + # elem = Element('name', PassMethod='IdTablePass', \ + # xkick=x0, ykick=x1, \ # xtable=x2, ytable=x3, Nslice=x4) super(IdTable, self).__init__(family_name, **kwargs) - From 1fab8acd9bd9b0965ba2a46f34d46a0f56ba19a9 Mon Sep 17 00:00:00 2001 From: oscarxblanco Date: Thu, 9 Feb 2023 15:37:10 +0100 Subject: [PATCH 08/11] change filename to idtable_element.py --- pyat/at/lattice/{id_table_element.py => idtable_element.py} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename pyat/at/lattice/{id_table_element.py => idtable_element.py} (100%) diff --git a/pyat/at/lattice/id_table_element.py b/pyat/at/lattice/idtable_element.py similarity index 100% rename from pyat/at/lattice/id_table_element.py rename to pyat/at/lattice/idtable_element.py From 637b2b68f93ed7bf1c7fe70f2ab9d994bbc9deff Mon Sep 17 00:00:00 2001 From: oscarxblanco Date: Thu, 9 Feb 2023 15:40:12 +0100 Subject: [PATCH 09/11] adds idtable_element --- pyat/at/lattice/__init__.py | 1 + 1 file changed, 1 insertion(+) diff --git a/pyat/at/lattice/__init__.py b/pyat/at/lattice/__init__.py index e5a890f2f..9503b0ebf 100644 --- a/pyat/at/lattice/__init__.py +++ b/pyat/at/lattice/__init__.py @@ -8,6 +8,7 @@ from .options import DConstant, random from .particle_object import Particle from .elements import * +from .idtable_element import IdTable from .utils import * from .lattice_object import * from .cavity_access import * From 29944fb2aef7ed19bf78cd09dd85c23fc4b60889 Mon Sep 17 00:00:00 2001 From: oscarxblanco Date: Fri, 17 Feb 2023 15:57:34 +0100 Subject: [PATCH 10/11] changes IdTable to InsertionDeviceKickMap --- pyat/at/lattice/__init__.py | 2 +- pyat/at/lattice/idtable_element.py | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/pyat/at/lattice/__init__.py b/pyat/at/lattice/__init__.py index 9503b0ebf..feebb7df4 100644 --- a/pyat/at/lattice/__init__.py +++ b/pyat/at/lattice/__init__.py @@ -8,7 +8,7 @@ from .options import DConstant, random from .particle_object import Particle from .elements import * -from .idtable_element import IdTable +from .idtable_element import InsertionDeviceKickMap from .utils import * from .lattice_object import * from .cavity_access import * diff --git a/pyat/at/lattice/idtable_element.py b/pyat/at/lattice/idtable_element.py index 92e4f3688..77be3d7bd 100644 --- a/pyat/at/lattice/idtable_element.py +++ b/pyat/at/lattice/idtable_element.py @@ -4,7 +4,7 @@ from scipy.constants import c as clight -class IdTable(Element): +class InsertionDeviceKickMap(Element): """ Insertion Device Element. Valid for a parallel electron beam. @@ -180,4 +180,4 @@ def __init__(self, # elem = Element('name', PassMethod='IdTablePass', \ # xkick=x0, ykick=x1, \ # xtable=x2, ytable=x3, Nslice=x4) - super(IdTable, self).__init__(family_name, **kwargs) + super(InsertionDeviceKickMap, self).__init__(family_name, **kwargs) From 625d79c5912da4aac307491f7acbb095d33217b0 Mon Sep 17 00:00:00 2001 From: oscarxblanco Date: Fri, 17 Feb 2023 19:00:08 +0100 Subject: [PATCH 11/11] adds methods set_DriftPass, set_IdTablePass, get_PassMethod --- pyat/at/lattice/idtable_element.py | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/pyat/at/lattice/idtable_element.py b/pyat/at/lattice/idtable_element.py index 77be3d7bd..2af64b3b5 100644 --- a/pyat/at/lattice/idtable_element.py +++ b/pyat/at/lattice/idtable_element.py @@ -111,6 +111,15 @@ def sorted_table(self, table_in, sorted_index, order_axis): table_out2 = numpy.asfortranarray(table_out) return table_out2 + def set_DriftPass(self): + setattr(self, 'PassMethod', 'DriftPass') + + def set_IdTablePass(self): + setattr(self, 'PassMethod', 'IdTablePass') + + def get_PassMethod(self): + return getattr(self, 'PassMethod') + def __init__(self, family_name: str, Nslice: float,