Nevar pievienot vairāk kā 25 tēmas Tēmai ir jāsākas ar burtu vai ciparu, tā var saturēt domu zīmes ('-') un var būt līdz 35 simboliem gara.

175 rindas
7.8 KiB

  1. from antab_editor_lib.meta_data import (
  2. MetaData, get_setup_stations, get_station_scans, get_channel_map,
  3. header2channels)
  4. from antab_editor_lib.station_widget import create_station_widget
  5. from antab_editor_lib.poly_plot import PolyPlotWidget
  6. from antab_editor_lib.general import GeneralWidget
  7. from antab_editor_lib import antab_file
  8. from PyQt5.QtWidgets import QApplication, QTabWidget
  9. import sys
  10. import argparse
  11. import os
  12. import copy
  13. if __name__ == "__main__":
  14. parser = argparse.ArgumentParser(description="GUI to edit ANTAB files. "
  15. "Documentation available at "
  16. "https://code.jive.eu/eldering/antab")
  17. parser.add_argument("-e", "--experiment", default=None,
  18. help="Experiment to handle, defaults to the current "
  19. "directory name.")
  20. parser.add_argument("-s", "--setupstation", default=None,
  21. help="Force setup station, required if setup station "
  22. "cannot be determined from correlator database.")
  23. parser.add_argument("-l", "--spectralline",
  24. action="store_true", default=False,
  25. help="Generate two ANTAB files per station, one for "
  26. "the continuum pass (from *_1_1.IDI* files) and one "
  27. "for the spectral line pass (from *_2_1.IDI* files).")
  28. parser.add_argument("-a", "--addfits", default=[], nargs="+",
  29. metavar="EXPERIMENT",
  30. help="Additionally read FITS files for given "
  31. "experiment(s).")
  32. args = parser.parse_args()
  33. experiment = args.experiment
  34. if experiment is None:
  35. experiment = os.path.split(os.getcwd())[1]
  36. setup_station = args.setupstation
  37. if setup_station is None:
  38. setup_stations = get_setup_stations(experiment)
  39. if len(setup_stations) != 1:
  40. print("Cannot determine setup station automatically, "
  41. "specify it using the -s/--setupstation option.")
  42. sys.exit(1)
  43. setup_station = setup_stations[0][0]
  44. print(f"Using {setup_station} as setup station.")
  45. app = QApplication(sys.argv)
  46. meta_data = MetaData(experiment, setup_station,
  47. args.spectralline, args.addfits)
  48. vex = meta_data.get_vex()
  49. main_widget = QTabWidget()
  50. station_widgets = {}
  51. scans = vex["SCHED"].values()
  52. for station in sorted(vex["STATION"].keys()):
  53. if len(get_station_scans(scans, station)) == 0:
  54. print(f"Warning, ignoring {station} because it is not in any VEX "
  55. "scan.")
  56. continue
  57. if len(meta_data.fits_cache.station_time_ranges[station]) == 0:
  58. print(f"Warning, ignoring {station} because it has no data in any "
  59. "FITS file.")
  60. continue
  61. station_widget = create_station_widget(
  62. station, experiment, meta_data)
  63. main_widget.addTab(station_widget, station)
  64. station_widgets[station] = station_widget
  65. poly_widget = PolyPlotWidget(station_widgets, meta_data)
  66. main_widget.insertTab(0, poly_widget, "Polys")
  67. general_widget = GeneralWidget(station_widgets, meta_data)
  68. main_widget.insertTab(0, general_widget, "Overview")
  69. def activate_station_tab(station):
  70. for tab_index in range(main_widget.count()):
  71. if main_widget.tabText(tab_index) == station:
  72. main_widget.setCurrentIndex(tab_index)
  73. break
  74. general_widget.station_clicked.connect(activate_station_tab)
  75. def write_antab():
  76. assert((not args.spectralline) or
  77. (len(meta_data.fits_cache.pass_time_ranges) == 1))
  78. no_pass = ((not args.spectralline) and
  79. (len(meta_data.fits_cache.pass_time_ranges) == 1))
  80. for pass_, time_ranges in meta_data.fits_cache.pass_time_ranges.items():
  81. pass_ext = "" if no_pass else f"_{pass_}"
  82. with open(f"{experiment.lower()}{pass_ext}.antab", "w") as fp:
  83. for w in station_widgets.values():
  84. if no_pass:
  85. w.save_to(fp)
  86. else:
  87. # FIX too strict filter, add times in gaps to time_ranges
  88. w.save_to_filtered(fp, time_ranges)
  89. if args.spectralline:
  90. # map the spectral line correlator output channels to
  91. # the continuum correlator output channels and
  92. # change the INDEX field accordingly
  93. # assertion guarantees that there is only one pass
  94. time_ranges = next(iter(
  95. meta_data.fits_cache.pass_time_ranges.values()))
  96. def get_channels(timed_channels):
  97. ret = None
  98. for channel_time_range, channels in timed_channels.items():
  99. overlap = any(((time_range[1] > channel_time_range[0]) and
  100. (time_range[0] < channel_time_range[1]))
  101. for time_range in time_ranges)
  102. if overlap:
  103. if ret is None:
  104. ret = channels
  105. elif channels != ret:
  106. raise RuntimeError(
  107. "Multiple frequency setups found, "
  108. "this is not supported in spectral line mode.")
  109. if ret is None:
  110. raise RuntimeError(
  111. "Failed to find any frequency setup in time range "
  112. f"{time_range[0]} - {time_range[1]}.")
  113. return ret
  114. channel_map = get_channel_map(
  115. get_channels(meta_data.fits_cache.spectral_frequency),
  116. get_channels(meta_data.fits_cache.time_frequency))
  117. with open(f"{experiment.lower()}_2.antab", "w") as fp:
  118. for station in sorted(station_widgets.keys()):
  119. widget = station_widgets[station]
  120. for station_data in widget.get_station_data_sections():
  121. rename_map = {}
  122. for continuum_column_header in \
  123. station_data.data.columns:
  124. old_channels = set(
  125. header2channels(continuum_column_header))
  126. # the new INDEX column header is composed of all
  127. # spectral channels which map to a continuum channel
  128. # in the old INDEX column header
  129. new_channels = [k for k, v in channel_map.items()
  130. if v in old_channels]
  131. if len(new_channels) > 0:
  132. new_value = "|".join(new_channels)
  133. else:
  134. new_value = "X"
  135. rename_map[continuum_column_header] = new_value
  136. data = station_data.data.rename(columns=rename_map,
  137. copy=False,
  138. inplace=False,
  139. errors="raise")
  140. antab_file.write(fp, station_data.header, data)
  141. general_widget.generate_clicked.connect(write_antab)
  142. def save_all():
  143. for w in station_widgets.values():
  144. w.save()
  145. general_widget.save_all_clicked.connect(save_all)
  146. main_widget.setCurrentIndex(0)
  147. main_widget.show()
  148. desktop = QApplication.desktop()
  149. main_widget.resize(main_widget.minimumSizeHint().expandedTo(
  150. desktop.screenGeometry(desktop.screenNumber(main_widget)).size()/2))
  151. app.exec_()