0
0

compton_combiner.py 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509
  1. """Script to combine compton measurements with runs and process these data
  2. """
  3. import argparse
  4. from configparser import ConfigParser
  5. from datetime import datetime, timedelta, timezone
  6. import os
  7. import sqlite3
  8. from typing import Union, Tuple, Optional
  9. from compton_filter import CalibrdbHandler
  10. from iminuit import Minuit
  11. import matplotlib.dates as mdates
  12. import matplotlib.pyplot as plt
  13. from mysql.connector import connect, Error
  14. import numpy as np
  15. import pandas as pd
  16. from tqdm import tqdm
  17. SEASONS = {
  18. 'name': ['HIGH2017', 'RHO2018', 'HIGH2019', 'LOW2020', 'HIGH2020', 'HIGH2021', 'NNBAR2021'],
  19. 'start_run': [36872, 48938, 70014, 85224, 89973, 98116, 107342, None],
  20. }
  21. class RunsDBHandler():
  22. def __init__(self, host: str = 'cmddb', database: str = 'online', user: str = None, password: str = None):
  23. self.conn = connect(host = host, database = database, user = user, password = password)
  24. self.cur = self.conn.cursor()
  25. self.cur.execute("SET time_zone = '+07:00';")
  26. @property
  27. def fields(self) -> list:
  28. """Returns a list of available columns in the RunsDB
  29. """
  30. self.cur.execute("""DESCRIBE Runlog""")
  31. return self.cur.fetchall()
  32. def load_tables(self, range: Union[Tuple[int, Optional[int]], Tuple[datetime, datetime]], energy_point: Optional[float] = None, select_bad_runs: bool = False):
  33. """
  34. Parameters
  35. ----------
  36. range : Union[Tuple[int, Optional[int]], Tuple[datetime, datetime]]
  37. selection range
  38. int range defines an interval in runs
  39. datetime range defines a time interval (NSK: +7:00 time)
  40. energy_point : Optional[float]
  41. energy point name, MeV (default is None)
  42. select_bad_runs : bool
  43. select runs with labels except (Y) (default is False)
  44. """
  45. cond = ""
  46. if isinstance(range[0], int):
  47. cond = f" AND run >= {range[0]} "
  48. if range[1] is not None:
  49. cond += f" AND run <= {range[1]} "
  50. elif isinstance(range[0], datetime):
  51. cond = f" AND starttime >= %s "
  52. if range[1] is not None:
  53. cond += " AND stoptime <= %s"
  54. else:
  55. range = (range[0], )
  56. energy_cond = ""
  57. if energy_point is not None:
  58. energy_cond = f" AND energy = {energy_point}"
  59. quality_cond = ' quality = "Y" '
  60. if select_bad_runs:
  61. quality_cond = ' quality <> "Y" '
  62. sql_query = f"""
  63. SELECT
  64. run,
  65. starttime,
  66. stoptime,
  67. energy,
  68. luminosity
  69. FROM Runlog
  70. WHERE
  71. {quality_cond}
  72. {cond}
  73. {energy_cond}
  74. AND luminosity > 0
  75. AND stoptime > starttime
  76. AND nevent > 0
  77. ORDER BY run DESC"""
  78. if isinstance(range[0], datetime):
  79. self.cur.execute(sql_query, range)
  80. else:
  81. self.cur.execute(sql_query)
  82. field_names = [i[0] for i in self.cur.description]
  83. res = self.cur.fetchall()
  84. return res, field_names
  85. def __del__(self):
  86. self.conn.close()
  87. class Combiner():
  88. """Combines a dataframe with runs and a dataframe with compton measurements together
  89. """
  90. def __init__(self, runsdb: Tuple[list, list], clbrdb: Tuple[list, list]):
  91. """
  92. Parameters
  93. ----------
  94. runsdb : Tuple[list, list]
  95. table of runs (rows and field names)
  96. clbrdb : Tuple[list, list]
  97. table of compton measurements (rows and field names)
  98. """
  99. rdb_rows, r_fld = runsdb
  100. cdb_rows, c_fld = clbrdb
  101. self.conn = sqlite3.connect(":memory:", detect_types=sqlite3.PARSE_DECLTYPES|sqlite3.PARSE_COLNAMES)
  102. self.cur = self.conn.cursor()
  103. self.cur.execute(f"CREATE table runs (run, elabel, starttime timestamp, stoptime timestamp, luminosity)")
  104. self.cur.execute(f"CREATE table compton (begintime timestamp, endtime timestamp, e_mean, e_std, spread_mean, spread_std)")
  105. run_row_generator = map(lambda x: (x[r_fld.index("run")], x[r_fld.index("energy")],
  106. x[r_fld.index("starttime")], x[r_fld.index("stoptime")],
  107. x[r_fld.index("luminosity")]), rdb_rows)
  108. c_data_idx = c_fld.index("data")
  109. compton_row_generator = map(lambda x: (x[c_fld.index("begintime")], x[c_fld.index("endtime")],
  110. float(x[c_data_idx][0]), float(x[c_data_idx][1]),
  111. float(x[c_data_idx][2]), float(x[c_data_idx][3])), cdb_rows)
  112. self.cur.executemany(f"""INSERT into runs VALUES ({','.join(['?']*5)})""", run_row_generator)
  113. self.cur.executemany(f"""INSERT into compton VALUES ({','.join(['?']*6)})""", compton_row_generator)
  114. self.__create_combined_table()
  115. def __create_combined_table(self):
  116. create_combined_query = """
  117. CREATE TABLE combined_table AS
  118. SELECT
  119. runs.run AS run,
  120. runs.elabel AS elabel,
  121. runs.starttime as "run_start [timestamp]",
  122. runs.stoptime AS "run_stop [timestamp]",
  123. compton.begintime AS "compton_start [timestamp]",
  124. compton.endtime AS "compton_stop [timestamp]",
  125. runs.luminosity, compton.e_mean, compton.e_std, compton.spread_mean, compton.spread_std
  126. FROM runs, compton
  127. WHERE
  128. (runs.starttime BETWEEN compton.begintime AND compton.endtime)
  129. OR (runs.stoptime BETWEEN compton.begintime AND compton.endtime)
  130. OR (compton.begintime BETWEEN runs.starttime AND runs.stoptime)
  131. OR (compton.endtime BETWEEN runs.starttime AND runs.stoptime);
  132. """
  133. self.cur.execute(create_combined_query)
  134. return
  135. def combined_table(self) -> pd.DataFrame:
  136. """Returns combined dataframe
  137. """
  138. sql_query = """
  139. SELECT * FROM combined_table;
  140. """
  141. df = pd.read_sql(sql_query, self.conn)
  142. df['common_duration'] = df[['run_stop', 'compton_stop']].min(axis=1) - df[['run_start', 'compton_start']].max(axis=1)
  143. df['run_duration'] = df['run_stop'] - df['run_start']
  144. df['run_in_measurement'] = df['common_duration']/df['run_duration']
  145. df = df.sort_values(by='run_in_measurement', ascending=False).drop_duplicates(subset='run').sort_values(by='run')
  146. df = df.drop(['run_duration', 'common_duration'], axis=1) #, 'run_start', 'run_stop'
  147. return df
  148. def __del__(self):
  149. self.conn.close()
  150. class Likelihood():
  151. """
  152. Likelihood function
  153. """
  154. def __init__(self, means: np.array, sigmas: np.array, weights: np.array):
  155. """
  156. Parameters
  157. ----------
  158. means : np.array
  159. array of means, [MeV]
  160. sigmas : np.array
  161. array of standard deviations, [MeV]
  162. weights : np.array
  163. array of luminosities
  164. """
  165. self.means = means
  166. self.sigmas = sigmas
  167. self.weights = weights/weights.mean()
  168. def __call__(self, mean: float, sigma: float):
  169. """
  170. Calls likelihood calculation
  171. Parameters
  172. ----------
  173. mean : float
  174. expected mean
  175. sigma : float
  176. expected standard deviation
  177. """
  178. sigma_total = np.sqrt(sigma**2 + self.sigmas**2)
  179. ln_L = -np.sum( self.weights*( ((mean - self.means)**2)/(2*(sigma_total**2)) + np.log(sigma_total) ) )
  180. return -ln_L
  181. def __estimate_point_with_closest(comb_df: pd.DataFrame, runs_df: pd.DataFrame, compton_df: pd.DataFrame):
  182. # estimate energy by the nearest points
  183. min_run_time = runs_df[runs_df.run == comb_df.iloc[0].at['run_first']].iloc[0].at['starttime']
  184. max_run_time = runs_df[runs_df.run == comb_df.iloc[0].at['run_last']].iloc[0].at['stoptime']
  185. nearest_row_before = compton_df.iloc[pd.Index(compton_df.endtime).get_loc(min_run_time, 'nearest')]
  186. nearest_row_after = compton_df.iloc[pd.Index(compton_df.begintime).get_loc(max_run_time, 'nearest')]
  187. # regulatization
  188. nearest_row_before['data'][1] = max(nearest_row_before['data'][3], 1e-3)
  189. nearest_row_after['data'][3] = max(nearest_row_after['data'][3], 1e-3)
  190. nearest_row_before['data'][1] = max(nearest_row_before['data'][1], 1e-3)
  191. nearest_row_after['data'][3] = max(nearest_row_after['data'][3], 1e-3)
  192. mean_energy = (nearest_row_before['data'][0] + nearest_row_after['data'][0])/2
  193. mean_spread = (nearest_row_before['data'][2] + nearest_row_after['data'][2])/2
  194. std_energy = np.sqrt(1/(1/(nearest_row_before['data'][1])**2 + 1/(nearest_row_after['data'][1])**2))
  195. std_spread = np.sqrt(1/(1/(nearest_row_before['data'][3])**2 + 1/(nearest_row_after['data'][3])**2))
  196. sys_energy = np.std([nearest_row_before['data'][0], nearest_row_after['data'][0]])
  197. return {
  198. 'energy_point': comb_df.elabel.min(),
  199. 'first_run': comb_df.run_first.min(),
  200. 'last_run': comb_df.run_last.max(),
  201. 'mean_energy': mean_energy,
  202. 'mean_energy_stat_err': std_energy,
  203. 'mean_energy_sys_err': sys_energy,
  204. 'mean_spread': mean_spread,
  205. 'mean_spread_stat_err': std_spread,
  206. 'used_lum': 0,
  207. 'comment': 'indirect measurement #2',
  208. }, pd.DataFrame([])
  209. def calculate_point(comb_df: pd.DataFrame, runs_df: pd.DataFrame, compton_df: pd.DataFrame, rdb) -> dict:
  210. """Calculates parameters of the energy (mean, std, spread) in this dataFrame
  211. Parameters
  212. ----------
  213. comb_df : pd.DataFrame
  214. table of the measurements linked with runs
  215. runs_df : pd.DataFrame
  216. table of the runs
  217. compton_df : pd.DataFrame
  218. table of the comptons
  219. Returns
  220. -------
  221. dict, pd.DataFrame
  222. average parameters on this DataFrame, clean dataFrame
  223. """
  224. if (len(comb_df) == 1) and pd.isnull(comb_df.iloc[0].at['compton_start']):
  225. # no direct measurements of the compton during data runs
  226. min_Yruntime = runs_df[runs_df.run == comb_df.iloc[0].at['run_first']].iloc[0].at['starttime']
  227. max_Yruntime = runs_df[runs_df.run == comb_df.iloc[0].at['run_last']].iloc[0].at['stoptime']
  228. dlt0 = timedelta(days=1)
  229. # assymetric time because energy can be stable only after
  230. runs_df_with_bads = rdb.load_tables((min_Yruntime, max_Yruntime + dlt0), energy_point = comb_df.iloc[0].at['elabel'], select_bad_runs = True)
  231. if len(runs_df_with_bads[0]) == 0:
  232. return __estimate_point_with_closest(comb_df, runs_df, compton_df)
  233. runs_df_with_bads_df = pd.DataFrame(runs_df_with_bads[0], columns = runs_df_with_bads[1])
  234. min_run_time, max_run_time = min(min_Yruntime, runs_df_with_bads_df.starttime.min()), max(max_Yruntime, runs_df_with_bads_df.stoptime.max())
  235. compton_meas = compton_df.query('((begintime>=@min_run_time)&(begintime<=@max_run_time))|((endtime>=@min_run_time)&(endtime<=@max_run_time))').copy()
  236. res_df = pd.DataFrame(list(map(lambda x: {
  237. 'compton_start': x[1]['begintime'],
  238. 'compton_stop': x[1]['endtime'],
  239. 'e_mean': float(x[1]['data'][0]),
  240. 'e_std': float(x[1]['data'][1]),
  241. 'spread_mean': float(x[1]['data'][2]),
  242. 'spread_std': float(x[1]['data'][3]),
  243. }, compton_meas.iterrows())))
  244. res_df = res_df.query(f'abs(e_mean -{comb_df.iloc[0].at["elabel"]})<5')
  245. if len(res_df) == 0:
  246. return __estimate_point_with_closest(comb_df, runs_df, compton_df)
  247. return {
  248. 'energy_point': comb_df.elabel.min(),
  249. 'first_run': comb_df.run_first.min(),
  250. 'last_run': comb_df.run_last.max(),
  251. 'mean_energy': res_df.e_mean.mean(),
  252. 'mean_energy_stat_err': np.sqrt(1/np.sum(1/(res_df.e_std)**2)),
  253. 'mean_energy_sys_err': np.abs(comb_df.iloc[0].at['elabel'] - res_df.e_mean.mean()),
  254. 'mean_spread': res_df.spread_mean.mean(),
  255. 'mean_spread_stat_err':np.sqrt(1/np.sum(1/(res_df.spread_std)**2)),
  256. 'used_lum': 0,
  257. 'comment': 'indirect measurement #1',
  258. }, res_df
  259. df = comb_df.loc[~comb_df.compton_start.isna()].copy()
  260. df.spread_std = np.where(df.spread_std < 1e-4, 1e-4, df.spread_std)
  261. df = df[df.e_std > 0]
  262. mean_energy = np.sum(df.e_mean*df.luminosity/(df.e_std**2))/np.sum(df.luminosity/(df.e_std**2))
  263. # std_energy = np.sqrt(1/np.sum((df.luminosity/df.luminosity.mean())/df.e_std**2))
  264. good_criterion = np.abs((df.e_mean - mean_energy)/np.sqrt(df.e_mean.std()**2 + df.e_std**2)) < 5
  265. #print(df[~good_criterion].elabel.value_counts())
  266. df = df[good_criterion]
  267. m = Minuit(Likelihood(df.e_mean, df.e_std, df.luminosity), mean=df.e_mean.mean(), sigma=df.e_mean.std())
  268. m.errordef = 0.5
  269. m.limits['sigma'] = (0, None)
  270. m.migrad();
  271. sys_err = m.values['sigma']
  272. mean_en = m.values['mean']
  273. mean_spread = np.sum(df.spread_mean*df.luminosity/(df.spread_std**2))/np.sum(df.luminosity/(df.spread_std**2))
  274. std_spread = np.sqrt(1/np.sum((df.luminosity/df.luminosity.mean())/df.spread_std**2))
  275. res_dict = {
  276. 'energy_point': comb_df.elabel.min(),
  277. 'first_run': comb_df.run_first.min(),
  278. 'last_run': comb_df.run_last.max(),
  279. 'mean_energy': mean_en,
  280. 'mean_energy_stat_err': m.errors['mean'],
  281. 'mean_energy_sys_err': sys_err,
  282. 'mean_spread': mean_spread,
  283. 'mean_spread_stat_err': std_spread,
  284. 'used_lum': df.luminosity.sum()/comb_df.luminosity_total.sum(),
  285. 'comment': '',
  286. }
  287. return res_dict, df
  288. def process_intersected_compton_meas(combined_df: pd.DataFrame) -> pd.DataFrame:
  289. """Replaces compton measurements writed on the border of two energy points on NaNs
  290. """
  291. energy_point_borders = combined_df[['point_idx', 'elabel', 'run_start', 'run_stop']].groupby(['point_idx'], dropna=True).agg(
  292. elabel_start_time=('run_start', 'min'), elabel_stop_time=('run_stop', 'max'),
  293. )
  294. df_comb = combined_df.set_index('point_idx').join(energy_point_borders, how='left')
  295. df_comb['comptonmeas_in_elabel'] = (df_comb[['elabel_stop_time', 'compton_stop']].min(axis=1) - df_comb[['elabel_start_time', 'compton_start']].max(axis=1))/(df_comb['compton_stop'] - df_comb['compton_start'])
  296. #print(df_comb['comptonmeas_in_elabel'].dropna().sort_values())
  297. df_comb = df_comb.query('comptonmeas_in_elabel < 0.7')
  298. border_comptons = df_comb.compton_start.values
  299. #print(combined_df.compton_start.isin(border_comptons).sum())
  300. #print(combined_df.loc[combined_df.compton_start.isin(border_comptons)].elabel.value_counts())
  301. combined_df.loc[combined_df.compton_start.isin(border_comptons), ['compton_start', 'compton_stop', 'e_mean', 'e_std', 'spread_mean', 'spread_std']] = np.nan
  302. return combined_df
  303. def process_combined(combined_df: pd.DataFrame, runs_df: pd.DataFrame, compton_df: pd.DataFrame, pics_folder: Optional[str] = None, rdb: Optional[RunsDBHandler] = None) -> pd.DataFrame:
  304. if pics_folder is not None:
  305. plt.ioff()
  306. plt.style.use('ggplot')
  307. locator = mdates.AutoDateLocator(minticks=5)
  308. formatter = mdates.ConciseDateFormatter(locator)
  309. formatter.formats = ['%y', '%b', '%d', '%H:%M', '%H:%M', '%S.%f', ]
  310. formatter.zero_formats = [''] + formatter.formats[:-1]
  311. formatter.zero_formats[3] = '%d-%b'
  312. formatter.offset_formats = ['', '%Y', '%b %Y', '%d %b %Y', '%d %b %Y', '%d %b %Y %H:%M', ]
  313. runs_df = runs_df.rename({'luminosity': 'luminosity_full', 'energy': 'elabel'}, axis=1)
  314. combined_df = pd.merge(combined_df.drop(['elabel'], axis=1), runs_df[['run', 'elabel', 'luminosity_full']], how='outer')
  315. combined_df = combined_df.sort_values(by='run')
  316. combined_df['luminosity'] = combined_df['luminosity'].fillna(0)
  317. combined_df['point_idx'] = np.cumsum(~np.isclose(combined_df.elabel, combined_df.elabel.shift(1), atol=1e-4))
  318. combined_df = process_intersected_compton_meas(combined_df)
  319. combined_df = combined_df.groupby(['point_idx', 'compton_start'], dropna=False).agg(
  320. elabel=('elabel', 'min'), elabel_test=('elabel', 'max'),
  321. run_first=('run', 'min'), run_last=('run', 'max'),
  322. luminosity=('luminosity', 'sum'), luminosity_total=('luminosity_full', 'sum'),
  323. compton_stop=('compton_stop', 'min'), compton_stop_test=('compton_stop', 'max'),
  324. e_mean=('e_mean', 'min'), e_mean_test=('e_mean', 'max'),
  325. e_std=('e_std', 'min'), e_std_test=('e_std', 'max'),
  326. spread_mean=('spread_mean', 'min'), spread_mean_test=('spread_mean', 'max'),
  327. spread_std=('spread_std', 'min'), spread_std_test=('spread_std', 'max'),
  328. ).reset_index().set_index('point_idx')
  329. #return combined_df
  330. result_df = pd.DataFrame(columns=['energy_point', 'first_run', 'last_run', 'mean_energy', 'mean_energy_stat_err', 'mean_energy_sys_err', 'mean_spread', 'mean_spread_stat_err', 'used_lum', 'comment'])
  331. for i, table in tqdm(combined_df.groupby('point_idx', dropna=False)):
  332. res_dict, good_df = calculate_point(table, runs_df, compton_df, rdb)
  333. result_df = result_df.append(res_dict, ignore_index=True)
  334. if pics_folder is not None:
  335. plt_table = good_df.dropna()
  336. if len(plt_table) == 0:
  337. continue
  338. total_error = np.sqrt(res_dict["mean_energy_stat_err"]**2 + res_dict["mean_energy_sys_err"]**2)
  339. half_timedelta = (plt_table.compton_stop - plt_table.compton_start)/2
  340. time = plt_table.compton_start + half_timedelta
  341. dlt0, total_time = timedelta(days=1), plt_table.compton_stop.max() - plt_table.compton_stop.min()
  342. timelim = [plt_table.compton_start.min() - 0.05*total_time, plt_table.compton_stop.max() + 0.05*total_time]
  343. fig, ax = plt.subplots(1, 1, dpi=120, tight_layout=True)
  344. ax.errorbar(time, plt_table.e_mean, xerr=half_timedelta, yerr=plt_table.e_std, fmt='.')
  345. ax.axhline(res_dict['mean_energy'], color='black', zorder=3, label='Mean')
  346. ax.fill_between(timelim,
  347. [res_dict['mean_energy'] - total_error]*2,
  348. [res_dict['mean_energy'] + total_error]*2, color='green', zorder=1, alpha=0.4)
  349. ax.tick_params(axis='x', labelrotation=45)
  350. ax.xaxis.set_major_locator(locator)
  351. ax.xaxis.set_major_formatter(formatter)
  352. ax.set(title=f'{res_dict["energy_point"]}, E = {res_dict["mean_energy"]:.3f} ± {res_dict["mean_energy_stat_err"]:.3f} ± {res_dict["mean_energy_sys_err"]:.3f} MeV',
  353. xlabel='Time, NSK', ylabel='Energy, [MeV]', xlim=timelim)
  354. plt.savefig(f'{pics_folder}/{res_dict["first_run"]}_{res_dict["energy_point"]}.png', transparent=True)
  355. plt.close()
  356. return result_df
  357. def final_table_to_clbrdb(df: pd.DataFrame, clbrdb: CalibrdbHandler, runs_df: pd.DataFrame, season: str):
  358. """Write good values from the averaged table into clbrdb
  359. """
  360. good_values = (df.comment=='')|((df.comment!='')&((df.mean_energy.astype(float) - df.energy_point).abs()<5))
  361. df_clbrdb = df.loc[good_values].drop(['comment', 'used_lum'], axis=1)
  362. df_clbrdb = pd.merge(df_clbrdb, runs_df[['run', 'starttime']], how='left', left_on='first_run', right_on='run').drop(['run'], axis=1)
  363. df_clbrdb = pd.merge(df_clbrdb, runs_df[['run', 'stoptime']], how='left', left_on='last_run', right_on='run').drop(['run'], axis=1)
  364. df_clbrdb = df_clbrdb.assign(writetime=lambda df: df['stoptime'])
  365. df_clbrdb = df_clbrdb[['writetime', 'starttime', 'stoptime',
  366. 'energy_point', 'first_run', 'last_run', 'mean_energy',
  367. 'mean_energy_stat_err', 'mean_energy_sys_err', 'mean_spread', 'mean_spread_stat_err']].values.tolist()
  368. clbrdb.insert(df_clbrdb, 'Misc', 'RunHeader', 'Compton_run_avg', 'Default', comment = season)
  369. clbrdb.commit()
  370. def save_csv(df: pd.DataFrame, filepath: str):
  371. """Saves csv file. Updates current file in filepath if exists"""
  372. if os.path.isfile(filepath):
  373. df_current = pd.read_csv(filepath)
  374. df_current = df_current.append(df, ignore_index=True)
  375. df_current = df_current.drop_duplicates(subset=['energy_point', 'first_run'], keep='last')
  376. df = df_current
  377. df.to_csv(filepath, index=False, float_format='%g')
  378. return
  379. # python scripts/compton_combiner.py -s NNBAR2021 -c database.ini --csv_dir . --clbrdb
  380. def main():
  381. parser = argparse.ArgumentParser(description = 'Mean compton energy measurements from clbrdb')
  382. parser.add_argument('-s', '--season', help = 'Name of the season')
  383. parser.add_argument('-c', '--config', help = 'Config file containing information for access to databases')
  384. parser.add_argument('--csv_dir', help = 'Save csv file with data in the folder or not if skip it')
  385. parser.add_argument('--clbrdb', action = 'store_true', help = 'Update Compton_run_avg clbrdb or not')
  386. parser.add_argument('--pics_folder', help = 'Path to the directory for saving the pictures')
  387. parser.add_argument('--only_last', action = 'store_true', help = 'Compute values of the last (in Compton_run_avg clbrdb) and new points only')
  388. args = parser.parse_args()
  389. # logging.info(f"Arguments: season: {args.season}, config {args.config}")
  390. parser = ConfigParser()
  391. parser.read(args.config);
  392. rdb = RunsDBHandler(**parser['cmdruns'])
  393. clbrdb = CalibrdbHandler(**parser['clbrDB'])
  394. idx = SEASONS['name'].index(args.season)
  395. runs_range = (SEASONS['start_run'][idx], SEASONS['start_run'][idx+1])
  396. if args.only_last:
  397. res_avg = clbrdb.load_table('Misc', 'RunHeader', 'Compton_run_avg', num_last_rows = 1)
  398. if len(res_avg[0]) != 0:
  399. begintime = res_avg[0][0][res_avg[1].index("begintime")]
  400. runs_range = (begintime, None)
  401. res_rdb = rdb.load_tables(runs_range)
  402. runs_df = pd.DataFrame(res_rdb[0], columns=res_rdb[1])
  403. tdlt0 = timedelta(days=2)
  404. time_range = (runs_df.starttime.min() - tdlt0, runs_df.stoptime.max() + tdlt0)
  405. res_clbrdb = clbrdb.load_table('Misc', 'RunHeader', 'Compton_run', num_last_rows = None, timerange = time_range)
  406. cb = Combiner(res_rdb, res_clbrdb)
  407. comb_df = cb.combined_table()
  408. compton_df = pd.DataFrame(res_clbrdb[0], columns=res_clbrdb[1])
  409. cdf = process_combined(comb_df, runs_df, compton_df, args.pics_folder, rdb)
  410. if args.csv_dir is not None:
  411. csv_path = os.path.join(args.csv_dir, f'{args.season}.csv')
  412. save_csv(cdf, csv_path)
  413. # cdf.to_csv(f'{args.season}.csv', index=False, float_format='%g')
  414. if args.clbrdb:
  415. final_table_to_clbrdb(cdf, clbrdb, runs_df, args.season)
  416. return
  417. if __name__ == "__main__":
  418. main()