def __init__(self, cell_line, lineage_num):
        self.cell_line = cell_line
        self.lineage_num = lineage_num
        self.T = cell_line[0].T
        self.t = cell_line[0].t
        self.L = np.array([x.length[0][0] for x in cell_line])
        self.spots = shared.get_parB_path(self.cell_line, self.T, self.lineage_num)
        self.spot_storage = SpotStorage()

        self.plot_setup()
        self.plot_parB()

        plt.show()
def get_parB_split(lin, lin_num):
    """ Time until first ParB spot splits, or None if no split """
    parB_paths = shared.get_parB_path(lin, lin[0].T, lin_num)
    lin_t0 = lin[0].T[lin[0].frame - 1]
    split_times = []
    for path in parB_paths:
        if type(path) is shared.TraceConnect:
            if path.split_parent:
                # it has split!
                # get timing of split
                split_times.append(path.timing[0] - lin_t0)
    if not split_times:
        return None
    else:
        return np.min(split_times)
def process():
    lin_files = sorted(glob.glob("data/cell_lines/lineage*.npy"))
    lineage_nums = sorted([int(re.search("lineage(\d+).npy", x).group(1)) for x in lin_files])
    processable = []
    traces = {}
    for lineage_num in lineage_nums:
        lineage_file = "data/cell_lines/lineage{0:02d}.npy".format(lineage_num)
        cell_line = np.load(lineage_file)
        T = cell_line[0].T
        parB_paths = shared.get_parB_path(cell_line, T, lineage_num)

        for spot_trace in parB_paths:
            if hasattr(spot_trace, "spot_ids"):
                traces[spot_trace.spot_ids[0]] = spot_trace
            if type(spot_trace) is shared.TraceConnect and spot_trace.split_children:
                processable.append((
                    spot_trace.split_children[0],
                    spot_trace.split_children[1],
                    spot_trace
                ))

    velocities = []
    growth_rates = []
    elong_rates = []

    for spot_pair in processable:
        spot1 = traces[spot_pair[0]]
        spot2 = traces[spot_pair[1]]
        parent = spot_pair[2]

        add_parent(parent, spot1)
        add_parent(parent, spot2)

        # take spot with minimum max timing as comparator (spot1)
        if spot1.spots()["timing"].max() > spot2.spots()["timing"].max():
            delta = get_delta(spot2, spot1)
        else:
            delta = get_delta(spot1, spot2)

        if len(delta) >= 5:
            interspot_velocity = get_velocity(delta)
            if interspot_velocity:
                velocities.append(interspot_velocity)
                growth_rates.append(get_growth_rate(delta))
                elong_rates.append(get_elong_rate(delta))

    return velocities, growth_rates, elong_rates
def process():
    lin_files = sorted(glob.glob("data/cell_lines/lineage*.npy"))
    spots = []
    for lf in lin_files:
        lineage_num = int(re.search("lineage(\d+).npy", lf).group(1))
        cell_line = np.load(lf)
        elongation_rate = shared.get_elongation_rate(cell_line, discard=True)
        if not elongation_rate or len(cell_line) < THRESHOLD_FRAMES:
            continue

        parB_paths = shared.get_parB_path(cell_line, cell_line[0].T, lineage_num)
        spot_num = 1
        for path in parB_paths:
            spot_trace = path.spots()
            lengths = list(path.len())
            idx = 0
            spot_data = {
                "t": [],
                "intensity": [],
                "cell_length": lengths,
                "x_mid": [],
                "x_new": [],
                "x_old": [],
                "pole_known": cell_line[0].pole_assignment,
                "spot_num": spot_num,
                "lineage_num": lineage_num,
            }
            for x in spot_trace:
                l = lengths[idx]
                x_M = x[1]
                x_N = x[1] + (l / 2)
                x_O = l - x_N
                spot_data["t"].append(x[0])
                spot_data["intensity"].append(x[2])
                spot_data["x_mid"].append(x_M)
                spot_data["x_new"].append(x_N)
                spot_data["x_old"].append(x_O)
                idx += 1
            spot_num += 1
            if len(spot_data["t"]) >= THRESHOLD_FRAMES:
                spots.append(spot_data)
                # calculate diffusion parameters
                d_mid, d_new, d_old = diffusion(spot_data)

    s = pd.DataFrame(spots)
    print(s)
