Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
299 changes: 283 additions & 16 deletions apsuite/commisslib/meas_ac_orm.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,12 @@
"""Main module."""

import datetime
import operator as _opr
import time as _time
from copy import deepcopy as _dcopy
from functools import reduce as _red
from fpdf import FPDF
from pathlib import Path
from threading import Thread as _Thread

import matplotlib.pyplot as _mplt
Expand Down Expand Up @@ -713,7 +716,9 @@ def check_measurement_quality(self, mat_ac=None, mat_dc=None, dthres=1e-3):
cond_ok &= (corr_rf[0] < dthres).all()
return cond_ok

def plot_comparison_correlations(self, mat_ac=None, mat_dc=None):
def plot_comparison_correlations(
self, mat_ac=None, mat_dc=None, show_fig=True
):
"""Plot comparison of measured response matrix with reference respmat.

Two graphics will be made, one comparing the column space of both
Expand Down Expand Up @@ -788,11 +793,12 @@ def plot_comparison_correlations(self, mat_ac=None, mat_dc=None):
)

fig.tight_layout()
fig.show()
if show_fig:
fig.show()
return fig, (ax, ay), corr

def plot_comparison_single_corrector(
self, corr_idx, mat_ac=None, mat_dc=None
self, corr_idx, mat_ac=None, mat_dc=None, show_fig=True
):
"""Plot single corrector signatures of measured and reference respmat.

Expand Down Expand Up @@ -835,10 +841,11 @@ def plot_comparison_single_corrector(
ay.set_ylabel('Vertical ' + unit)
ay.set_xlabel('BPM position')
fig.tight_layout()
fig.show()
if show_fig:
fig.show()
return fig, (ax, ay)

def plot_scale_conversion_factors(self):
def plot_scale_conversion_factors(self, show_fig=True):
"""Plot single corrector signatures of measured and reference respmat.

Returns:
Expand All @@ -860,10 +867,13 @@ def plot_scale_conversion_factors(self):
ax.set_ylabel('Relative Factor')
ax.set_xlabel('Correctors Position [m]')
fig.tight_layout()
fig.show()
if show_fig:
fig.show()
return fig, ax

def plot_phases_vs_amplitudes(self, title='', corrsidx2highlight=None):
def plot_phases_vs_amplitudes(
self, title='', corrsidx2highlight=None, show_fig=True
):
"""."""
fig = _mplt.figure(figsize=(8, 6))
gs = _mplt.GridSpec(
Expand Down Expand Up @@ -926,11 +936,11 @@ def plot_phases_vs_amplitudes(self, title='', corrsidx2highlight=None):
avx.set_xlabel(r'Amplitudes [$\mu$m]')
ahx.set_ylabel(r'Phases [$\pi$]')
avy.set_ylabel(r'Phases [$\pi$]')

fig.show()
if show_fig:
fig.show()
return fig, ((ahx, ahy), (avy, avx))

def plot_phases_histogram(self, title=''):
def plot_phases_histogram(self, title='', show_fig=True):
"""."""
fig = _mplt.figure(figsize=(8, 6))
gs = _mplt.GridSpec(
Expand Down Expand Up @@ -980,11 +990,11 @@ def plot_phases_histogram(self, title=''):
avy.set_ylabel(r'Counts')
avx.set_xlabel(r'Phases [$\pi$]')
avy.set_xlabel(r'Phases [$\pi$]')

fig.show()
if show_fig:
fig.show()
return fig, ((ahx, ahy), (avy, avx))

def plot_bpms_fluctuations(self):
def plot_bpms_fluctuations(self, show_fig=True):
"""Plot BPMs flutuations statistics along BPMs and Correctors.

Returns:
Expand Down Expand Up @@ -1035,11 +1045,12 @@ def plot_bpms_fluctuations(self):
ay.set_title('BPMs Variation along BPMs')

fig.tight_layout()
fig.show()
if show_fig:
fig.show()
return fig, (ax, ay)

def plot_orbit_residue_after_fitting(
self, bpm_idx=0, excit_idx=0, time_domain=True
self, bpm_idx=0, excit_idx=0, time_domain=True, show_fig=True
):
"""Plot orbit residue after fitting.

Expand Down Expand Up @@ -1130,7 +1141,8 @@ def plot_orbit_residue_after_fitting(
ncol=4,
)
fig.tight_layout()
fig.show()
if show_fig:
fig.show()
return fig, (ax, ay), orbx, orby, dorbx, dorby

# ------------------ Auxiliary Methods ------------------
Expand Down Expand Up @@ -2366,3 +2378,258 @@ def _wait_cycle_to_finish(self, corr_names=None, timeout=10):
def _shift_list(lst, num):
"""."""
return lst[-num:] + lst[:-num]

# ----------------- ORM report Class ----------------------------------


class ORMReport(FPDF):
"""."""

# TODO: change labels "ac mat" or "dc mat" in the analysis plots
# use "measured mat" and "reference mat" instead
# adjust figures sizing
TIME_FMT = '%Y-%m-%d %H:%M:%S'

def _get_cnpem_logo_path(self):
import apsuite

return str(
Path(apsuite.__file__).parent / 'resources/cnpem_lnls_logo.jpg'
)

def __init__(self, meas_orm=None):
"""."""
super().__init__()
self.WIDTH = 210
self.HEIGHT = 297

self.meas_orm = meas_orm
self.params = None
self.data = None

self._folder = ''

def header(self):
"""."""
path = self._get_cnpem_logo_path()
self.image(path, x=10, y=6, w=40, h=15)
self.set_font('Arial', 'B', 14)
self.cell(0, 6, 'SIRIUS AC ORM Report', 0, 0, 'C')
self.set_font('Arial', '', 11)
now = datetime.datetime.now()
stg = '{:s}'.format(now.strftime(self.TIME_FMT))
self.cell(0, 6, stg, 0, 0, 'R')
self.ln(10)

def footer(self):
"""."""
self.set_y(-15)
self.set_font('Arial', 'I', 8)
self.set_text_color(129)
self.cell(0, 10, f'Page {self.page_no()}', 0, 0, 'C')

def page_title(self, title, loc_y=None):
"""."""
self.set_font('Arial', '', 12)
self.set_fill_color(215)
if loc_y is not None:
self.set_y(loc_y)
self.cell(0, 6, f'{title:s}', 0, 1, 'C', 1)
self.ln(2)

def meas_fingerprint(self):
"""."""
info = self.data['bpms_noise']

tstamp = datetime.datetime.fromtimestamp(info['timestamp'])
tstamp = tstamp.strftime(self.TIME_FMT)

rows = [
('Measurement Timestamp', tstamp),
('Stored current', f'{info["stored_current"]:.2f} [mA]'),
('RF Frequency', f'{info["rf_frequency"] / 1e6:.6f} [MHz]'),
('Neasyred frac. tune X', f'{info["tunex"]:.4f}'),
('Measured frac. tune y', f'{info["tuney"]:.4f}'),
('Sampling freq.', f'{info["sampling_frequency"]:.2f} [Hz]'),
('Acq rate', str(info['acq_rate'])),
('Switching mode', str(info['switching_mode'])),
('Switching freq.', f'{info["switching_frequency"]:.2f} [Hz]'),
]

self.set_font('Arial', '', 10)

w = self.WIDTH / 2.5
h = 5
x0 = (self.WIDTH - 2 * w) / 2

for row in rows:
self.set_x(x0)
for item in row:
self.cell(w, h, str(item), border=1, align='C')
self.ln(h)

def config_table(self):
"""."""
p = self.params

rows = [
('Timeout BPMs [s]', p.timeout_bpms),
('Timeout Correctors [s]', p.timeout_correctors),
('Meas BPM noise', p.meas_bpms_noise),
('Meas RF', p.meas_rf_line),
('Meas magnets', p.meas_magnets),
('CH kick [urad]', p.corrs_ch_kick),
('CV kick [urad]', p.corrs_cv_kick),
('CH freqs', str(p.corrs_ch_freqs)),
('CV freqs', str(p.corrs_cv_freqs)),
('RF mode', str(p._rf_mode)),
('RF step [Hz]', p.rf_step_kick),
('RF phase amp [deg]', p.rf_phase_amp),
]

self.set_font('Arial', '', 10)

w = self.WIDTH / 2.5
h = 5
x0 = (self.WIDTH - 2 * w) / 2

for row in rows:
self.set_x(x0)
for item in row:
self.cell(w, h, str(item), border=1, align='C')
self.ln(h)

def add_scale_factors(self):
"""."""
w = self.WIDTH - 30
x = (self.WIDTH - w) / 3

self.image(self._folder + 'scale_factors.png', x=x, y=26, w=w)

def add_correlations(self):
"""."""
w = self.WIDTH - 30
x = (self.WIDTH - w) / 3

self.image(self._folder + 'correlation.png', x=x, y=130, w=w)

def add_least_correlated(self):
"""."""
w = self.WIDTH - 30
x = (self.WIDTH - w) / 2

self.image(self._folder + 'least_corr_ch.png', x=x, y=26, w=w)
self.image(self._folder + 'least_corr_cv.png', x=x, y=155, w=w)

def add_best_correlated(self):
"""."""
w = self.WIDTH - 30
x = (self.WIDTH - w) / 2

self.image(self._folder + 'best_corr_ch.png', x=x, y=26, w=w)
self.image(self._folder + 'best_corr_cv.png', x=x, y=155, w=w)

def add_rf_column(self):
"""."""
w = self.WIDTH - 30
x = (self.WIDTH - w) / 2

self.image(self._folder + 'rf_column.png', x=x, y=26, w=w)

def create_report(self, meas_orm, folder=None):
"""."""
# TODO: change methods labels from "mat AC" or "mat DC"
# to "measured mat" and "reference mat", or something similar
if folder is None:
folder = ''

self.meas_orm = meas_orm
self.params = meas_orm.params
self.data = meas_orm.data
self._folder = folder

if not meas_orm.analysis:
meas_orm.process_data()

mat_ac = meas_orm.build_respmat()
mat_dc = meas_orm.get_ref_respmat()

fig, _ = meas_orm.plot_scale_conversion_factors(show_fig=False)
fig.savefig(folder + 'scale_factors.png', dpi=300)
_mplt.close(fig) # even if show_fig=False, figs can be displayed
# in interactive envs (notebooks specifically)

fig, _, corr = meas_orm.plot_comparison_correlations(
mat_ac=mat_ac, mat_dc=mat_dc, show_fig=False
)
fig.savefig(folder + 'correlation.png', dpi=300)
_mplt.close(fig)

corr_h = corr[:, :120]
corr_v = corr[:, 120:280]

idcsh = corr_h[1].argsort()
idcsv = corr_v[0].argsort() + 120

# least correlated
fig, _ = meas_orm.plot_comparison_single_corrector(
idcsh[-1], mat_ac=mat_ac, mat_dc=mat_dc, show_fig=False
)
fig.savefig(folder + 'least_corr_ch.png', dpi=300)
_mplt.close(fig)

fig, _ = meas_orm.plot_comparison_single_corrector(
idcsv[-1], mat_ac=mat_ac, mat_dc=mat_dc, show_fig=False
)
fig.savefig(folder + 'least_corr_cv.png', dpi=300)
_mplt.close(fig)

# best correlated
fig, _ = meas_orm.plot_comparison_single_corrector(
idcsh[0], mat_ac=mat_ac, mat_dc=mat_dc, show_fig=False
)
fig.savefig(folder + 'best_corr_ch.png', dpi=300)
_mplt.close(fig)

fig, _ = meas_orm.plot_comparison_single_corrector(
idcsv[0], mat_ac=mat_ac, mat_dc=mat_dc, show_fig=False
)
fig.savefig(folder + 'best_corr_cv.png', dpi=300)
_mplt.close(fig)

# rf
fig, _ = meas_orm.plot_comparison_single_corrector(
280, mat_ac=mat_ac, mat_dc=mat_dc, show_fig=False
)
fig.savefig(folder + 'rf_column.png', dpi=300)
_mplt.close(fig)

self.add_page()
self.page_title('Measurement fingerprint')
self.meas_fingerprint()
self.page_title('Measurement params. & setup', loc_y=80)
self.set_y(90)
self.config_table()

self.add_page()
self.page_title('Measurement scale factors')
self.add_scale_factors()

self.page_title(
'Measurement correlation residue (from unity)', loc_y=122
)
self.add_correlations()

self.add_page()
self.page_title('Least correlated columns comparison')
self.add_least_correlated()

self.add_page()
self.page_title('Most correlated columns comparison')
self.add_best_correlated()

self.add_page()
self.page_title('RF Column (dispersion) comparsion')
self.add_rf_column()

self.output(folder + 'orm_report.pdf', 'F')
Loading