def calc_weight(errdata): sp = np.fft.fft(errdata)[1:len(errdata) // 2] if sp.sum() == 0: # there is no variation in the signal log.warn('no variation in the signal. fft cannot continue') return 1 # get the phase in radians # -np.pi < phase <= +np.pi phase = np.angle(sp) # radians # find the amplitude integral of neighboring samples. # search <360 degrees to left of most recent sample's phase # p_k = phase - degrees_between_samples * k # kth phase amplitude_integrals = np.abs(np.sin(phase)) # iteratively updated # samples per cycle kth = len(errdata) / np.arange(1, len(errdata) // 2) num_degrees_between_samples = 2 * np.pi / kth p_k = phase.copy() while (kth > 0).any(): # find amplitude of a sign wave at specific phase p_k -= num_degrees_between_samples amplitude_integrals += np.abs(np.sin(p_k)) kth -= 1 idxs = kth > 0 not_idxs = ~idxs kth = kth[idxs] p_k[not_idxs] = 0 num_degrees_between_samples[not_idxs] = 0 # get the amplitude of each frequency in the fft spectrum amplitude = np.abs(sp) return ( # np.sin(phase) (np.sin(phase) / amplitude_integrals) * (amplitude / amplitude.sum())).sum()
def calc_weight(errdata): sp = np.fft.fft(errdata)[1 : len(errdata) // 2] if sp.sum() == 0: # there is no variation in the signal log.warn("no variation in the signal. fft cannot continue") return 1 # get the phase in radians # -np.pi < phase <= +np.pi phase = np.angle(sp) # radians # find the amplitude integral of neighboring samples. # search <360 degrees to left of most recent sample's phase # p_k = phase - degrees_between_samples * k # kth phase amplitude_integrals = np.abs(np.sin(phase)) # iteratively updated # samples per cycle kth = len(errdata) / np.arange(1, len(errdata) // 2) num_degrees_between_samples = 2 * np.pi / kth p_k = phase.copy() while (kth > 0).any(): # find amplitude of a sign wave at specific phase p_k -= num_degrees_between_samples amplitude_integrals += np.abs(np.sin(p_k)) kth -= 1 idxs = kth > 0 not_idxs = ~idxs kth = kth[idxs] p_k[not_idxs] = 0 num_degrees_between_samples[not_idxs] = 0 # get the amplitude of each frequency in the fft spectrum amplitude = np.abs(sp) return ( # np.sin(phase) (np.sin(phase) / amplitude_integrals) * (amplitude / amplitude.sum()) ).sum()
def main(ns): validate_ns_or_sysexit(ns) configure_logging(True) if ns.sendstats: if ns.sendstats == 'webui': add_zmq_log_handler('ipc:///tmp/relaylog') start_webui() else: add_zmq_log_handler(ns.sendstats) log.info("Starting relay!", extra={k: str(v) for k, v in ns.__dict__.items()}) metric = ns.metric() target = ns.target() errhist = window(ns.lookback) ramp_index = 0 while True: SP = next(target) # set point PV = next(metric) # process variable err = (SP - PV) log.debug('got metric value', extra=dict(PV=PV, SP=SP)) if ramp_index < ns.ramp: if ramp_index == 0: plan = create_ramp_plan(err, ns.ramp) ramp_index += 1 MV = next(plan) errdata = errhist.send(0) else: errdata = errhist.send(err) weight = calc_weight(errdata) MV = int(round(err - weight * sum(errdata) / len(errdata))) log.info( 'data', extra=dict(data=[err, weight, sum(errdata) / len(errdata)])) if MV > 0: if ns.warmer: log.debug('adding heat', extra=dict(MV=MV, err=err)) threading.Thread(target=ns.warmer, args=(MV, )).start() else: log.warn('too cold') elif MV < 0: if ns.cooler: log.debug('removing heat', extra=dict(MV=MV, err=err)) threading.Thread(target=ns.cooler, args=(MV, )).start() else: log.warn('too hot') else: log.debug('stabilized PV at setpoint', extra=dict(MV=MV, PV=PV, SP=SP)) time.sleep(ns.delay) evaluate_stop_condition(list(errdata), ns.stop_condition)
def main(ns): validate_ns_or_sysexit(ns) configure_logging(True) if ns.sendstats: if ns.sendstats == "webui": add_zmq_log_handler("ipc:///tmp/relaylog") start_webui() else: add_zmq_log_handler(ns.sendstats) log.info("Starting relay!", extra={k: str(v) for k, v in ns.__dict__.items()}) metric = ns.metric() target = ns.target() errhist = window(ns.lookback) ramp_index = 0 while True: SP = next(target) # set point PV = next(metric) # process variable err = SP - PV log.debug("got metric value", extra=dict(PV=PV, SP=SP)) if ramp_index < ns.ramp: if ramp_index == 0: plan = create_ramp_plan(err, ns.ramp) ramp_index += 1 MV = next(plan) errdata = errhist.send(0) else: errdata = errhist.send(err) weight = calc_weight(errdata) MV = int(round(err - weight * sum(errdata) / len(errdata))) log.info("data", extra=dict(data=[err, weight, sum(errdata) / len(errdata)])) if MV > 0: if ns.warmer: log.debug("adding heat", extra=dict(MV=MV, err=err)) threading.Thread(target=ns.warmer, args=(MV,)).start() else: log.warn("too cold") elif MV < 0: if ns.cooler: log.debug("removing heat", extra=dict(MV=MV, err=err)) threading.Thread(target=ns.cooler, args=(MV,)).start() else: log.warn("too hot") else: log.debug("stabilized PV at setpoint", extra=dict(MV=MV, PV=PV, SP=SP)) time.sleep(ns.delay) evaluate_stop_condition(list(errdata), ns.stop_condition)