-
Notifications
You must be signed in to change notification settings - Fork 33
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
pyat ReadWrite Insertion Devices into mat files #597
Conversation
Dear @lfarv , what is your opinion on this modifications ? Would you consider them ok to review ? Best regards, |
Hello @oscarxblanco , let's wait for @lfarv to be back he may have good suggestions, but this seems very complicated to me. I have a couple questions: Cheers |
Dear @swhite2401
Sure it could be an option that I have not tried out yet.
When starting from python it should have some kind of class to be saved. And you are right, the attributes are saved but the mapping from pyat classes to AT matlab elements is still missing.
Yes, I would also prefer this solution. But, I wrote this work around to avoid changing both pyat at AT matlab at the same time. This of course is possible.
Unfortunately not yet, there is a problem when reading back the array from an m file. The memory allocation is not fortran-aligned. I believe this could be solved but I wanted to raise the point before doing more modifications.
|
My feeling is that we should go for an option that does not require external files to load a lattice file. I you want I can help with the implementation (after IPAC). |
Perfect ! Thank you |
Quick update: After conversations with @swhite2401 and @simoneliuzzo , the initial proposal to store the ID data in a multipole class is abandoned because it was too misleading. In tag bd48038 So, I'm half way through. The pyat modifications work. The matlab implementation of a compatible atidtable is missing. I will solve the issue wrt to matlab, and at the end try to solve the conflict on pyat/at/load/utils.py shown in the automatic check. o |
Thanks for the update, I have not arrived to this issue yet but I will soon be able to help if needed! |
Dear @lfarv I have implemented the modifications you suggested, and it looks much better. I attach a zip file with the scripts I used for testing. NOTE: The InsertionDeviceKickMap still does not implement the additional blocks xkick1 and ykick1, and assume they are filled with zeros. I don't have an example of an insertion device that uses these two parameters. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Taking NumX
and NumY
out of the element attributes is the main modification, since they appear in many places…
@@ -120,37 +49,156 @@ def set_IdTablePass(self): | |||
def get_PassMethod(self): | |||
return getattr(self, 'PassMethod') |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What is the interest of these methods compared to the direct access to the attributes:
elem.PassMethod='IdTablePass'
PassMethod
is a public attribute. Following this, we could add "set" methods for all attributes: set_length()
, get_length()
, set_FamName()
, etc
It looks redundant to me…
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Dear @lfarv , at the moment of testing the Insertion Device I tipically needed to set the pass method to IdTablePass and DriftPass. I implemented these functions to profit from autocompletion therefore avoiding misspelling errors.
In any case, you are right, get_PassMethod is redudant. I have put a UserWarning about its deprecation. It might be possible to completely remove it in a following version. Or if you see it is better I would remove it now.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ok, I don' care, it's just unusual but it is harmless!
pyat/at/lattice/idtable_element.py
Outdated
'NumX', | ||
'NumY', |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You don't need to store NumX
and NumY
as attributes: they can be derived from the shape of xkick
. The pass method does not use them, it looks at xkick
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
NumX and Numy were removed
atmat/lattice/at2str.m
Outdated
'NumX', ... | ||
'NumY', ... |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not necessary: see comment above
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
NumX and Numy were removed
Elem.NumX = NumX; | ||
Elem.NumY = NumY; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As above: you don't need to store NumX
and NumY
: they are not used be the pass method.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
NumX and NumY were removed
pyat/at/lattice/idtable_element.py
Outdated
if len(args) == 3: | ||
Nslice = args[0] | ||
Filename_in = args[1] | ||
Energy = args[2] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What happens if not ?
You could instead declare from_text_file
as:
def from_text_file(self, Nslice, Filename_in, Energy):
which avoids this test and ensures these variables are defined. Also kwargs
is unused.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thank you, this comparison has been removed.
pyat/at/lattice/idtable_element.py
Outdated
if len(args) < 13: | ||
# get data from text file | ||
elemargs = self.from_text_file(*args, **kwargs) | ||
else: | ||
# get data from arguments | ||
elemargs = dict(zip(_argnames, args)) | ||
elemargs.update(kwargs) | ||
super().__init__(family_name, **elemargs) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
if len(args) < 13:
# get data from text file
elemargs = self.from_text_file(*args)
else:
# get data from arguments
elemargs = dict(zip(_argnames, args))
elemargs.update(kwargs)
super().__init__(family_name, **elemargs)
kwargs
is no more declared in from_text_file
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thank you again, I changed the first line in the code you suggested; length should be larger than 11.
pyat/at/lattice/idtable_element.py
Outdated
else: | ||
# get data from arguments | ||
elemargs = dict(zip(_argnames, args)) | ||
elemargs.update(kwargs) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
My last comment: you can take the elemargs.update(kwargs)
statement out of the test, so that it applies in both cases:
if len(args) < 11:
# get data from text file
elemargs = self.from_text_file(*args)
else:
# get data from arguments
elemargs = dict(zip(_argnames, args))
elemargs.update(kwargs)
super().__init__(family_name, **elemargs)
Thanks for your patience, now it's ok for me !
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No problem at all. This suggestion is implemented in the last commit.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ok for me
@swhite2401 do you have any suggestions ? |
Hi @oscarxblanco , sorry I am just back from vacations. No objection on my side please go ahead with the merge! |
@swhite2401 No problem |
Dear all,
this PR is a workaround to a limitation in read and write capabilities on pyat when adding an Insertion Device map, already mentioned in #558 . The existing InsertionDeviceKickMap class always needed the field map file (here called, IdFile) to be read, and that made it incompatible with the save_mat function.
Here, the class InsertionDeviceKickMap has been modified to a function, and a new class called IdTable is created compatible with the structure stored in .mat files from pyat and matlab. Due to the non-existence of an equivalent class in AT matlab, the insertion device element is saved by changing it into a multipole which exists in both AT versions.
I expect no impact on the users, as the InsertionDeviceKickMap function uses exactly the same call and parameters, and the IdTable is saved in a backwards compatible format through the multipole class (no new elements are created on the .mat output).
The output to .m files is still not compatible. The output from ATmatlab transforms the element into a drift which could change the beam dynamics results when read back. I have done the same on pyAT to keep similar results on both sides, but, I discourage to use .m file for the moment.
The following diagram shows the data flow.
Best regards,
o