def get_traces(orig_dir=None, two_spot=False, reuse=True):
    data_hash = hashlib.sha1(os.getcwd().encode("utf8")).hexdigest()
    if reuse and orig_dir and os.path.exists(os.path.join(orig_dir, "ParB_velocity", "data", data_hash)):
        data_dir = os.path.join(orig_dir, "ParB_velocity", "data", data_hash)
        files = sorted(glob.glob(os.path.join(data_dir, "*.pandas")))
        spot_data = []
        progress = progressbar.ProgressBar()
        for f in progress(files):
            spot_data.append(pd.read_pickle(f))
        return spot_data

    lin_files = sorted(glob.glob("data/cell_lines/lineage*.npy"))
    lineage_nums = [int(re.search("lineage(\d+).npy", x).group(1)) for x in lin_files]
    spot_data = []
    progress = progressbar.ProgressBar()
    for lineage_num, lf in progress(list(zip(lineage_nums, lin_files))):
        cell_line = np.load(lf)
        if not hasattr(cell_line[0], "pole_assignment") or cell_line[0].pole_assignment is None:
            continue
#        pole_assignment = cell_line[0].pole_assignment

        T = cell_line[0].T
        paths = shared.get_parB_path(cell_line, T, lineage_num)

        if two_spot:
            if len(paths) != 3:
                continue

            if len(cell_line[0].ParB) != 1:
                continue

        cell_elongation_rate = shared.get_elongation_rate(cell_line)
        if cell_elongation_rate and cell_elongation_rate < 0:
            cell_elongation_rate = 0
        spot_num = 1
        for path in paths:
            # path.positions: distance from midcell
            spot_trace = path.spots()
            timing = []
            d_mid = []
            d_parA = []

            intensity = []
            lengths = path.len()
            for x in spot_trace:
                timing.append(x[0])
                d_mid.append(x[1])
                intensity.append(x[2])

                c_idx = list(cell_line[0].t).index(x[0])
                cell = cell_line[c_idx]
                parA_mid = cell.ParA[0] - (cell.length[0][0] / 2)
                dparA = np.abs(parA_mid - x[1])
                d_parA.append(dparA)

            data = pd.DataFrame(
                data={
                    "timing": timing,
                    "d_mid": d_mid,  # negative = closer to new pole
                    "d_parA": d_parA,
                    "intensity": intensity,
                    "cell_length": lengths,
                },
            )

            data["d_new"] = data.d_mid + (data.cell_length / 2)
            data["d_old"] = data.cell_length - data.d_new

            path, subdir = os.path.split(os.getcwd())
            topdir = os.path.basename(path)
            data._path = os.getcwd()
            data._top_dir = topdir
            data._sub_dir = subdir
            data._lineage_num = lineage_num
            data._spot_num = spot_num
            data._cell_line_id = cell_line[0].id
            data._elongation_rate = cell_elongation_rate
            data._hash = hashlib.sha256("{0}-{1}-{2}-{3}".format(
                topdir,
                subdir,
                lineage_num,
                spot_num,
            ).encode("utf-8")).hexdigest()
            data._metadata = [
                "_path", "_top_dir", "_sub_dir", "_lineage_num",
                "_spot_num", "_cell_line_id",
                "_elongation_rate", "_hash"
            ]

            if orig_dir:
                target_dir = os.path.join(orig_dir, "ParB_velocity", "data", data_hash)
                if not os.path.exists(target_dir):
                    os.makedirs(target_dir)
                data.to_pickle(os.path.join(
                    target_dir, "{0:03d}-{1:03d}.pandas".format(lineage_num, spot_num)
                ))

            spot_data.append(data)
            spot_num += 1
    return spot_data
