Skip to content
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

Twiss at certain positions #98

Closed
Rasimilian opened this issue Aug 31, 2021 · 13 comments · Fixed by #99
Closed

Twiss at certain positions #98

Rasimilian opened this issue Aug 31, 2021 · 13 comments · Fixed by #99

Comments

@Rasimilian
Copy link

Rasimilian commented Aug 31, 2021

Hello!
I'm trying to get Twiss at BPMs positions via a select command, but I get a full twiss table:

madx.input('select,flag=twiss_in_bpms,class=monitor,full=False,column=name,s,betx,bety,dx;')
madx.twiss(sequence='RING', centre=True, table='twiss_in_bpms')
twiss_table = madx.table.twiss_in_bpms.betx

The only way to get at certain positions is to save a table to a file and then to read the file:

madx.input('select,flag=twiss_in_bpms,class=monitor,full=False,column=name,s,betx,bety,dx;')
madx.twiss(sequence='RING', centre=True, table='twiss_in_bpms', file="log_file.txt")
madx.input('readtable,file="log_file.txt",table=twiss_in_bpms;')
twiss_table = madx.table.twiss_in_bpms.betx

Is it possible not to create an additional file? Could you help me with this please?

@fsoubelet
Copy link

fsoubelet commented Aug 31, 2021

Hi @Rasimilian, I believe the flag should be the generic name of a MADX table, and this will work if you just change select, flag=twiss_in_bpms,... to select, flag=twiss,....

@Rasimilian
Copy link
Author

@fsoubelet it doesn't work too :(

@fsoubelet
Copy link

That's unfortunate. Could you provide your script, or a minimal version so we can have a look at the issue?

@Rasimilian
Copy link
Author

Rasimilian commented Aug 31, 2021

Actually, this doesn't work for any element selected via the command.
But here is the code:

madx = Madx(stdout=True)
madx.call(file='structure.txt')
madx.input('beam,particle=electron,energy=1.8;')
madx.input('use,sequence=RING;')

madx.input('select,flag=twiss,class=monitor,full=False,column=name,s,betx,bety,dx;')
madx.twiss(sequence='RING', centre=True, table='twiss_in_bpms')
twiss_table = madx.table.twiss_in_bpms.betx

@fsoubelet
Copy link

Could you also provide the contents of structure.txt?

@fsoubelet
Copy link

I can confirm the behavior here. While waiting for @coldfix's take, the simplest I can suggest for now would be to make use of the associated pandas.DataFrame from the TWISS results:

madx = Madx()
madx.call(file="structure.txt")
madx.command.beam(particle="electron", energy=1.8)
madx.use(sequence="RING")

madx.command.select(flag="twiss", class_="monitor", full=False, column=["name", "s", "betx", "bety", "dx"])
madx.twiss(sequence="RING", centre=True)

twiss_table = madx.table.twiss.dframe().copy()
monitors = twiss_table[twiss_table.keyword == "monitor"][madx.table.twiss.selected_columns()]

