Skip to content

Conversation

@mattiastefanelli
Copy link
Contributor

Adding a script to generate .tfs and .txt tables with the summary of the KMOD measurement imported with kmod_importer. It will generate one .tfs and one .txt table for each beam.
The .txt table has been made to be easily copy/pasted in the logbook keeping a readable format.

@mattiastefanelli mattiastefanelli requested a review from a team as a code owner November 26, 2025 16:52
@mattiastefanelli mattiastefanelli marked this pull request as draft November 26, 2025 16:54
@mattiastefanelli mattiastefanelli marked this pull request as ready for review November 27, 2025 08:37
@mattiastefanelli
Copy link
Contributor Author

The output .txt table for the Logbook looks like this without Tabulate package

B1_summary_logbook.txt

@github-actions
Copy link

github-actions bot commented Nov 27, 2025

Coverage report

Click to see where and how coverage changed

FileStatementsMissingCoverageCoverage
(new stmts)
Lines missing
  omc3
  kmod_importer.py 226
  omc3/scripts
  kmod_summary.py 71, 79-81, 112-113, 147-148, 208, 230, 271-286
Project Total  

This report was generated by python-coverage-comment-action

Copy link
Member

@fsoubelet fsoubelet left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the PR Mattia, this is going to be useful to have.

I left comments here and there about inconsistencies / code clarity etc. See below.

One thing I'm wondering is: could this be a stand-alone script? And then it could be run on previous folders with kmod measurements from before we had it (and the relevant part just imported and called into kmob_importer.py)?

lumi_filename = _get_lumi_filename(betas, ip_a=ips[0], ip_b=ips[1])
assert (average_dir / lumi_filename).exists()


Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could we add a little check that the written files are as expected?

Copy link
Member

@JoschD JoschD left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A few comments, but my main point is also, that this should be a standalone script, in case someone only wants the table without importing it anywhere.

When refactoring, also separate the output from the reading/transforming. There should be one function that creates the tables and simply returns them. Then another funtion/outer function that writes them out.

In my opinion the script/main function of the script should also have the following parameters:

  • outputdir -> optional, write the files ou (always return the tables)
  • average -> true/false, calls the functions to average the data (could also be boolean | path-to-the-file | averaged-dataframes)
  • logbook -> optional, specify a logbook (LHC_OMC, LHC_OP, true->LHC_OMC) uses the logbook uploader to create a new logbook entry.

And then you can import the function here and re-use it to create the table automatically on import.

When putting it into another script: consider which parts might benefit from being in their own little function as well, to make the code more readable/self-explainatory.

mattiastefanelli and others added 2 commits November 27, 2025 13:40
Co-authored-by: Felix Soubelet <19598248+fsoubelet@users.noreply.github.com>
@mattiastefanelli
Copy link
Contributor Author

mattiastefanelli commented Dec 16, 2025

Hey, I’ve implemented most of the suggested changes in this second draft. I moved the script into a standalone module, which is now called by the main kmod_importer. Labels, comments, and variable names have been updated for clarity.

The saving of files is now optional: if an output directory is provided, the results are saved; otherwise, the script simply returns the .txt tables for the logbook and the .tfs DataFrames containing all K-mod results. Additionally, if averaged results are provided, the script also includes the average values.

I’m still working on implementing the optional creation of the logbook entry, and the writing of some further tests. I look forward to any further feedback or suggestions, thank you!

@mattiastefanelli
Copy link
Contributor Author

I was also thinking that the other scripts within kmod_importer operate per beam, whereas this script currently processes both beams at the same time. Should I modify it to generate the tables for each beam individually, consistent with the other scripts?

Copy link
Member

@JoschD JoschD left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The table creation function is quite hard to read and follow, because there are a lot of branches within that function. You need to split it into it's functional parts and then have a main function, that calls all of that:

  • one function to read the data and put it into a df
  • one function that takes a df and creates a txt
  • one small function for the writing
  • probably no function for the logbook, as you can just call the main from the logbook
  • depending on the user input you then call the writing and/or the logbook function
  • always return the df and txt content
  • Unify the output filenames. Why to completely different filenames for files that basically contain the same information? "logbook" is also not needed in the file name, it doesn't matter what the tables are used for.

mattiastefanelli and others added 8 commits December 17, 2025 17:25
Co-authored-by: Felix Soubelet <19598248+fsoubelet@users.noreply.github.com>
Co-authored-by: Felix Soubelet <19598248+fsoubelet@users.noreply.github.com>
Co-authored-by: Felix Soubelet <19598248+fsoubelet@users.noreply.github.com>
Co-authored-by: Felix Soubelet <19598248+fsoubelet@users.noreply.github.com>
Co-authored-by: Felix Soubelet <19598248+fsoubelet@users.noreply.github.com>
Co-authored-by: Felix Soubelet <19598248+fsoubelet@users.noreply.github.com>
Co-authored-by: Felix Soubelet <19598248+fsoubelet@users.noreply.github.com>
@mattiastefanelli
Copy link
Contributor Author