def plot_graphs(cell_line, lineage_num, num_plots=5, parA_heatmap=None, save=True, labels=None, um=False, plot_kwargs=None):
    lineage = track.Lineage()
    if save:
        fig = plt.figure(figsize=(20, 10))
        gs = matplotlib.gridspec.GridSpec(2, 3)
        fig.patch.set_alpha(0)

    spots_ParA = []
    traces_ParA = []
    L = []
    T = shared.get_timings()
    for cell in cell_line:
        spots_ParA.append(cell.ParA)
        traces_ParA.append(cell.parA_fluorescence_smoothed[::-1])
        if um:
            L.append(cell.length[0][0] * PX)
        else:
            L.append(cell.length[0][0])
    L = np.array(L)

    traces_ParA = np.concatenate(traces_ParA)
    max_parA_intensity = traces_ParA.max()

    start = cell_line[0].frame - 1
    end = cell_line[-1].frame - 1
    t = np.array(T[start:end + 1])

    if save:
        parA_heatmap = fig.add_subplot(gs[0, 0])
        _despine(parA_heatmap)
    # use Rectangles to generate a heatmap
    i = 0
    cmapper = plt.cm.get_cmap("afmhot")
    for cell in cell_line:
        trace = cell.parA_fluorescence_smoothed
        if um:
            l = cell.length[0][0] * PX
        else:
            l = cell.length[0][0]
        x0 = t[i] - 8
        y0 = -(l / 2)
        increment = l / len(trace)
        colours = cmapper(trace / max_parA_intensity)
        i2 = 0
        for _t in trace:
            if _t < 0:
                _t = 0
            r = matplotlib.patches.Rectangle(
                (x0, y0),
                width=15,
                height=increment,
                facecolor=colours[i2],
                edgecolor="none",
            )
            parA_heatmap.add_patch(r)
            y0 += increment
            i2 += 1
        i += 1

    if save:
        parA_heatmap.set_ylabel(r"Distance from mid-cell (px)")
        parA_heatmap.set_xlabel(r"Time (min)")
        parA_heatmap.set_title("ParA")

    poledict = poles.PoleAssign(lineage.frames).assign_poles()
    if poledict[cell_line[0].id] is None:
        parA_heatmap.plot(t, L / 2, "r-", lw=2)
        parA_heatmap.plot(t, -(L / 2), "r-", lw=2)
    else:
        parA_heatmap.plot(t, L / 2, "k-", lw=2)
        parA_heatmap.plot(t, -(L / 2), "k-", lw=2)

    parAs = {}
    i = 0
    for s in spots_ParA:
        midcell = s[2] / 2
        spot = s[0] - midcell
        parAs[t[i]] = spot
        i += 1
    parAs = np.array(sorted(parAs.items()))

    if num_plots >= 2:
        parA_heatmap.plot(
            parAs[:, 0], parAs[:, 1],
            lw=2, marker=".", mec="k", ms=10
        )

    decorate_daughters(cell_line, lineage, parA_heatmap, labels=labels, um=um)
    parA_heatmap.patch.set_alpha(0)

    if num_plots >= 3:
        ax_parA = fig.add_subplot(gs[1, 0])
        _despine(ax_parA)
        ax_parA.set_title("ParA maximum")
        ax_parA.plot(
            parAs[:, 0], (L / 2) - parAs[:, 1],
            marker=".", lw=2, mec="k", ms=10,
            label="Distance from top pole"
        )
        ax_parA.plot(
            parAs[:, 0], (L / 2) + parAs[:, 1],
            marker=".", lw=2, mec="k", ms=10,
            label="Distance from bottom pole"
        )
        ax_parA.set_xlabel(r"Time (min)")
        ax_parA.set_ylabel(r"Distance (px)")
        ax_parA.patch.set_alpha(0)

    if num_plots >= 2:
        parB_midcell = fig.add_subplot(gs[0, 1])
        _despine(parB_midcell)
        parB_midcell.set_title("ParB")
        parB_midcell.plot(t, L / 2, "k-", lw=2, label="Cell poles")
        parB_midcell.plot(t, -(L / 2), "k-", lw=2)

    spots_ParB = shared.get_parB_path(cell_line, T, lineage_num)
    spotnum = 1
    for x in spots_ParB:
        s = x.spots(False)
        if hasattr(x, "split_parent") and x.split_parent:
            for y in spots_ParB:
                if y.spot_ids[-1] == x.split_parent:
                    textra = y.timing[-1:]
                    timings = np.concatenate([textra, s["timing"]])
                    posextra = np.array(y.position[-1:])
                    if um:
                        positions = np.concatenate([posextra * PX, s["position"] * PX])
                    else:
                        positions = np.concatenate([posextra, s["position"]])
                    break
        else:
            timings = s["timing"]
            if um:
                positions = s["position"] * PX
            else:
                positions = s["position"]

        if num_plots >= 2:
            ax_target = parB_midcell
            label = "Spot {0}".format(spotnum)
        else:
            ax_target = parA_heatmap
            label = "ParB"

        if plot_kwargs:
            ax_target.plot(
                timings, positions, **plot_kwargs
            )
        else:
#            ax_target.plot(
#                timings, positions,
#                lw=2,
#                marker=".",
#                markeredgecolor="k",
#                ms=10,
#                label=label,
#                color=colour,
#            )
            ax_target.plot(
                timings, positions,
                lw=2,
                marker=".",
                markeredgecolor="k",
                ms=10,
                label=label,
                color="k",
                path_effects=[
                    matplotlib.patheffects.Stroke(
                        linewidth=2, foreground=(0.7, 0.7, 0.7)
                    )
                ],
            )

        dparA = []
        for spot in s:
            parApos = parAs[np.where(parAs[:, 0] == spot[0])][0, 1]
            dpA = spot[1] - parApos
            dparA.append(dpA)

        x.parA_d = dparA
        x.parA_dmean = np.mean(dparA)
        x.parA_dsem = np.std(dparA) / np.sqrt(len(dparA))
        x.spotnum = spotnum
        x.intensity_mean = s["intensity"].mean()

        spotnum += 1

    if num_plots >= 2:
        lines = parB_midcell.lines[::-1]
        for l in lines:
            parB_midcell.lines.remove(l)
            parB_midcell.add_line(l)

        parB_midcell.set_ylabel(r"Distance from mid-cell (px)")
        parB_midcell.set_xlabel(r"Time (min)")

        decorate_daughters(cell_line, lineage, parB_midcell, pad=5, labels=labels, um=um)

        parB_midcell.legend(bbox_to_anchor=(1.35, 1))
        parB_midcell.patch.set_alpha(0)
    else:
        if save:
            parA_heatmap.legend(
                [parA_heatmap.lines[-1]], [parA_heatmap.lines[-1].get_label()],
                bbox_to_anchor=(1.2, 1)
            )

    if num_plots >= 4:
        filtered = [x for x in spots_ParB if len(x) > 4]
        if len(filtered) > 0:
            ax_parB_closest = fig.add_subplot(gs[1, 1], sharex=ax_parA, sharey=ax_parA)
            dmin = min(
                filtered,
                key=lambda x: np.abs(x.parA_dmean)
            )
            ax_parB_closest.set_title("ParB spot {0} (dmin)".format(dmin.spotnum))
            _despine(ax_parB_closest)
            s = dmin.spots(False)
            dpol_t = (dmin.len() / 2) - s["position"]
            dpol_b = (dmin.len() / 2) + s["position"]

            ax_parB_closest.plot(
                s["timing"], dpol_t,
                marker=".", lw=2, mec="k", ms=10,
                label="Distance from top pole"
            )
            ax_parB_closest.plot(
                s["timing"], dpol_b,
                marker=".", lw=2, mec="k", ms=10,
                label="Distance from bottom pole"
            )
            ax_parB_closest.plot(
                s["timing"], dmin.parA_d,
                marker=".", lw=2, ms=10,
                label="Distance from ParA focus"
            )
            ax_parB_closest.plot(
                ax_parB_closest.get_xlim(),
                [0, 0],
                "k--"
            )
            ax_parB_closest.patch.set_alpha(0)

            if num_plots >= 5:
                imax = max(filtered, key=lambda x: x.intensity_mean)
                if imax.id != dmin.id:
                    ax_parB_highest = fig.add_subplot(gs[1, 2], sharex=ax_parB_closest, sharey=ax_parA)
                    s = imax.spots(False)
                    dpol_t = (imax.len() / 2) - s["position"]
                    dpol_b = (imax.len() / 2) + s["position"]
                    ax_parB_highest.plot(s["timing"], dpol_t, marker=".", lw=2, mec="k", ms=10, label="Distance from top pole")
                    ax_parB_highest.plot(s["timing"], dpol_b, marker=".", lw=2, mec="k", ms=10, label="Distance from bottom pole")
                    ax_parB_highest.plot(s["timing"], imax.parA_d, marker=".", lw=2, mec="k", ms=10, label="Distance from ParA focus")

                    ax_parB_highest.plot(ax_parB_highest.get_xlim(), [0, 0], "k--")

                    _despine(ax_parB_highest)
                    ax_parB_highest.set_title("ParB Spot {0} (imax)".format(imax.spotnum))
                    ax_parB_highest.set_ylabel(r"Distance (px)")
                    ax_parB_highest.set_xlabel("Time (min)")
                    ax_parB_highest.patch.set_alpha(0)
                    ax_parB_highest.legend(bbox_to_anchor=(0.8, 1.35))
                else:
                    ax_parB_closest.legend(bbox_to_anchor=(1.65, 1))
            else:
                ax_parB_closest.legend(bbox_to_anchor=(1.65, 1))
        else:
            ax_parA.legend(bbox_to_anchor=(1.65, 1))

    if save:
        plt.tight_layout()
        fn = "data/data-lineage{0:02d}.pdf".format(lineage_num)
        plt.savefig(fn)
        print("Saved data file to {0}".format(fn))
def plot_graphs_parB_only(cell_line, lineage_num, ax_parB=None, save=True, labels=None, um=False):
    if um:
        L = np.array([x.length[0][0] * PX for x in cell_line])
    else:
        L = np.array([x.length[0][0] for x in cell_line])
    T = shared.get_timings()
    t = np.array(T[cell_line[0].frame - 1:cell_line[-1].frame])

    lineage = track.Lineage()

    if not ax_parB:
        fig = plt.figure(figsize=(20 / 3, 5))
        ax_parB = fig.add_subplot(111)
        _despine(ax_parB)
        ax_parB.set_title("ParB")
        ax_parB.set_ylabel(r"Distance from mid-cell (px)")
        ax_parB.set_xlabel(r"Time (min)")

    poledict = poles.PoleAssign(lineage.frames).assign_poles()
    if poledict[cell_line[0].id] is None:
        ax_parB.plot(t, L / 2, "r-", lw=2, label="Cell poles")
        ax_parB.plot(t, -(L / 2), "r-", lw=2)
    else:
        ax_parB.plot(t, L / 2, "k-", lw=2, label="Cell poles")
        ax_parB.plot(t, -(L / 2), "k-", lw=2)

    spots_ParB = shared.get_parB_path(cell_line, T, lineage_num)
    spotnum = 1
    colourwheel = sns.color_palette(n_colors=len(spots_ParB))
    for x in spots_ParB:
        colour = colourwheel[spotnum - 1]
        s = x.spots(False)
        if hasattr(x, "split_parent") and x.split_parent:
            for y in spots_ParB:
                if y.spot_ids[-1] == x.split_parent:
                    textra = y.timing[-1:]
                    timings = np.concatenate([textra, s["timing"]])
                    posextra = np.array(y.position[-1:])
                    if um:
                        positions = np.concatenate([posextra * PX, s["position"] * PX])
                    else:
                        positions = np.concatenate([posextra, s["position"]])
                    break
        else:
            timings = s["timing"]
            if um:
                positions = s["position"] * PX
            else:
                positions = s["position"]

        ax_parB.plot(
            timings, positions,
            lw=2, marker=".",
            mec="k", ms=10,
            label="Spot {0}".format(spotnum),
            color=colour
        )
        spotnum += 1

    lines = ax_parB.lines[::-1]
    for l in lines:
        ax_parB.lines.remove(l)
        ax_parB.add_line(l)

    decorate_daughters(cell_line, lineage, ax_parB, pad=5, labels=labels, um=um)

    if save:
        ax_parB.legend(bbox_to_anchor=(1.35, 1))
        ax_parB.patch.set_alpha(0)

        plt.tight_layout()
        fn = "data/data-lineage{0:02d}.pdf".format(lineage_num)
        plt.savefig(fn)
        print("Saved data file to {0}".format(fn))
        plt.close()
 def determine_par_path(self, force=False):
     self.spots = shared.get_parB_path(self.cell_line, self.T, self.lineage_num, force=force)
