elabelizer.py 7.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242
  1. """
  2. The script is for corresponding the elabels from database and compton average measurements
  3. run it on cc-8 with the command:
  4. `python3 elabelizer.py`
  5. If this script is not working properly, try to setup environment firstly with the following command in bash:
  6. `source /sl/cmd3/cc8-64/Cmd3Off/tune.cmd3_runs_scripts.sh`
  7. This script is inspired by listoffdata.py script (/sl/cmd3/cc7-64/Cmd3Off/scripts/listoffdata.py)
  8. """
  9. from datetime import datetime
  10. from typing import Dict, List, Tuple, NamedTuple, Optional
  11. from pathlib import Path
  12. from urllib.request import urlopen
  13. import json
  14. import os
  15. os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'settings_read_all')
  16. API_KEY = "9e3b3d9b7a57098bb1bc0e5c5053f2084251cd00"
  17. import django
  18. django.setup()
  19. from cmdweb.apps.cmd3off.energypoints.models import EnergyPoint, Param, ParamData
  20. class RowEPoint(NamedTuple):
  21. """Structure of the energy point metadata"""
  22. elabel: str
  23. first_run: int
  24. last_run: int
  25. nominal_energy: float
  26. start_time: datetime
  27. stop_time: datetime
  28. season: str
  29. class AvgEPoint(NamedTuple):
  30. """Structure of the averaged beam energy point"""
  31. energy_mean: float
  32. first_run: int
  33. last_run: int
  34. nominal_energy: float
  35. season: str
  36. class CombinedEPoint(NamedTuple):
  37. """Structure of the combined energy point"""
  38. season: str
  39. elabel: Optional[str]
  40. energy_mean: Optional[float]
  41. def retrieve_elabels(startrun: int, stoprun: int) -> List[RowEPoint]:
  42. """Retrieves elabels from database
  43. Parameters:
  44. -----------
  45. startrun : int
  46. first run for retrieving
  47. stoprun : int
  48. last run for retrieving
  49. Returns:
  50. --------
  51. List[RowEPoint]
  52. list of elabels and information about them
  53. (elabel, firstrun, lastrun, nominal energy, starttime, stoptime, season)
  54. """
  55. points, seasons = [], []
  56. # Get seasons (they are sorted by date)
  57. for e in EnergyPoint.objects.filter(name__startswith="Season"):
  58. info = [e.name[7:], e.startrun, e.endrun]
  59. seasons.append(info)
  60. # Get energy points (they are sorted by date) and match corresponing seasons
  61. season_idx = 0
  62. for e in EnergyPoint.objects.filter(startrun__gte=startrun, endrun__lte=stoprun):
  63. while((e.startrun < seasons[season_idx][1]) or (e.endrun > seasons[season_idx][2])):
  64. season_idx+=1
  65. info = RowEPoint(
  66. elabel = e.name,
  67. first_run = e.startrun,
  68. last_run = e.endrun,
  69. nominal_energy = e.energy,
  70. start_time = e.starttime,
  71. stop_time = e.endtime,
  72. season = seasons[season_idx][0]
  73. )
  74. if not(e.name.startswith("Season")):
  75. points.append(info)
  76. return points
  77. def get_available_compton_seasons() -> Dict[str, str]:
  78. """Returns a dictionary containing all available
  79. average energy season tables
  80. Returns
  81. -------
  82. Dict[str, str]
  83. keys are season names, values are pathes to the tables
  84. """
  85. tables_url = f'https://cmd.inp.nsk.su/~compton/gogs/api/v1/repos/compton/tables/contents/?token={API_KEY}'
  86. with urlopen(tables_url) as f:
  87. data_str = f.read().decode('utf-8')
  88. data = json.loads(data_str)
  89. datarows = {Path(row['name']).stem: row['download_url'] for row in
  90. filter(lambda x: (x['type'] == 'file') and x['name'].endswith('.csv'), data)}
  91. return datarows
  92. def retrieve_comptons(season_names: Optional[List[str]] = None) -> List[AvgEPoint]:
  93. """Retrieves compton measurements from tables
  94. Parameters:
  95. -----------
  96. season_names: Optional[List[str]]
  97. list of seasons for retrieving
  98. (default is None, it means retrieving all available seasons)
  99. Returns:
  100. --------
  101. List[AvgEPoint]
  102. list of compton means measurements
  103. (season, energy_point, first_run, last_run, mean_energy)
  104. first_run and last_run can be different from the corresponding energy points from elabels database
  105. """
  106. available_seasons = get_available_compton_seasons()
  107. seasons = dict()
  108. if season_names is not None:
  109. for s in season_names:
  110. try:
  111. seasons[s] = available_seasons[s]
  112. except KeyError:
  113. raise ValueError(f"Season {s} is not found. List of available seasons: {available_seasons.keys()}")
  114. else:
  115. seasons = available_seasons
  116. def parse_compton_row(row: str, season: str) -> AvgEPoint:
  117. items = row.split(',')
  118. return AvgEPoint(
  119. season=season,
  120. nominal_energy=float(items[0]),
  121. first_run=int(items[1]),
  122. last_run=int(items[2]),
  123. energy_mean=float(items[3])
  124. )
  125. def retrieve_compton_one_season(season_name: str, season_table_url: str) -> List[AvgEPoint]:
  126. with urlopen(season_table_url) as f:
  127. r = f.read().decode('utf-8').strip()
  128. rows = list(map(lambda x: parse_compton_row(x, s_name), r.split('\n')[1:]))
  129. return rows
  130. datarows = []
  131. for s_name, s_table in seasons.items():
  132. seasonrows = retrieve_compton_one_season(s_name, s_table)
  133. datarows.extend(seasonrows)
  134. return datarows
  135. def combine_compton_elabel(epoints: List[RowEPoint], comptonpoints: List[AvgEPoint]) -> List[CombinedEPoint]:
  136. """Combines compton energy points and elabels from database
  137. Parameters:
  138. -----------
  139. epoints : List[RowEPoint]
  140. list of energy points
  141. comptonpoints : List[AvgEPoint]
  142. list of compton averaged points
  143. Returns:
  144. --------
  145. combpoints : List[CombinedEPoint]
  146. list of combined points (outer join)
  147. """
  148. epoints_sorted = sorted(epoints, key=lambda x: x.first_run)
  149. cpoints_sorted = sorted(comptonpoints, key=lambda x: x.first_run)
  150. combined_data = []
  151. eidx, cidx = 0, 0
  152. while (eidx < len(epoints_sorted)) and (cidx < len(cpoints_sorted)):
  153. erow = epoints_sorted[eidx]
  154. crow = cpoints_sorted[cidx]
  155. cstart, cstop, cenergy, cseason = crow.first_run, crow.last_run, crow.energy_mean, crow.season
  156. estart, estop, elabel, eseason = erow.first_run, erow.last_run, erow.elabel, erow.season
  157. if (cstart >= estart) and (cstop <= estop):
  158. combrow = CombinedEPoint(eseason, elabel, cenergy)
  159. eidx += 1
  160. cidx += 1
  161. #print(combrow)
  162. elif (cstart > estop):
  163. combrow = CombinedEPoint(eseason, elabel, None)
  164. eidx += 1
  165. elif (estart > cstop):
  166. combrow = CombinedEPoint(cseason, None, cenergy)
  167. cidx += 1
  168. else:
  169. raise Exception("Something wrong")
  170. # print(combrow)
  171. combined_data.append(combrow)
  172. for i in range(eidx, len(epoints_sorted)):
  173. erow = epoints_sorted[i]
  174. combrow = CombinedEPoint(erow.season, erow.elabel, None)
  175. combined_data.append(combrow)
  176. for i in range(cidx, len(cpoints_sorted)):
  177. crow = cpoints_sorted[i]
  178. combrow = CombinedEPoint(crow.season, None, crow.energy_mean)
  179. combined_data.append(combrow)
  180. return combined_data
  181. def elabelize() -> List[CombinedEPoint]:
  182. RUNLIMITS = (17405, 200000)
  183. SEASONS = None
  184. epoints = retrieve_elabels(*RUNLIMITS)
  185. comptonpoints = retrieve_comptons(SEASONS)
  186. combdata = combine_compton_elabel(epoints, comptonpoints)
  187. return combdata
  188. def main():
  189. combdata = elabelize()
  190. for c in combdata:
  191. season, elabel, energy = c.season, c.elabel, c.energy_mean
  192. if season is None:
  193. season = ''
  194. if elabel is None:
  195. elabel = ''
  196. print(f'{season:>15s}, {elabel:>13s}, {energy}')
  197. print('The number of not found points in compton is', len(list(filter(lambda x: x[2] is None, combdata))))
  198. if __name__=="__main__":
  199. main()