I have further applied your suggestions to the code, now the script is more modular, and divided as:

  1. _collect_kmod_results: to gather together multiple kmod results
  2. _collect_averaged_kmod_results: to gather together, if given. the averaged kmod results already calculated
  3. _prepare_logbook_table: to prepare a nice .txt file
  4. _save_outputs: for saving
  5. _logbook_entry: to create logbook entry

The saving and the logbook creation are now independent (just no file is attached, the content of the .txt file is passed to create_logbook_entry as "text".)

I also change the input parameters, now the code write the files, if required, to the average_dir of the averaged results, not the main output_dir.

Also the beam is now an input parameter, first because it seems to me more coherent with the other parts of the kmod_importer, second because I was thinking that, hypothetically, if we are in the CCC, and we import the kmod results for both B1 and B2, it will create each time the tables for both beams, so we would need to coordinate. In this way, each logbook entry/saving is related to the particular beam you're working on.

Small updates for the test_kmod_importer.

@mattiastefanelli
Copy link
Contributor Author

I have added the optional luminosity imbalance information in the .txt tables generated.

Copy link
Member

@fsoubelet fsoubelet left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There were plenty of inconsistencies from the transition to helper functions, see comments below. For most simple ones I've made a suggestion.

Importantly, there is not argument parsing for the main function that would run in script mode. So this would instantly crash in script mode. You need to add a get_params like usually done. The file docstring seems to already be there but I didn't check it yet.

Note: I find it a bit strange in the logic flow that the kmod results have to be parsed from file but the averaged results would already be parsed and provided.

Also, it would be nice to run ruff format on this file.

@JoschD
Copy link
Member

JoschD commented Dec 20, 2025

I think one of the main issues, why this looks/is so complicated it, that the main function from the kmod table creator is used in the kmod importer, which makes the input parameters very wonky.

IMO the structure becomes much cleaner, if the main function in the table creator does (in separate consecutive functions):

  • averaging (if requested)
  • lumni imbalance (if requested)
  • reading of all kmod data
  • conversion into formatted table (given the 1-3 outputs from above)
  • write to file (if requested, doesn't even need to be it's own function just to Path().write_text())
  • send to logbook (if requested, doesn't even need to be it's own function, just call the send-to-logbook function)

In the kmod importer you only need to call then
the last 3 functions, not the main function.

mattiastefanelli and others added 6 commits December 20, 2025 13:17
Co-authored-by: Felix Soubelet <19598248+fsoubelet@users.noreply.github.com>
Co-authored-by: Felix Soubelet <19598248+fsoubelet@users.noreply.github.com>
Co-authored-by: Felix Soubelet <19598248+fsoubelet@users.noreply.github.com>
@mattiastefanelli
Copy link
Contributor Author

I think one of the main issues, why this looks/is so complicated it, that the main function from the kmod table creator is used in the kmod importer, which makes the input parameters very wonky.

IMO the structure becomes much cleaner, if the main function in the table creator does (in separate consecutive functions):

* averaging (if requested)

* lumni imbalance (if requested)

* reading of all kmod data

* conversion into formatted table (given the 1-3 outputs from above)

* write to file (if requested, doesn't even need to be it's own function just to Path().write_text())

* send to logbook (if requested, doesn't even need to be it's own function, just call the send-to-logbook function)

In the kmod importer you only need to call then the last 3 functions, not the main function.

I'll make shortly a new commit to include those changes.

@mattiastefanelli
Copy link
Contributor Author

I have updated the code to match the new structure suggested by @JoschD.

Now kmod_summary contains just the single functions as:

  1. _collect_kmod_results: to gather the kmod results from the measurement paths.
  2. _collect_averaged_kmod_results: to gather averaged kmod results from dataframes in output directory.
  3. _collect_lumi_imbalance_results: to gather lumi imbalance results from dataframes in output directory.

now both follow the same logic, the values are taken from the same output directory which is the average_output_dir in the kmod_importer. No need to pass directly the dataframes to the function as before.

  1. _prepare_logbook_table: Prepare formatted logbook tables from K-modulation summary data. No saving, no logbook entry. Just preparing the formatted table. It needs the path to measurements, and optionally, if the output directory is given to kmod_averaged_output_dir and/or lumi_imb_output_dir, the averaged results and the lumi imbalance results are included in the text table.

---> I wonder if it's better to pass the output dir once, and then give the option to include averaged and/or lumi imbalance as a boolean. For the moment you basically pass the same argument twice to the corresponding quantity you want to include.

  1. _save_outputs: for saving, could be also not a script, but it contains some log.INFO, and it's still 6/7 lines of code.
  2. _summary_logbook_entry: for creating logbook entry. Same considerations as before.

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 this pull request may close these issues.

4 participants