def gen_xl(cell_line, lineage_num):
    lineage_num = int(lineage_num)
    T = cell_line[0].T
    t = cell_line[0].t

    spots_ParA = [x.ParA for x in cell_line]
    spots_ParB = shared.get_parB_path(cell_line, T, lineage_num)

    excel_wb = xlwt.Workbook()
    ws_parA = excel_wb.add_sheet("ParA")
    ws_parB = excel_wb.add_sheet("ParB")

    ws_parA.write(0, 0, "Time")
    ws_parA.write(0, 1, "Distance from top pole")
    ws_parA.write(0, 2, "Distance from midcell")
    ws_parA.write(0, 3, "Cell length")
    ws_parA.write(0, 4, "Spot intensity")

    parAs = {}
    i = 0
    for pos, inten, celllen in spots_ParA:
        midcell = celllen / 2
        spot = pos - midcell

        ws_parA.write(i + 1, 0, int(t[i]))
        ws_parA.write(i + 1, 1, float(pos))
        ws_parA.write(i + 1, 2, float(spot))
        ws_parA.write(i + 1, 3, float(celllen))
        ws_parA.write(i + 1, 4, float(inten))
        parAs[t[i]] = spot

        ws_parB.write(i + 1, 1, float(celllen))

        i += 1

    ws_parB.write(0, 0, "Time")
    ws_parB.write(0, 1, "Cell length")

    i = 1
    time_dict = {}
    for time_ in t:
        ws_parB.write(i, 0, int(time_))
        time_dict[float(time_)] = i
        i += 1

    rmax = max(time_dict.values())
    ws_parB.write(rmax + 2, 0, "Intensity mean:")
    ws_parB.write(rmax + 3, 0, "Intensity SEM:")
    ws_parB.write(rmax + 4, 0, "Distance from ParA (mean):")
    ws_parB.write(rmax + 5, 0, "Distance from ParA (SEM):")

    col = 2
    spotnum = 1
    for x in spots_ParB:
        s = x.spots(False)
        ws_parB.write(0, col, "Distance from mid-cell (Spot {0})".format(spotnum))
        ws_parB.write(0, col + 1, "Intensity (Spot {0})".format(spotnum))
        ws_parB.write(0, col + 2, "Distance from ParA (Spot {0})".format(spotnum))

        parA_d = []
        for spot in s:
            r = time_dict[spot[0]]
            ws_parB.write(r, col, float(spot[1]))
            ws_parB.write(r, col + 1, float(spot[2]))
            dpA = spot[1] - parAs[spot[0]]
            parA_d.append(dpA)
            ws_parB.write(r, col + 2, float(dpA))

        # intensity mean and SEM for spot lineage
        intensity_mean = s["intensity"].mean()
        intensity_sem = s["intensity"].std() / np.sqrt(len(s["intensity"]))
        ws_parB.write(rmax + 2, col + 1, float(intensity_mean))
        ws_parB.write(rmax + 3, col + 1, float(intensity_sem))

        # distance from ParA mean and SEM for spot lineage
        parA_dmean = np.mean(parA_d)
        parA_dsem = np.std(parA_d) / np.sqrt(len(parA_d))
        ws_parB.write(rmax + 4, col + 2, float(parA_dmean))
        ws_parB.write(rmax + 5, col + 2, float(parA_dsem))

        col += 3
        spotnum += 1

    if not os.path.exists("data/xls"):
        os.mkdir("data/xls")

    fn = "data/xls/lineage{0:02d}.xls".format(lineage_num)

    if os.path.exists(fn):
        if not os.path.exists("data/xls/backups"):
            os.mkdir("data/xls/backups")

        backup_file = "data/xls/backups/{0}-lineage{1:02d}.xls".format(
            datetime.datetime.strftime(datetime.datetime.now(), "%Y%m%d-%H%M"),
            lineage_num
        )
        attempt = 2
        while os.path.exists(backup_file):
            first = backup_file.split(".xls")[0]
            backup_file = "{0}.xls-{1}".format(first, attempt)
            attempt += 1
        print("Backing up previous xls file to {0}".format(backup_file))
        os.rename(fn, backup_file)

    print("Saving new xls file to {0}".format(fn))
    excel_wb.save(fn)