Alternatively, if you have a know regex pattern (beware of MADX's own regex) for your monitors you can use select, pattern=... which has always worked fine on my side.

@Rasimilian
Copy link
Author

Rasimilian commented Aug 31, 2021

@fsoubelet, do you suggest to use select, pattern=monitor1;select, pattern=monitor2..., if there are monitors named as monitor1, monitor2 ...? if I understand you correctly, this doesn't work too.
Anyway, thank you!

@coldfix
Copy link
Member

coldfix commented Aug 31, 2021

Hi,
cpymad has the Table.selected_rows() method that can be used to retrieve which rows were selected by a previous SELECT statement. It can currently be used as follows:

twiss = madx.table.twiss

selection = np.array(twiss.selected_rows(), dtype=bool)
rows = twiss.dframe().iloc[selection]

However, the function is currently not implemented according to its documentation which means that I will change the implementation to fit the documentation, so this will be slightly different (removing the need for the manual np.array creation).

I will also add rows keyword arguments to some relevant methods to allow the user querying only specified rows. We should maybe even make the default to return only the selected rows. What do you think?

@coldfix
Copy link
Member

coldfix commented Aug 31, 2021

Also for an unknown reason, it currently doesn't seem to work if specifying a custom table name, I will check if anything can be done about that.

@coldfix
Copy link
Member

coldfix commented Aug 31, 2021

Scrap my last comment, it does work, but the flag parameter of SELECT must be set to the table name, e.g.:

madx.input('SELECT, flag=twiss_in_bpms, class=monitor;')
madx.twiss(sequence=..., table='twiss_in_bpms')

(but this also seems to be the case when exporting the table to a file using the filename argument)

@Rasimilian
Copy link
Author

@coldfix, the reason I asked is that I'm struggling for milliseconds now. For my current problem the code speed is essential. So I have measured time of program execution for suggested methods and the best time is for the code with a created file. I thought avoidance of file creating and accessing an internal table instead would buy me time.
But your suggestions are relevant and great.

@coldfix
Copy link
Member

coldfix commented Aug 31, 2021

Sure. I will change it so that the selected rows are applied on the C side without having to read out the entire table, so you won't have to worry about performance. But I can't promise I'll be able to do it today.

@Rasimilian
Copy link
Author

Thank you! :)

coldfix added a commit that referenced this issue Sep 1, 2021
coldfix added a commit that referenced this issue Sep 1, 2021
API changes:

- ``Table.selected_rows()`` now actually returns the *indices* of the selected
  elements as documented, rather than returning a boolean mask.
- ``Madx.eval()`` does no automatic syntax checking anymore. This is a minor
  performance improvement and is more consistent with ``Madx.input()`` which
  doesn't check the syntax either. Expressions can still be checked manually
  using ``cpymad.util.check_expression``

New features:

- (#90) Add comparison operators for ArrayAttribute (see #89)
- (#94) Add keyword argument ``Table.dframe(index=..)`` to allow specifying
  a column or sequence as the DataFrame index rather than using the default
  (``row_names()``). This is essential when accessing a table after having
  executed a ``USE`` statement (see #93).
- (#97) Add basic support for unexpanded nested sequences by returning
  them as elements of type ``Sequence`` from ``Sequence.elements`` (see #76)
- Add keyword argument ``Madx(prompt=...)`` as a shortcut for the most common
  ``CommandLog`` use case
- (#99) Add method ``Table.column()`` to retrieve specified rows in a specific
  column.
- (#99) Add ``rows`` and/or ``columns`` arguments to several ``Table`` methods
  to allow querying only specific columns or rows from the MAD-X process
- (#99) Add method ``Table.selection()`` that returns a new ``Table`` object
  which exposes only those rows/columns marked by a previous ``SELECT`` statement
  (see #98)
- Fix ``Madx.eval()`` to handle function calls, e.g.: ``sin(...)`` or ``table(...)``

Bug fixes:

- (#95) Fix ``KeyError`` when accessing tables after ``CLEAR`` (see #57)
- (#99) Fix requesting a subset of table rows using using a *numpy array*
  of indices
- Fix expression syntax checker to not reject function calls anymore. Rewrite
  the checker to use a LL(1) parser generator.

Documentation:

- Add links to external documentation using intersphinx
- Use automodapi to create module and class summary pages
- Use type hints from function annotations in documentation
- Mark more objects for inclusion in the documentation
- Add "Edit on GitHub" link to directly edit documentation
- Add many function annotations
- Generate class inheritance diagrams using graphviz
- Document problem with ``Table.row_names()`` after ``USE`` (#93)

Tests/CI:

- Move python 3.5 deprecation warning to package level
- Create GitHub releases for tags automatically (required for zenodo DOIs)
- Setup sequence definitions individually and explicitly in each test
- Add module for regression tests for all future bugfixes
- Put transfer map tests in their own module
- Port tests from unittest to pytest for simplicity
- Mark flaky tests for expected failure on macOS and windows
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants