def setup(self, win): self.plots = [] self.curves = [] for i in range(self.num_depths): title = "{:.0f} cm".format(100 * self.depths[i]) plot = win.addPlot(row=0, col=i, title=title) plot.showGrid(x=True, y=True) plot.setYRange(-2**15, 2**15) plot.hideAxis("left") plot.hideAxis("bottom") plot.plot(np.arange(self.num_subsweeps), np.zeros(self.num_subsweeps)) curve = plot.plot(pen=example_utils.pg_pen_cycler()) self.plots.append(plot) self.curves.append(curve) self.ft_plot = win.addPlot(row=1, col=0, colspan=self.num_depths) self.ft_im = pg.ImageItem(autoDownsample=True) self.ft_im.setLookupTable(example_utils.pg_mpl_cmap("viridis")) self.ft_plot.addItem(self.ft_im) self.ft_plot.setLabel("bottom", "Depth (cm)") self.ft_plot.getAxis("bottom").setTickSpacing(6 * self.stepsize, 6) self.smooth_max = example_utils.SmoothMax( self.smooth_max_f, tau_grow=0, tau_decay=0.5, hysteresis=0.1, ) self.setup_is_done = True self.update_processing_config()
def setup(self, win): win.setWindowTitle("Acconeer envelope mode example") self.envelope_plot_window = win.addPlot(row=0, col=0, title="Envelope", colspan=self.num_sensors) self.envelope_plot_window.showGrid(x=True, y=True) self.envelope_plot_window.addLegend(offset=(-10, 10)) self.envelope_plot_window.setYRange(0, 1) self.envelope_plot_window.setLabel("left", "Amplitude") self.envelope_plot_window.setLabel("bottom", "Distance (mm)") self.peak_text = pg.TextItem(text="", color=(1, 1, 1), anchor=(0, 1), fill="#f0f0f0") self.peak_text.setZValue(3) self.envelope_plot_window.addItem(self.peak_text) self.envelope_plots = [] self.peak_vlines = [] self.clutter_plots = [] self.hist_plot_images = [] self.hist_plots = [] self.hist_plot_peaks = [] lut = example_utils.pg_mpl_cmap("viridis") hist_pen = example_utils.pg_pen_cycler(1) for s in range(self.num_sensors): legend_text = "Sensor {}".format(self.sensor_config.sensor[s]) pen = example_utils.pg_pen_cycler(s+1) self.envelope_plots.append( self.envelope_plot_window.plot(range(10), np.zeros(10), pen=pen, name=legend_text) ) self.peak_vlines.append( pg.InfiniteLine(pos=0, angle=90, pen=pg.mkPen(width=2, style=QtCore.Qt.DotLine)) ) self.envelope_plot_window.addItem(self.peak_vlines[s]) hist_title = "Envelope history" if self.num_sensors == 1: pen = pg.mkPen(0.2, width=2, style=QtCore.Qt.DotLine) self.clutter_plots.append( self.envelope_plot_window.plot( range(10), np.zeros(10), pen=pen, name="Background") ) self.clutter_plots[0].setZValue(2) else: hist_title = "History {}".format(legend_text) self.hist_plot_images.append(win.addPlot(row=2, col=s, title=hist_title)) self.hist_plot_images[s].setLabel("left", "Distance (mm)") self.hist_plot_images[s].setLabel("bottom", "Time (s)") self.hist_plots.append(pg.ImageItem()) self.hist_plots[s].setAutoDownsample(True) self.hist_plots[s].setLookupTable(lut) self.hist_plot_images[s].addItem(self.hist_plots[s]) self.hist_plot_peaks.append( self.hist_plot_images[s].plot(range(10), np.zeros(10), pen=hist_pen))
def setup(self, win): win.setWindowTitle("Acconeer sparse example") self.data_plot = win.addPlot(title="Sparse data") self.data_plot.showGrid(x=True, y=True) self.data_plot.setLabel("bottom", "Depth (m)") self.data_plot.setLabel("left", "Amplitude") self.data_plot.setYRange(-2**15, 2**15) self.scatter = pg.ScatterPlotItem(size=10) self.data_plot.addItem(self.scatter) win.nextRow() cmap_cols = ["steelblue", "lightblue", "#f0f0f0", "moccasin", "darkorange"] cmap = LinearSegmentedColormap.from_list("mycmap", cmap_cols) cmap._init() lut = (cmap._lut * 255).view(np.ndarray) self.data_history_plot = win.addPlot(title="Data history") self.data_history_im = pg.ImageItem(autoDownsample=True) self.data_history_im.setLookupTable(lut) self.data_history_plot.addItem(self.data_history_im) self.data_history_plot.setLabel("bottom", "Time (s)") self.data_history_plot.setLabel("left", "Depth (m)") win.nextRow() self.movement_history_plot = win.addPlot(title="Movement history") self.movement_history_im = pg.ImageItem(autoDownsample=True) self.movement_history_im.setLookupTable(example_utils.pg_mpl_cmap("viridis")) self.movement_history_plot.addItem(self.movement_history_im) self.movement_history_plot.setLabel("bottom", "Time (s)") self.movement_history_plot.setLabel("left", "Depth (m)")
def setup(self, win): win.setWindowTitle("Acconeer sparse example") self.data_plots = [] self.scatters = [] self.data_history_ims = [] self.presence_history_ims = [] for i in range(len(self.sensor_config.sensor)): data_plot = win.addPlot(title="Sparse data", row=0, col=i) data_plot.showGrid(x=True, y=True) data_plot.setLabel("bottom", "Depth (m)") data_plot.setLabel("left", "Amplitude") data_plot.setYRange(-2**15, 2**15) scatter = pg.ScatterPlotItem(size=10) data_plot.addItem(scatter) cmap_cols = [ "steelblue", "lightblue", "#f0f0f0", "moccasin", "darkorange" ] cmap = LinearSegmentedColormap.from_list("mycmap", cmap_cols) cmap._init() lut = (cmap._lut * 255).view(np.ndarray) data_history_plot = win.addPlot(title="Data history", row=1, col=i) data_history_im = pg.ImageItem(autoDownsample=True) data_history_im.setLookupTable(lut) data_history_plot.addItem(data_history_im) data_history_plot.setLabel("bottom", "Time (s)") data_history_plot.setLabel("left", "Depth (m)") presence_history_plot = win.addPlot(title="Movement history", row=2, col=i) presence_history_im = pg.ImageItem(autoDownsample=True) presence_history_im.setLookupTable( example_utils.pg_mpl_cmap("viridis")) presence_history_plot.addItem(presence_history_im) presence_history_plot.setLabel("bottom", "Time (s)") presence_history_plot.setLabel("left", "Depth (m)") self.data_plots.append(data_plot) self.scatters.append(scatter) self.data_history_ims.append(data_history_im) self.presence_history_ims.append(presence_history_im) for im in [presence_history_im, data_history_im]: im.resetTransform() im.translate(-self.history_len_s, self.depths[0] - self.depth_res / 2) im.scale(self.time_res, self.depth_res)
def setup(self, win): win.setWindowTitle("Acconeer obstacle detection example") self.env_ax = win.addPlot(row=0, col=0, title="Envelope and max FFT") self.env_ax.setLabel("bottom", "Depth (cm)") self.env_ax.setXRange(*(self.config.range_interval * 100)) self.env_ax.showGrid(True, True) self.env_ax.addLegend() self.env_ax.setYRange(0, 0.1) self.env_ampl = self.env_ax.plot(pen=example_utils.pg_pen_cycler(0), name="Envelope") self.fft_max = self.env_ax.plot(pen=example_utils.pg_pen_cycler( 1, "--"), name="FFT max") self.peak_dist_text = pg.TextItem(color="k", anchor=(0, 1)) self.env_ax.addItem(self.peak_dist_text) self.peak_dist_text.setPos(self.config.range_start * 100, 0) self.peak_dist_text.setZValue(3) self.env_peak_vline = pg.InfiniteLine(pos=0, angle=90, pen=pg.mkPen( width=2, style=QtCore.Qt.DotLine)) self.env_ax.addItem(self.env_peak_vline) self.obstacle_ax = win.addPlot(row=1, col=0, title="Obstacle map") self.obstacle_im = pg.ImageItem() self.obstacle_ax.setLabel("bottom", "Velocity (cm/s)") self.obstacle_ax.setLabel("left", "Distance (cm)") self.obstacle_im.setLookupTable(example_utils.pg_mpl_cmap("viridis")) self.obstacle_ax.addItem(self.obstacle_im) self.obstacle_ax.setXRange(-self.max_velocity, self.max_velocity) self.obstacle_ax.setYRange(*self.config.range_interval * 100) self.obstacle_peak = pg.ScatterPlotItem(brush=pg.mkBrush("k"), size=15) self.obstacle_ax.addItem(self.obstacle_peak) self.peak_fft_text = pg.TextItem(color="w", anchor=(0, 1)) self.obstacle_ax.addItem(self.peak_fft_text) self.peak_fft_text.setPos(-self.max_velocity, self.config.range_start * 100) self.smooth_max = example_utils.SmoothMax(self.config.sweep_rate, tau_decay=1, tau_grow=0.2)
def update(self, data): feat_map = None if data["ml_frame_data"] is not None: frame_data = data["ml_frame_data"] feat_map = frame_data["current_frame"]["feature_map"] frame_size = frame_data["frame_info"]["frame_size"] frame_pad = frame_data["frame_info"]["frame_pad"] frame_complete = frame_data["current_frame"]["frame_complete"] model_dimension = data["ml_frame_data"]["model_dimension"] else: return sensors = [] if self.sensor_config is not None: sensors = self.sensor_config.sensor mode = data["sensor_config"].mode if self.first: self.first = False self.env_plot_max_y = 0 s_buff = frame_size + 2 * frame_pad self.feat_plot.resetTransform() if model_dimension > 1: self.feat_plot.translate(-frame_pad, 0) self.feat_plot_image.setXRange(-frame_pad, s_buff - frame_pad) self.border_left.setValue(0) self.border_right.setValue(frame_size) self.border_left.show() self.border_right.show() nr_sensors = len(sensors) self.hist_plot_max_y = np.zeros(nr_sensors) lut = example_utils.pg_mpl_cmap("viridis") if mode == "sparse": cmap_cols = [ "steelblue", "lightblue", "#f0f0f0", "moccasin", "darkorange" ] cmap = LinearSegmentedColormap.from_list("mycmap", cmap_cols) cmap._init() lut = (cmap._lut * 255).view(np.ndarray) for i in range(4): if (i + 1) in sensors: self.hist_plot_images[i].show() self.set_axis(data, self.hist_plot_images[i]) self.hist_plots[i].setLookupTable(lut) else: self.hist_plot_images[i].hide() for idx, sensor in enumerate(sensors): if mode == "sparse": data_history_adj = data["hist_env"][idx, :, :].T sign = np.sign(data_history_adj) data_history_adj = np.abs(data_history_adj) data_history_adj /= data_history_adj.max() data_history_adj = np.power(data_history_adj, 1 / 2.2) # gamma correction data_history_adj *= sign self.hist_plots[sensor - 1].updateImage(data_history_adj, levels=(-1.05, 1.05)) else: max_val = np.max(data["env_ampl"][idx]) ymax_level = min( 1.5 * np.max(np.max(data["hist_env"][idx, :, :])), self.hist_plot_max_y[idx]) if max_val > self.hist_plot_max_y[idx]: self.hist_plot_max_y[idx] = 1.2 * max_val self.hist_plots[sensor - 1].updateImage( data["hist_env"][idx, :, :].T, levels=(0, ymax_level)) if self.show_predictions and data.get("prediction") is not None: self.predictions_plot_window.show() predictions = data["prediction"]["label_predictions"] pred_num = data["prediction"]["number_labels"] pred_history = data["prediction_hist"] if len(self.prediction_plots) < pred_num: self.generate_predciction_plots(predictions, pred_num) if pred_history is not None: for idx in range(pred_num): self.prediction_plots[idx].setData(pred_history[idx, :]) detected = True if feat_map is None: detected = False if detected and not len(feat_map): detected = False if not detected: motion_score = frame_data.pop("motion_score", None) text = "Waiting..." if motion_score is not None: text = "Waiting.. (Motion score: {:.1f})".format(motion_score) self.detected_text.setText(text) return else: self.detected_text.setText("Collecting..") if not frame_complete: self.border_rolling.show() self.border_rolling.setValue( frame_data["current_frame"]["sweep_counter"] - frame_pad) else: self.border_rolling.hide() feauture_nr = frame_data["current_frame"]["frame_nr"] self.feature_nr_text.setText("Feature: {}".format(feauture_nr)) self.feat_plot_image.setYRange(0, feat_map.shape[0]) map_max = 1.2 * np.max(feat_map) ymax_level = max(map_max, self.env_plot_max_y) g = 1 / 2.2 feat_map = 254 / (ymax_level + 1.0e-9)**g * feat_map**g feat_map[feat_map > 254] = 254 self.feat_plot.updateImage(feat_map.T, levels=(0, 256)) if map_max > self.env_plot_max_y: self.env_plot_max_y = map_max
def setup(self, win): win.setWindowTitle("Feature plotting") self.feat_plot_image = win.addPlot(row=0, col=0) self.feat_plot = pg.ImageItem() self.feat_plot.setAutoDownsample(True) self.feat_plot_image.addItem(self.feat_plot) self.feat_plot_image.setLabel("left", "Features") self.feat_plot_image.setLabel("bottom", "Sweeps") lut = example_utils.pg_mpl_cmap("viridis") self.feat_plot.setLookupTable(lut) self.feat_plot_image.setXRange(0, 40) self.feat_plot_image.setYRange(0, 1) self.border_right = pg.InfiniteLine(pos=0, angle=90, pen=pg.mkPen( width=2, style=QtCore.Qt.DotLine)) self.border_left = pg.InfiniteLine(pos=0, angle=90, pen=pg.mkPen( width=2, style=QtCore.Qt.DotLine)) self.border_rolling = pg.InfiniteLine(pos=0, angle=90, pen=pg.mkPen(width=2)) self.detected_text = pg.TextItem(color="r", anchor=(0, 1)) self.feature_nr_text = pg.TextItem(color="r", anchor=(0, 2)) self.feat_plot_image.addItem(self.detected_text) self.feat_plot_image.addItem(self.feature_nr_text) self.feat_plot_image.addItem(self.border_left) self.feat_plot_image.addItem(self.border_right) self.feat_plot_image.addItem(self.border_rolling) self.border_left.hide() self.border_right.hide() self.border_rolling.hide() self.history_plot_window = win.addLayout(row=1, col=0) self.envelope_plots = [] self.peak_vlines = [] self.clutter_plots = [] self.hist_plot_images = [] self.hist_plots = [] self.hist_plot_peaks = [] lut = example_utils.pg_mpl_cmap("viridis") for s in range(4): legend_text = "Sensor {}".format(s + 1) hist_title = "History {}".format(legend_text) self.hist_plot_images.append( self.history_plot_window.addPlot(row=0, col=s, title=hist_title)) self.hist_plot_images[s].setLabel("left", "Distance (mm)") self.hist_plot_images[s].setLabel("bottom", "Time (s)") self.hist_plots.append(pg.ImageItem()) self.hist_plots[s].setAutoDownsample(True) self.hist_plots[s].setLookupTable(lut) self.hist_plot_images[s].addItem(self.hist_plots[s]) if self.show_predictions: self.predictions_plot_window = win.addPlot( row=2, col=0, title="Prediction results") self.predictions_plot_window.showGrid(x=True, y=True) self.predictions_plot_window.addLegend(offset=(-10, 10)) self.predictions_plot_window.setYRange(0, 1) self.predictions_plot_window.setLabel("left", "Probability") self.predictions_plot_window.setLabel("bottom", "Iteration") self.prediction_plots = []
def main(): args = example_utils.ExampleArgumentParser(num_sens=1).parse_args() example_utils.config_logging(args) if args.socket_addr: client = JSONClient(args.socket_addr) else: port = args.serial_port or example_utils.autodetect_serial_port() client = RegClient(port) config = configs.EnvelopeServiceConfig() config.sensor = args.sensors config.range_interval = [0.2, 0.6] config.sweep_rate = 60 config.gain = 0.65 info = client.setup_session(config) num_points = info["data_length"] xs = np.linspace(*config.range_interval, num_points) num_hist = 2 * config.sweep_rate hist_data = np.zeros([num_hist, num_points]) hist_max = np.zeros(num_hist) smooth_max = example_utils.SmoothMax(config.sweep_rate) app = QtGui.QApplication([]) pg.setConfigOption("background", "w") pg.setConfigOption("foreground", "k") pg.setConfigOptions(antialias=True) win = pg.GraphicsLayoutWidget() win.closeEvent = lambda _: interrupt_handler.force_signal_interrupt() win.setWindowTitle("Acconeer PyQtGraph example") env_plot = win.addPlot(title="Envelope") env_plot.showGrid(x=True, y=True) env_plot.setLabel("bottom", "Depth (m)") env_plot.setLabel("left", "Amplitude") env_curve = env_plot.plot(pen=pg.mkPen("k", width=2)) win.nextRow() hist_plot = win.addPlot() hist_plot.setLabel("bottom", "Time (s)") hist_plot.setLabel("left", "Depth (m)") hist_image_item = pg.ImageItem() hist_image_item.translate(-2, config.range_start) hist_image_item.scale(2 / num_hist, config.range_length / num_points) hist_plot.addItem(hist_image_item) # try to get a colormap from matplotlib try: hist_image_item.setLookupTable(example_utils.pg_mpl_cmap("viridis")) except ImportError: pass win.show() interrupt_handler = example_utils.ExampleInterruptHandler() print("Press Ctrl-C to end session") client.start_streaming() while not interrupt_handler.got_signal: info, sweep = client.get_next() hist_data = np.roll(hist_data, -1, axis=0) hist_data[-1] = sweep hist_max = np.roll(hist_max, -1) hist_max[-1] = np.max(sweep) y_max = smooth_max.update(np.amax(hist_max)) env_curve.setData(xs, sweep) env_plot.setYRange(0, y_max) hist_image_item.updateImage(hist_data, levels=(0, y_max)) app.processEvents() print("Disconnecting...") app.closeAllWindows() client.disconnect()
def setup(self, win): win.setWindowTitle("Acconeer obstacle detection example") row_idx = 0 self.env_ax = win.addPlot(row=row_idx, col=0, colspan=4, title="Envelope and max FFT") self.env_ax.setLabel("bottom", "Depth (cm)") self.env_ax.setXRange(*(self.sensor_config.range_interval * 100)) self.env_ax.showGrid(True, True) self.env_ax.addLegend() self.env_ax.setYRange(0, 0.1) self.env_ampl = self.env_ax.plot(pen=example_utils.pg_pen_cycler(0), name="Envelope") self.fft_max = self.env_ax.plot(pen=example_utils.pg_pen_cycler( 1, "--"), name="FFT max") self.peak_dist_text = pg.TextItem(color="k", anchor=(0, 1)) self.env_ax.addItem(self.peak_dist_text) self.peak_dist_text.setPos(self.sensor_config.range_start * 100, 0) self.peak_dist_text.setZValue(3) self.env_peak_vline = pg.InfiniteLine(pos=0, angle=90, pen=pg.mkPen( width=2, style=QtCore.Qt.DotLine)) self.env_ax.addItem(self.env_peak_vline) row_idx += 1 self.obstacle_ax = win.addPlot(row=row_idx, col=0, colspan=self.num_hist_plots, title="Obstacle map") self.obstacle_im = pg.ImageItem() self.obstacle_ax.setLabel("bottom", "Velocity (cm/s)") self.obstacle_ax.setLabel("left", "Distance (cm)") self.obstacle_im.setLookupTable(example_utils.pg_mpl_cmap("viridis")) self.obstacle_ax.addItem(self.obstacle_im) self.obstacle_ax.setXRange(-self.max_velocity, self.max_velocity) self.obstacle_ax.setYRange(*self.sensor_config.range_interval * 100) self.obstacle_ax.setXRange(-self.max_velocity, self.max_velocity) self.obstacle_ax.setYRange(*self.sensor_config.range_interval * 100) self.obstacle_peak = pg.ScatterPlotItem(brush=pg.mkBrush("k"), size=15) self.obstacle_ax.addItem(self.obstacle_peak) self.peak_fft_text = pg.TextItem(color="w", anchor=(0, 1)) self.obstacle_ax.addItem(self.peak_fft_text) self.peak_fft_text.setPos(-self.max_velocity, self.sensor_config.range_start * 100) self.peak_val_text = pg.TextItem(color="w", anchor=(0, 0)) self.obstacle_ax.addItem(self.peak_val_text) self.peak_val_text.setPos(-self.max_velocity, self.sensor_config.range_end * 100) row_idx += 1 if self.advanced_plots["background_map"]: self.obstacle_bg_ax = win.addPlot(row=row_idx, col=0, colspan=self.num_hist_plots, title="Obstacle background") self.obstacle_bg_im = pg.ImageItem() self.obstacle_bg_ax.setLabel("bottom", "Velocity (cm/s)") self.obstacle_bg_ax.setLabel("left", "Distance (cm)") self.obstacle_bg_im.setLookupTable( example_utils.pg_mpl_cmap("viridis")) self.obstacle_bg_ax.addItem(self.obstacle_bg_im) row_idx += 1 if self.advanced_plots["threshold_map"]: self.obstacle_thresh_ax = win.addPlot(row=row_idx, col=0, colspan=self.num_hist_plots, title="Obstacle threshold") self.obstacle_thresh_im = pg.ImageItem() self.obstacle_thresh_ax.setLabel("bottom", "Velocity (cm/s)") self.obstacle_thresh_ax.setLabel("left", "Distance (cm)") self.obstacle_thresh_im.setLookupTable( example_utils.pg_mpl_cmap("viridis")) self.obstacle_thresh_ax.addItem(self.obstacle_thresh_im) row_idx += 1 hist_col = 0 row_idx += self.num_hist_plots if self.hist_plots["distance"][1]: self.peak_hist_ax_l = win.addPlot(row=row_idx, col=hist_col, title="Distance history") self.peak_hist_ax_l.setLabel("bottom", "Sweep") self.peak_hist_ax_l.setXRange(0, self.peak_hist_len) self.peak_hist_ax_l.showGrid(True, True) self.peak_hist_ax_l.addLegend(offset=(-10, 10)) self.peak_hist_ax_l.setYRange(self.sensor_config.range_start * 100, self.sensor_config.range_end * 100) hist_col += 1 if self.hist_plots["velocity"][1]: self.peak_hist_ax_c = win.addPlot(row=row_idx, col=hist_col, title="Velocity history") self.peak_hist_ax_c.setLabel("bottom", "Sweep") self.peak_hist_ax_c.setXRange(0, self.peak_hist_len) limit = np.round(self.max_velocity / 10) * 10 if limit < 1.0: limit = self.max_velocity self.peak_hist_ax_c.setYRange(-limit, limit) self.peak_hist_ax_c.showGrid(True, True) self.peak_hist_ax_c.addLegend(offset=(-10, 10)) hist_col += 1 if self.hist_plots["angle"][1]: self.peak_hist_ax_r = win.addPlot(row=row_idx, col=hist_col, title="Angle history") self.peak_hist_ax_r.setLabel("bottom", "Sweep") self.peak_hist_ax_r.setXRange(0, self.peak_hist_len) self.peak_hist_ax_r.showGrid(True, True) self.peak_hist_ax_r.addLegend(offset=(-10, 10)) self.peak_hist_ax_r.setYRange(-100, 100) hist_col += 1 if self.hist_plots["amplitude"][1]: self.peak_hist_ax_r1 = win.addPlot(row=row_idx, col=hist_col, title="Amplitude history") self.peak_hist_ax_r1.setLabel("bottom", "Sweep") self.peak_hist_ax_r1.setXRange(0, self.peak_hist_len) self.peak_hist_ax_r1.showGrid(True, True) self.peak_hist_ax_r1.addLegend(offset=(-10, 10)) hist_col += 1 for i in range(self.nr_locals): if self.hist_plots["velocity"][1]: self.hist_plots["velocity"][0].append( self.peak_hist_ax_c.plot( pen=example_utils.pg_pen_cycler(i), name="Veloctiy {:d}".format(i))) if self.hist_plots["angle"][1]: self.hist_plots["angle"][0].append( self.peak_hist_ax_r.plot( pen=example_utils.pg_pen_cycler(i), name="Angle {:d}".format(i))) if self.hist_plots["distance"][1]: self.hist_plots["distance"][0].append( self.peak_hist_ax_l.plot( pen=example_utils.pg_pen_cycler(i), name="Distance {:d}".format(i))) if self.hist_plots["amplitude"][1]: self.hist_plots["amplitude"][0].append( self.peak_hist_ax_r1.plot( pen=example_utils.pg_pen_cycler(i), name="Amplitude {:d}".format(i))) self.smooth_max = example_utils.SmoothMax( self.sensor_config.sweep_rate, tau_decay=1, tau_grow=0.2)