def geochk(j_scan, scan_index, start_time, end_time): ok_geo = np.empty(shape=s.schsou.geosrci.shape, dtype=bool) use_geo = np.empty(shape=s.schsou.geosrci.shape, dtype=int) scans = scan_catalog.direct_access_entries stations = station_catalog.used(use_direct_access=True) sources = source_catalog.entries seg_elevation = np.empty(dtype=float, shape=(len(stations), s.schsou.ngeo)) use_time = True last_scan_index = np.zeros(shape=(StationCatalog.maxsta, )) approx_time = (start_time + end_time) / 2 n_reject = 0 if len(stations) > 20: s.wlog(1, "GEOCHK: Printing only first 20 stations information") ms_print = 20 else: ms_print = len(stations) s.wlog(1, " --------------------- ") year, day, time_rad = s.timej(approx_time) c_time = f2str(s.tformwrp(time_rad, "T", 0, 2, 2, "::@")) s.wlog( 1, "Building geodetic segment centered at {} {} {}".format( year, day, c_time)) s.wlog( 1, " Using GEOPRT={:>4} GEOTRIES={:>4} GEOBACK={:>3} " "GEOSREP={:>3}".format(s.schsou.geoprt, s.schsou.geotries, s.schsou.geoback, s.schsou.geosrep)) s.wlog( 1, " GEOSLEW={:>6.2f} GEOSLOW={:>7.1f} GELOWEL={:>6.2f} " "GEOHIEL={:>6.2f}".format(s.schsou.geoslew, s.schsou.geoslow, s.schsou.geolowel, s.schsou.geohiel)) s.wlog(1, " See sched.runlog for details of the build process.") if s.schsou.geoprt >= 0: s.wlog( 0, " Note in fit, SecZ < 4 treated as 4 to avoid favoring " "extreme low elevations.") s.wlog(0, "Elevations at center for sources considered are: ") s.wlog( 0, " Prio " + " ".join(s.stcode for s in stations[:20])) elevation_tolerance = 0 sun_coord = SkyCoord(*s.sunpos(approx_time), unit="rad") t_freq = sf_catalog.entries[scans[j_scan - 1].setnum - 1].sffreq[0] / 1000 required_separation = 60 * (t_freq**-0.6) for geo_index in range(s.schsou.ngeo): l_scan = scan_index + 1 n_good = makescn(last_scan_index, l_scan, j_scan, s.schsou.geosrci[geo_index], f2str(s.schcsc.geosrc[geo_index]), approx_time, scans[j_scan - 1].opminel - elevation_tolerance, use_time) for i, station in enumerate(stations): seg_elevation[i, geo_index] = (station.el1[l_scan - 1] + station.el2[l_scan - 1]) / 2 ok_geo[geo_index] = (n_good >= scans[j_scan - 1].opmian) source = sources[s.schsou.geosrci[geo_index] - 1] source_coord = SkyCoord(source.rap, source.decp, unit="rad") source_separation = sun_coord.separation(source_coord).deg ok_geo[geo_index] = ok_geo[geo_index] and \ (source_separation > required_separation) if not ok_geo[geo_index]: n_reject += 1 use_geo[geo_index] = 9 if ok_geo[geo_index]: use_geo[geo_index] = 5 for i, station in enumerate(stations): if station.stascn[l_scan - 1]: if (seg_elevation[i, geo_index] <= s.schsou.geolowel + 10): use_geo[geo_index] = 4 for i, station in enumerate(stations): if station.stascn[l_scan - 1]: if (seg_elevation[i, geo_index] <= s.schsou.geolowel): use_geo[geo_index] = 3 n_low = 0 n_high = 0 for i, station in enumerate(stations): if station.stascn[l_scan - 1] and \ (seg_elevation[i, geo_index] > (scans[j_scan - 1].opminel - elevation_tolerance)) and \ (seg_elevation[i, geo_index] <= s.schsou.geolowel): n_low += 1 if station.stascn[l_scan - 1] and \ (seg_elevation[i, geo_index] >= s.schsou.geohiel): n_high += 1 if ((n_low >= 1) and (n_high >= 3)) or (n_low >= 3): use_geo[geo_index] = 2 if (n_low >= 2) and (n_high >= 2): use_geo[geo_index] = 1 if s.schsou.geoprt >= 0: msg = "{:>5d} {:<8} {:>5d}".format( geo_index + 1, f2str(s.schcsc.geosrc[geo_index]), use_geo[geo_index]) msg += "".join( "{:5.0f}".format(el) if el > (scans[l_scan - 1].opminel - elevation_tolerance) else " --" for el in seg_elevation[:, geo_index]) if source_separation <= required_separation: msg += " Too near sun: {:5.0f} deg.".format( source_separation) s.wlog(0, msg) if n_reject == s.schsou.ngeo: s.errlog("GEOCHK: None of the sources specified for a geodetic " "segment are up at OPMINANT antennas.") return ok_geo, use_geo, seg_elevation
def addpeak(last_scan_index, scans, stations, setups, peak_groups, peak_opt, insert_adjust, scan_index): if s.schcon.debug: s.wlog(0, "ADDPEAK starting") scan = scans[scan_index - 1] if (not s.schcon.autopeak) or ((scan.point >= -1) and (peak_opt == 0)): return peak_opt, insert_adjust assert(s.schpeakn.npkgrp > 0), "ADDPEAK: Want automatic pointing, but "\ "there are no groups" t_gap = np.empty(dtype=float, shape=(len(stations), )) try_group = np.full(fill_value=False, shape=(len(peak_groups), )) try_group2 = np.full(fill_value=False, shape=(len(peak_groups), )) # last_*_scan objects are passed to FORTRAN, so require a fixed size, # only len(stations) is actually used last_target_scan = np.empty(dtype=int, shape=(StationCatalog.maxsta, )) last_pointing_scan = np.empty(dtype=int, shape=(StationCatalog.maxsta, )) sr_ok = np.empty(dtype=bool, shape=(s.schpeakn.pksrnum.shape[0], )) sr_ok2 = np.empty(dtype=bool, shape=(s.schpeakn.pksrnum.shape[0], )) slew_max = np.empty(dtype=float, shape=(s.schpeakn.pksrnum.shape[0], )) slew_min = np.empty(dtype=float, shape=(s.schpeakn.pksrnum.shape[0], )) if peak_opt == 0: if s.schcon.pkwatch: s.wlog(0, " ") year, day1, start = s.timej(scan.startj) stime = f2str(s.tformwrp(start, "T", 0, 2, 2, "::@")) s.wlog( 0, "ADDPEAK: Trying to add pointing scan for target scan " "{} {} {}".format(scan_index, scan.scnsrc, stime)) try_group = np.full(shape=(s.schpeakn.npkgrp, ), fill_value=False) try_group2 = np.full(shape=(s.schpeakn.npkgrp, ), fill_value=False) n_up = np.full(shape=(s.schpeakn.npkgrp, ), fill_value=0) m_settle = np.full(shape=(s.schpeakn.npkgrp, ), fill_value=0.0) n_good = 0 for station in stations: group_index = station.pkgroup if station.stascn[scan_index - 1] and (group_index != 0) and \ ((f2str(station.up1[scan_index - 1]) == "") or (f2str(station.up2[scan_index - 1]) == "")): n_good += 1 n_up[group_index - 1] += 1 if n_good == 0: if s.schcon.pkwatch: s.wlog( 0, "ADDPEAK: Source down or below OPMINEL at all " "stations.") return peak_opt, insert_adjust for station_index, station in enumerate(stations): if station.stascn[scan_index - 1] and (station.pkgroup > 0): setup = setups[station.nsetup[scan_index - 1] - 1] group_index = station.pkgroup freq_test = setup.freqref[0] peak_group = peak_groups[group_index - 1] if (peak_group.pkminfq < freq_test): if (last_scan_index[station_index] != 0): last_scan = scans[last_scan_index[station_index] - 1] t_gap[station_index] = scan.startj - last_scan.stopj lastptg = (last_scan.point in {0, group_index}) and \ (t_gap[station_index] < 600. / secpday) if (not lastptg) and (n_up[group_index - 1] > 0): if t_gap[station_index] > peak_group.pkdwell: try_group[group_index - 1] = True if t_gap[station_index] > 2 * peak_group.pkdwell: try_group2[group_index - 1] = True else: t_gap[station_index] = 10000 try_group[group_index - 1] = n_up[group_index - 1] > 0 try_group2[group_index - 1] = n_up[group_index - 1] > 0 last_target_scan[station_index] = last_scan_index[station_index] last_pointing_scan[station_index] = last_scan_index[station_index] n_try = np.count_nonzero(try_group) + np.count_nonzero(try_group2) if s.schcon.pkwatch: if n_try >= 1: for group_index, peak_group in enumerate(peak_groups): if try_group2[group_index]: s.wlog( 0, "ADDPEAK: Pointing group {}: Will try to " "add double pointing scans.".format(group_index + 1)) elif try_group[group_index]: s.wlog( 0, "ADDPEAK: Pointing group {}: Will try to " "add one pointing scan.".format(group_index + 1)) else: if n_up[group_index - 1] > 0: s.wlog( 0, "ADDPEAK: Pointing group {}: No " "stations up in scan.".format(group_index + 1)) else: s.wlog( 0, "ADDPEAK: Pointing group {}: Gap too " "short to add pointing scans.".format( group_index + 1)) else: s.wlog( 0, "ADDPEAK: Insufficient time to add pointing or " "last scan was pointing.") if n_try == 0: return peak_opt, insert_adjust keep_origen = scan.origen scan.origen = 4 for k_scan in range(scan_index, scan_index + n_try): scndup(k_scan, scan_index - 1, True, "ADDPEAK") n_added = 0 m_scan = scan_index + n_try for group_index, peak_group in enumerate(peak_groups, 1): if try_group[group_index - 1]: if s.schcon.pkwatch: s.wlog( 0, "ADDPEAK: Working on pointing group {}".format( group_index)) tab_head = True k_scan = scan_index + n_added got_station = False for station in stations: station.stascn[k_scan - 1] = \ station.stascn[m_scan - 1] and \ (station.pkgroup == group_index) and \ ((f2str(station.up1[m_scan - 1]) == "") or (f2str(station.up2[m_scan - 1]) == "")) if station.stascn[k_scan - 1]: got_station = True if got_station: for p_src in range(1, peak_group.npksrc + 1): stop_k = scans[m_scan - 1].startj - 20.0 * onesec start_k = stop_k - peak_group.pkdwell k_src = peak_group.pksrnum[p_src - 1] s.srinsert(k_scan, k_src, peak_group.pksrc[p_src - 1], start_k, stop_k, last_scan_index, m_scan) sr_ok[p_src - 1] = True sr_ok2[p_src - 1] = True watch_it = False min_el = 100 max_el = 0 min_slew = 1000 max_slew = 0 min_tot = 10000 for station in stations: if station.stascn[k_scan - 1] and \ (station.el1[k_scan - 1] < peak_group.pkminel): sr_ok[p_src - 1] = False sr_ok2[p_src - 1] = False if s.schcon.pkwatch: if station.stascn[k_scan - 1] and \ (f2str(station.up1[k_scan - 1]) == "") and \ (f2str(station.up2[k_scan - 1]) == ""): watch_it = True if station.stascn[k_scan - 1]: min_el = min(min_el, station.el1[k_scan - 1]) max_el = max(max_el, station.el1[k_scan - 1]) min_slew = min( min_slew, station.tslew[m_scan - 1] * secpday) max_slew = max( max_slew, station.tslew[m_scan - 1] * secpday) if sr_ok[p_src - 1]: for station_index, station in enumerate(stations): if station.stascn[k_scan - 1]: tot_time = peak_group.pkdwell + \ station.tslew[k_scan - 1] + \ station.tslew[m_scan - 1] if t_gap[station_index] < tot_time: sr_ok[p_src - 1] = False min_tot = min(min_tot, tot_time * secpday) tot_time2 = 2 * peak_group.pkdwell + \ station.tslew[k_scan - 1] + \ station.tslew[m_scan - 1] + \ station.tsettle / secpday if t_gap[station_index] < tot_time2: sr_ok2[p_src - 1] = False m_settle[group_index - 1] = \ max(m_settle[group_index - 1], station.tsettle) slew_max[p_src - 1] = 0 if sr_ok[p_src - 1]: for station in stations: if station.stascn[k_scan - 1]: slew_max[p_src - 1] = max( slew_max[p_src - 1], station.tslew[m_scan - 1]) if s.schcon.pkwatch and watch_it: if tab_head: s.wlog( 0, " Num Source Slew times (sec) " "Elevations (deg) Scans OK Min T") tab_head = False s.wlog( 0, "{:>6} {:<12}" "{:>6.0f} to {:<6.0f} " "{:>6.0f} to {:<6.0f}" " {} {} {:>7.0f}".format( p_src, peak_group.pksrc[p_src - 1], min_slew, max_slew, min_el, max_el, bool2str(sr_ok[p_src - 1]), bool2str(sr_ok2[p_src - 1]), float(min_tot))) use_p_src = 0 slew_min = 1 for p_src in range(1, peak_group.npksrc + 1): if sr_ok[p_src - 1]: if (0 < slew_max[p_src - 1] < slew_min): slew_min = slew_max[p_src - 1] use_p_src = p_src if use_p_src != 0: p_src = use_p_src k_src = peak_group.pksrnum[p_src - 1] add2 = try_group2[group_index - 1] and sr_ok2[p_src - 1] j_scan = k_scan ok_scan = 0 stop_k = scans[m_scan - 1].startj - slew_min start_k = stop_k - peak_group.pkdwell if add2: n_added += 2 ok_scan = 2 stop2 = start_k - m_settle[group_index - 1] / secpday start2 = stop2 - peak_group.pkdwell s.srinsert(k_scan, k_src, peak_group.pksrc[p_src - 1], start2, stop2, last_scan_index, m_scan) scans[k_scan - 1].point = group_index j_scan = k_scan + 1 for station_index, station in enumerate(stations): if station.stascn[k_scan - 1]: last_pointing_scan[station_index] = j_scan else: j_scan = k_scan n_added += 1 ok_scan = 1 s.srinsert(j_scan, k_src, peak_group.pksrc[p_src - 1], start_k, stop_k, last_pointing_scan, m_scan) scans[j_scan - 1].point = group_index if s.schcon.pkwatch: s.wlog( 0, "ADDPEAK: Adding {} scan(s) on {} for " "pointing group {}".format( ok_scan, peak_group.pksrc[p_src - 1], group_index)) for station_index, station in enumerate(stations): if station.stascn[j_scan - 1]: last_target_scan[station_index] = j_scan else: if s.schcon.pkwatch: s.wlog( 0, "ADDPEAK: No pointing sources available " "for pointing group {}".format(group_index)) else: if s.schcon.pkwatch: s.wlog( 0, "ADDPEAK: No stations for group {} in this " "scan. ".format(group_index)) # end of if try_group[group_index] # end of loop of peak groups k_scan = scan_index + n_added if k_scan != m_scan: scndup(k_scan - 1, m_scan - 1, True, "ADDPEAK2") scans[k_scan - 1].origen = keep_origen n_good = s.scngeo(last_target_scan, k_scan) scans[k_scan - 1].point = -999 if n_added > 0: peak_opt = n_added else: peak_opt = 0 else: # peak_opt != 0 if peak_opt > 0: peak_opt -= 1 if peak_opt >= 1: insert_adjust = False return peak_opt, insert_adjust
def optcells(last_scan_index, k_scan, scan_index): global cell_time, last_j_scan, weight_station if s.schcon.debug: s.wlog(1, "Starting OPTCELLS") done = False keep = True adjust = True stations = StationCatalog().used(use_direct_access=True) scans = ScanCatalog().direct_access_entries if k_scan == 1: if s.schn1.nscans > max_input_scans: s.errlog(" OPTCELLS: Too many input scans for cell optimizer " "- max: {}".format(max_input_scans)) if s.schcon.opdur <= 0: s.errlog(" OPTCELLS: For OPTMODE=CELLS, OPDUR must be given.") adjust = False scans[scan_index - 1].startj = scans[0].startj approx_time = scans[scan_index - 1].startj last_j_scan = 0 cell_time.fill(scans[0].startj - 0.5 / 24) baseline = np.zeros(dtype=float, shape=(len(stations), len(stations))) for (i, station1), (j, station2) in itertools.combinations( enumerate(stations), 2): baseline[i, j] = math.sqrt((station1.xpos - station2.xpos)**2 + (station1.ypos - station2.ypos)**2 + (station1.zpos - station2.zpos)**2) baseline += baseline.T mean_base = np.sum(baseline) / (len(stations) * (len(stations) - 1)) weight_station = np.square( np.sum(baseline, axis=1) / ((len(stations) - 1) * mean_base)) else: approx_time = scans[scan_index - 2].stopj got_station = np.zeros(dtype=int, shape=(s.schn1.nscans, )) ok_station = np.full(fill_value=False, dtype=bool, shape=(s.schn1.nscans, len(stations))) el_cell_index = np.empty(dtype=int, shape=(s.schn1.nscans, len(stations))) az_cell_index = np.empty(dtype=int, shape=(s.schn1.nscans, len(stations))) time_source = np.empty(dtype=float, shape=(s.schn1.nscans, )) points = np.zeros(dtype=float, shape=(s.schn1.nscans, )) for j_scan, scan in enumerate(scans[:s.schn1.nscans]): if j_scan + 1 != last_j_scan: for i, station in enumerate(stations): if station.stascn[j_scan]: last_time, station.tonsrc[j_scan] = s.stageo( j_scan + 1, i + 1, approx_time, last_scan_index[i], "OPTCELLS") if (f2str(station.up1[j_scan]) == "") and \ (f2str(station.up2[j_scan]) == "") and \ (station.el1[j_scan] > scan.opminel) and \ (station.el2[j_scan] > scan.opminel): ok_station[j_scan, i] = True got_station[j_scan] += 1 az_test = (station.az1[j_scan] + az_coff) % 360 if station.el1[j_scan] < el_cell[0]: el_cell_index[j_scan, i] = 1 elif station.el1[j_scan] < el_cell[1]: el_cell_index[j_scan, i] = 2 else: el_cell_index[j_scan, i] = 3 if el_cell_index[j_scan, i] == 3: az_cell_index[j_scan, i] = 1 else: if az_test < az_cell[0]: az_cell_index[j_scan, i] = 1 elif az_test < az_cell[1]: az_cell_index[j_scan, i] = 2 else: az_cell_index[j_scan, i] = 3 time_source[j_scan] = 1e10 all_0 = True for i, station in enumerate(stations): if ok_station[j_scan, i] and (last_scan_index[i] != 0): all_0 = False time_source[j_scan] = min(time_source[j_scan], station.tonsrc[j_scan]) if s.schcon.opnosub and (scan_index > s.schn1.scan1): time_source[j_scan] = max(time_source[j_scan], scans[scan_index - 2].stopj) if all_0: time_source[j_scan] = scans[0].startj if got_station[j_scan] >= scan.opmian: for i, station in enumerate(stations): if ok_station[j_scan, i]: eci = el_cell_index[j_scan, i] aci = az_cell_index[j_scan, i] weight_multiplier = 1 if eci == 1: for iaz in range(1, 4): if iaz != aci: pt_add = 1440 * \ (time_source[j_scan] - cell_time[eci - 1, iaz - 1, i]) weight_multiplier += pt_add ** 2 / \ (s.schcon.optlowt ** 2 + pt_add ** 2) lc_time = cell_time[eci - 1, aci - 1, i] pt_add = 1440 * (time_source[j_scan] - lc_time) points[j_scan] += weight_station[i] * pt_add * \ weight_multiplier max_points = np.max(points) time1 = 1e10 for j_scan, scan in enumerate(scans[:s.schn1.nscans]): if got_station[j_scan] >= scan.opmian: time1 = min(time1, time_source[j_scan]) for j_scan, scan in enumerate(scans[:s.schn1.nscans]): if got_station[j_scan] >= scan.opmian: sl_adj = 1440 * (time_source[j_scan] - time1) weight_multiplier = s.schcon.optslew**2 / (sl_adj**2 + s.schcon.optslew**2) points *= weight_multiplier look_back = 6 station_skip = np.zeros(dtype=int, shape=(len(stations), )) if scan_index > s.schn1.scan1 + 2: i_skip1 = max(scan_index - look_back, s.schn1.scan1) for l, l_scan in enumerate(scans[i_skip1 - 1:scan_index - 1]): for i, station in enumerate(stations): if not (station.stascn[l] and (station.el1[l] > l_scan.opminel)): station_skip[i] += 1 for j, scan in enumerate(scans[:s.schn1.nscans]): max_skip = 0 for i, station in enumerate(stations): if not (station.stascn[j_scan] and (station.el1[j_scan] > scan.opminel)): max_skip = max(max_skip, station_skip[i]) if max_skip > look_back // 3: points[j_scan] *= 0.2 max_scan = np.argmax(points) max_apt = points[max_scan] if max_apt > -1e10: j_scan = max_scan + 1 else: s.errlog("OPTCELLS: Something weird went wrong with POINTS.") scndup(scan_index - 1, j_scan - 1, False, "OPTCELLS") scan = scans[scan_index - 1] scan.startj = time_source[j_scan - 1] scan.stopj = scan.startj + scan.dur last_j_scan = j_scan year, day, time_rad = s.timej(scan.startj) time_text = f2str(s.tformwrp(time_rad, "T", 0, 2, 2, "::@")) s.wlog( 0, " Source, time, maxpts, maxapt: {:<12} {:>4d} {} " "{:>9.3f} {:>9.3f}".format(scan.scnsrc, day, time_text, max_points, max_apt)) for i, station in enumerate(stations): if ok_station[j_scan - 1, i]: cell_time[el_cell_index[j_scan - 1, i] - 1, az_cell_index[j_scan - 1, i] - 1, i] = scan.startj station.stascn[scan_index - 1] = True else: station.stascn[scan_index - 1] = False return adjust, keep, done
def opthas(last_scan_index, k_scan, scan_index): global n_out, scan_used, dur_total, ref_station_index, \ ha_min, ha_max, ha_begin, ha_end, t_ha_min, t_ha_max, t_use, t_avail, \ source_used, source_look, \ skip_time, skip_inc, n_skip, sd_total, \ op_ha_t, op_ha_wid_t scans = scan_catalog.direct_access_entries stations = station_catalog.used(use_direct_access=True) if k_scan == 1: # initialize for multiple calls to this function n_out = 0 skip_time = 0 n_skip = 0 skip_inc = 5 * 60 / secpday if s.schn1.nscans > max_ins: s.errlog( "OPHAS: Too many requested scans for OPTMODE=HAS. Max: {} " "Requested: {}".format(max_ins, s.schn1.nscans)) if s.schcon.opdur <= 0: s.errlog("OPHAS: Please specify OPDUR for OPTMODE=HAS") min_duration = min(scan.dur for scan in scans[:s.schn1.nscans]) if (s.schcon.opdur * sidereal - min_duration) > 1: s.errlog("OPHAS: OPTMODE=HAS not meant for observations over " "24 hours sidereal + min scan dur.") ht_stop = scans[0].startj + s.schcon.opdur _, ref_station_index, _ = s.stano(f2str(s.schsco.ophasta)) source_catalog = SourceCatalog() source_used = np.zeros(shape=(len(source_catalog.entries), ), dtype=int) source_look = np.zeros(shape=(s.schn1.nscans, ), dtype=int) dur_total = 0 sd_total = 0 for i, scan in enumerate(scans[:s.schn1.nscans]): source_index = scan.srcnum source_used[source_index - 1] += 1 source_look[i] = source_used[source_index - 1] scan_used[i] = 0 dur_total += scan.dur if dur_total > s.schcon.opdur: s.wlog( 1, "OPTHAS: ** The total time in requested scans of " "{} hours".format(dur_total * 24)) s.wlog( 1, " exceeds the experiment duration (OPDUR) of " "{} hours.".format(s.schcon.opdur * 24)) s.wlog(1, " Not all scans can be scheduled.") ref_station = stations[ref_station_index - 1] for j_scan, scan in enumerate(scans[:s.schn1.nscans]): ha_min[j_scan], ha_max[j_scan], t_ha_min[j_scan], t_ha_max[j_scan] \ = s.halim(j_scan + 1, ref_station_index) ref_station.ha1[j_scan], ref_station.el1[j_scan], \ ref_station.az1[j_scan], ref_station.lst1[j_scan], \ ref_station.pa1[j_scan] = s.schgeo( j_scan + 1, ref_station_index, scans[0].startj) ref_station.ha2[j_scan], ref_station.el2[j_scan], \ ref_station.az2[j_scan], ref_station.lst2[j_scan], \ ref_station.pa2[j_scan] = s.schgeo( j_scan + 1, ref_station_index, ht_stop - scan.dur) ha_begin[j_scan] = ref_station.ha1[j_scan] ha_end[j_scan] = ref_station.ha2[j_scan] t_avail[j_scan], t_use[j_scan] = s.haavai( t_ha_min[j_scan], t_ha_max[j_scan], scans[0].startj, ht_stop - scan.dur, source_used[scan.srcnum - 1], source_look[j_scan]) if t_avail[j_scan] == -1: s.wlog(1, " ") s.wlog( 1, " ****** {} is never above OPMINEL and the horizon at " "OPMINANT stations at once.".format(scan.scnsrc)) s.errlog("Leave out the source or change OPMINANT or OPMINEL") if scan.opha == 0: op_ha_t[j_scan] = t_use[j_scan] else: op_ha_t[j_scan] = (scan.opha - ha_begin[j_scan]) \ / sidereal + scans[0].startj if op_ha_t[j_scan] < scans[0].startj: op_ha_t[j_scan] += 24 / sidereal if op_ha_t[j_scan] > scans[0].startj + s.schcon.opdur: s.wlog( 1, "OPHAS: Requested hour angle outside range: " "scan, source, OPHA: {} {} {}".format( j_scan + 1, scan.scnsrc, scan.opha)) if scan.ophawid == 0: op_ha_wid_t[j_scan] = 0.7 * t_avail[j_scan] \ / source_used[scan.srcnum - 1] else: op_ha_wid_t[j_scan] = scan.ophawid / secpday else: ref_station = stations[ref_station_index - 1] if n_out > s.schn1.nscans: done = True else: done = False found_scan = False while not found_scan: if k_scan == 1: approx_time = scans[0].startj + skip_time adjust = False elif skip_time != 0: approx_time = scans[scan_index - 2].stopj + skip_time adjust = False if approx_time > scans[0].startj + s.schcon.opdur: done = True break else: approx_time = scans[scan_index - 2].stopj adjust = True weight_max = 0 weight_max_scan = -1 if s.schcon.opprtlev >= 3: s.wlog( 0, " Scan Source New scan time " "Opt scan time TIMEWT SLEWWT RISEWT SETWT SCNWT " " dT WID SlewSec") for j_scan, scan in enumerate(scans[:s.schn1.nscans]): if scan_used[j_scan] == 0: scan_weight[j_scan] = 0 ref_station.ha1[j_scan], ref_station.el1[j_scan], \ ref_station.az1[j_scan], ref_station.lst1[j_scan], \ ref_station.pa1[j_scan] = s.schgeo( j_scan + 1, ref_station_index, approx_time) if (ref_station.ha1[j_scan] >= ha_min[j_scan]) and \ (ref_station.ha1[j_scan] <= ha_max[j_scan]): at_source = 0 for i, station in enumerate(stations): if station.stascn[j_scan]: _, station.tonsrc[j_scan] = s.stageo( j_scan + 1, i + 1, approx_time, last_scan_index[i], "OPTHAS") if (k_scan > 1) and \ (f2str(station.up1[j_scan]) == ""): at_source = max(at_source, station.tonsrc[j_scan]) if k_scan > 1: op_slew = (at_source - scans[scan_index - 2].stopj) \ * secpday else: op_slew = 0 source_separation = 1 if k_scan > 1: for last_scan in scans[s.schn1.scan1 - 1:s.schn1.scanl]: if scan.scnsrc == last_scan.scnsrc: time_space = approx_time - last_scan.stopj source_separation = min( source_separation, time_space) if (source_separation < (scan.opminsep * op_ha_wid_t[j_scan])) or \ (abs(approx_time - op_ha_t[j_scan]) > scan.ophmaxdt / secpday): scan_weight[j_scan] = 0 else: time_weight = scan.ophawt * \ (0.5 + (1 / math.pi) * math.atan( 1.5 * (approx_time - op_ha_t[j_scan]) / op_ha_wid_t[j_scan])) slew_weight = 0 if (scan.scnsrc != scans[scan_index - 2].scnsrc) \ and (scan.opslewti > 0): slew_weight = max( 0, scan.opslewwt * (1 - op_slew / scan.opslewti)) rise_weight = 0 set_weight = 0 if scan.ophlimti > 0: rise_weight = max( 0, scan.ophlimwt * (1 - abs(ref_station.ha1[j_scan] - ha_min[j_scan]) * 3600 / scan.ophlimti)) set_weight = max( 0, scan.ophlimwt * (1 - abs(ref_station.ha1[j_scan] - ha_max[j_scan]) * 3600 / scan.ophlimti)) scan_weight[j_scan] = time_weight + slew_weight \ + rise_weight + set_weight if scan_weight[j_scan] > weight_max: weight_max = scan_weight[j_scan] weight_max_scan = j_scan if s.schcon.opprtlev >= 3: year, day1, time_rad = s.timej(approx_time) start_time_text = f2str( s.tformwrp(time_rad, "T", 0, 2, 2, "::@")) year, day2, time_rad = s.timej(op_ha_t[j_scan]) opt_time_text = f2str( s.tformwrp(time_rad, "T", 0, 2, 2, "::@")) s.wlog( 0, " SCAN WEIGHT {:>5d} {:<12} {:>4d} {} " "{:>4d} {} {:>7.2f} {:>7.2f} {:>7.2f} " "{:>7.2f} {:>7.2f} {:>7.2f} {:>7.2f} " "{:>7.2f}".format( j_scan + 1, scan.scnsrc, day1, start_time_text, day2, opt_time_text, time_weight, slew_weight, rise_weight, set_weight, scan_weight[j_scan], (approx_time - op_ha_t[j_scan]) * 24, op_ha_wid_t[j_scan] * 24, op_slew)) if weight_max_scan >= 0: n_out += 1 scndup(scan_index - 1, weight_max_scan, False, "OPTHAS") new_scan = scans[scan_index - 1] new_scan.startj = approx_time new_scan.stopj = new_scan.startj + new_scan.dur scan_used[weight_max_scan] = scan_index skip_time = 0 sd_total += new_scan.dur if s.schcon.opprtlev >= 2: year, day, time_rad = s.timej(approx_time) time_text = f2str(s.tformwrp(time_rad, "T", 0, 2, 2, "::@")) s.wlog( 0, "USE SCAN {:>5d} {} {:>5d} {} HA={:>10.2f} " "Weight: {:10.3f}".format( weight_max_scan + 1, scans[weight_max_scan].scnsrc, day, time_text, ref_station.ha1[weight_max_scan], weight_max)) found_scan = True else: skip_time += skip_inc n_skip += 1 if s.schcon.opprtlev >= 1: year, day, time_rad = s.timej(approx_time) time_text = f2str(s.tformwrp(time_rad, "T", 0, 2, 2, "::@")) s.wlog( 0, "OPTHAS: Skipping {:>6.2f} min at {} {:>7.2f} " "min after scan {:>5d} because no scans are " "available.".format(skip_inc * secpday / 60, time_text, skip_time * secpday / 60, scan_index)) if found_scan and (s.schcon.opdur > 0) and \ (new_scan.stopj > scans[0].startj + s.schcon.opdur): s.wlog( 1, "OPTHAS: Schedule stopped because requested total " "duration reached") done = True if done: s.wlog(0, " ") s.wlog(0, "OPTHAS: HAS mode schedule made.") s.wlog(0, " ") if s.schcon.opprtlev <= 0: s.wlog(0, " OPPRTLEV={}: Minimum information printed.".\ format(s.schcon.opprtlev)) elif s.schcon.opprtlev == 1: s.wlog( 0, " OPPRTLEV=1: Include summary of fate of each " "input scan.") elif s.schcon.opprtlev == 2: s.wlog( 0, " OPPRTLEV=2: Minimum feedback as scans chosen " "plus fate of input scans.") elif s.schcon.opprtlev >= 3: s.wlog( 0, " OPPRTLEV={}: Details of each scan choice plus " "summaries.".format(s.schcon.opprtlev)) s.wlog(0, " Requested scans: {}".format(s.schn1.nscans)) s.wlog(0, " Scheduled scans: {}".format(n_out)) s.wlog( 0, " Sum of requested durations: {:>7.3f} hr.".format( dur_total * 24)) s.wlog( 0, " Sum of scheduled durations: {:>7.3f} hr.".format( sd_total * 24)) year, day, time_rad = s.timej(scans[s.schn1.scan1 - 1].startj) time_text = f2str(s.tformwrp(time_rad, "T", 0, 2, 2, "::@")) s.wlog(0, " Start day and time: {:>5d} {}".format(day, time_text)) year, day, time_rad = s.timej(scans[s.schn1.scanl - 1].stopj) time_text = f2str(s.tformwrp(time_rad, "T", 0, 2, 2, "::@")) s.wlog( 0, " Stop day and time and total duration (hr): {:>5d} {}" " {:>12.3f}".format(day, time_text, (scans[s.schn1.scanl - 1].stopj - scans[s.schn1.scan1 - 1].startj) * 24)) s.wlog( 0, " Requested duration (hours) {:>8.2f}".format( s.schcon.opdur * 24)) s.wlog( 0, " Maximum allowed deviation from optimum time " "(hr; scan 1) {:>8.3f}".format(scans[0].ophmaxdt / 3600)) s.wlog( 0, " Number of {:>7.3f} minutes skips because of no scan " "available: {}".format(skip_inc * secpday / 60, n_skip)) s.wlog( 0, " Total time in skips: {:>8.3f} minutes. " "(Some may be after last scan)".format(skip_inc * n_skip * secpday / 60)) if s.schcon.opprtlev >= 1: s.wlog(0, " ") s.wlog(0, "OPTHAS: Input scan information. Columns are:") s.wlog(0, " Output scan number and time ") s.wlog( 0, " Reference station hour angle. " "for scheduled scan.") s.wlog( 0, " Allowed reference station hour angle range " "(for scan start).") s.wlog( 0, " Reference station hour angles for beginning " "and end of observations.") s.wlog(0, " Total hours this source is available.") s.wlog( 0, " The reference station is: {}".format( ref_station.station)) s.wlog( 0, " Input Source Output Time HA " "Time HA HA HA HA Available " "Rise Set") s.wlog( 0, " Scan Scan Day hms " "Scan Opt Min Max Start End Hours") for j, scan in enumerate(scans[:s.schn1.nscans]): if scan_used[j] != 0: year, day1, time_rad = s.timej(scans[scan_used[j] - 1].startj) start_time_text = f2str( s.tformwrp(time_rad, "T", 0, 2, 2, "::@")) ha_p = ref_station.ha1[scan_used[j] - 1] else: day1 = 0 start_time_text = " " ha_p = 0 year, day2, time_rad = s.timej(op_ha_t[j]) opt_time_text = f2str(s.tformwrp(time_rad, "T", 0, 2, 2, "::@")) year, day_rise, time_rad = s.timej(t_ha_min[j]) rise_time_text = f2str( s.tformwrp(time_rad, "T", 0, 2, 2, "::@")) year, day_set, time_rad = s.timej(t_ha_max[j]) set_time_text = f2str(s.tformwrp(time_rad, "T", 0, 2, 2, "::@")) s.wlog( 0, "{:>5d} {:<12} {:>5d} {:>5d} {:<8} {:>8.3f} {:>4d}" " {} {:>7.3f} {:>7.3f} {:>7.3f} {:>7.3f} {:>7.3f} {:>4d}" " {} {:>4d} {}".format( j + 1, scan.scnsrc, scan_used[j], day1, start_time_text, ha_p, day2, opt_time_text, ha_min[j], ha_max[j], ha_begin[j], ha_end[j], t_avail[j] * 24, day_rise, rise_time_text, day_set, set_time_text)) s.wlog( 1, "OPTHAS: There were {} requested scans and " "{} Scheduled scans.".format(s.schn1.nscans, n_out)) s.wlog(1, "OPTHAS: See the sched.runlog for details.") return adjust, True, done
def schopt(): if s.schcon.debug: s.wlog(0, "SCHOPT: Starting.") scan_catalog = ScanCatalog() scans = scan_catalog.direct_access_entries station_catalog = StationCatalog() stations = station_catalog.used(use_direct_access=True) source_catalog = SourceCatalog() sources = source_catalog.read() pc_catalog = PhaseCenterCatalog() phase_centers = pc_catalog.read() setups = SetupCatalog().read() peak_catalog = PeakCatalog() peak_groups = peak_catalog.read() # content of setup file catalog used in geochk (->addgeo->geomake->geochk) # call here once SetupFileCatalog().read() for scan in scans: scan.origen = 1 optmode = f2str(s.schsco.optmode) if (optmode not in {"NONE", "SCANS"}) or \ s.schcon.autopeak or s.schsou.anygeo: # get the int value of nscans, # else (increment) operations affect nscans directly, # since it's a dimensionless np.array scan_index = int(s.schn1.nscans) s.schn1.scan1 = scan_index + 1 else: scan_index = 0 s.schn1.scan1 = 1 s.wlog( 0, "SCHOPT: First output scan will be number {}".format(s.schn1.scan1)) done = False peak_opt = 0 geo_opt = 0 k_scan = 0 last_scan_index = np.zeros(shape=(station_catalog.maxsta, ), dtype=int) last_s_scan_index = np.zeros(shape=(station_catalog.maxsta, ), dtype=int) while not done: scan_index += 1 if scan_index > scan_catalog.maxscan: s.errlog("SCHOPT: Trying to generate too many scans. Max: {}".\ format(scan_catalog.maxscan)) scan = scans[scan_index - 1] if (peak_opt != 0) or (geo_opt != 0): keep = True else: k_scan += 1 assert ((k_scan == scan_index) or (scan_index >= s.schn1.nscans)) if optmode == "NONE": adjust, keep, done = optnone(k_scan, scan_index) elif optmode == "SCANS": adjust, keep, done = optskd(last_scan_index, k_scan, scan_index) elif optmode == "CELLS": adjust, keep, done = optcells(last_scan_index, k_scan, scan_index) scan.origen = 2 elif optmode == "CSUB": s.errlog("SCHOPT: OPTMODE CSUB is not supported in pySCHED") elif optmode == "UPTIME": last_scan_index, adjust, keep, done = optupt( last_scan_index, k_scan, scan_index) scan.origen = 2 elif optmode == "HAS": adjust, keep, done = opthas(last_scan_index, k_scan, scan_index) scan.origen = 2 elif optmode == "HIGHEL": k_scan, adjust, keep, done = opthiel(last_scan_index, k_scan, scan_index) scan.origen = 2 else: s.errlog("SCHOPT: Invalid OPTMODE: {}".format(optmode)) if keep and (not done): s.opttim(last_scan_index, last_s_scan_index, scan_index, adjust, False, False) if (s.schcon.opdur != 0) and \ (scan.stopj > scans[s.schn1.scan1 - 1].startj + s.schcon.opdur) and \ (optmode != "HAS"): done = True n_good = s.scngeo(last_scan_index, scan_index) insert_adjust = adjust if keep and (not done): if (peak_opt == 0) and ((scan.geolen > 0) or (geo_opt >= 1)): insert_adjust = False geo_opt, keep = addgeo(last_scan_index, scan_index, geo_opt, scans, stations) peak_opt, insert_adjust = addpeak(last_scan_index, scans, stations, setups, peak_groups, peak_opt, insert_adjust, scan_index) peak_catalog.write() keep = s.makeptg(last_scan_index, scan_index, keep) if keep and (not done): s.opttim(last_scan_index, last_s_scan_index, scan_index, insert_adjust, False, True) n_good = s.scngeo(last_scan_index, scan_index) n_good = s.autodown(last_scan_index, scan_index) keep = keep and ((n_good >= scan.opmian) or (optmode in {"CSUB", "HAS"}) or (scan.point >= 0)) if not keep: for station in stations: station.stascn[scan_index - 1] = False else: s.settps(scan_index, last_scan_index) for station_index, station in enumerate(stations, 1): if station.stascn[scan_index - 1] and s.schn1.vlbitp and \ (not s.schcon.noset) and station.usedisk: s.diskpos(scan_index, station_index, last_scan_index) if (optmode not in {"NONE", "UPTIME"}) or s.schsou.anygeo: s.optsch(scan_index) source = sources[scan.srcnum - 1] source.sused = True if not scan.norec: source.usedrec = True if scan.idopsrc != 0: sources[scan.idopsrc - 1].sused = True if scan.ivlaphs != 0: sources[scan.ivlaphs - 1].sused = True if scan.icent != 0: source.usedcent = True for source_index in phase_centers[scan.icent - 1].ctrsrci: sources[source_index - 1].usedphs = True for station_index, station in enumerate(stations): if station.stascn[scan_index - 1]: last_scan_index[station_index] = scan_index if scan.origen < 4: last_s_scan_index[station_index] = scan_index s.schn1.scanl = scan_index if s.schcon.debug: s.wlog(0, "SCHOPT: 9.") if s.schn1.scanl == 0: s.wlog(1, "SCHOPT: Did not schedule any scans") s.errlog(" Abort") source_catalog.write() s.accsrc(False) gotall = s.srcflg() if not gotall: s.errlog("SCHOPT: Not all sources found; programming problem.") s.getpairs() year, day1, start = s.timej(scans[s.schn1.scan1 - 1].startj) year, day2, stop = s.timej(scans[s.schn1.scanl - 1].stopj) time1 = f2str(s.tformwrp(start, "T", 0, 2, 2, "::@")) time2 = f2str(s.tformwrp(stop, "T", 0, 2, 2, "::@")) s.wlog( 0, "SCHOPT: There will be {number} output scans ({first} - {last}) " "from {day1}/{time1} to {day2}/{time2}".format(number=s.schn1.scanl - s.schn1.scan1 + 1, first=s.schn1.scan1, last=s.schn1.scanl, day1=day1, day2=day2, time1=time1, time2=time2)) s.schtim() s.sch24() if s.schcon.debug: s.wlog(0, "SCHOPT: Done.")