In [1]:
import itertools
import xml.etree.cElementTree as et

import networkx as nx
import pandas as pd
import numpy as np


def trackmate_peak_import(trackmate_xml_path, get_tracks=False):
    """Import detected peaks with TrackMate Fiji plugin.

    Parameters
    ----------
    trackmate_xml_path : str
        TrackMate XML file path.
    get_tracks : boolean
        Add tracks to label
    """

    root = et.fromstring(open(trackmate_xml_path).read())

    objects = []
    object_labels = {'FRAME': 't_stamp',
                     'POSITION_T': 't',
                     'POSITION_X': 'x',
                     'POSITION_Y': 'y',
                     'POSITION_Z': 'z',
                     'MEAN_INTENSITY': 'I',
                     'ESTIMATED_DIAMETER': 'w',
                     'QUALITY': 'q',
                     'ID': 'spot_id',
                     'MEAN_INTENSITY': 'mean_intensity',
                     'MEDIAN_INTENSITY': 'median_intensity',
                     'MIN_INTENSITY': 'min_intensity',
                     'MAX_INTENSITY': 'max_intensity',
                     'TOTAL_INTENSITY': 'total_intensity',
                     'STANDARD_DEVIATION': 'std_intensity',
                     'CONTRAST': 'contrast',
                     'SNR': 'snr'}

    features = root.find('Model').find('FeatureDeclarations').find('SpotFeatures')
    features = [c.get('feature') for c in features.getchildren()] + ['ID']

    spots = root.find('Model').find('AllSpots')
    trajs = pd.DataFrame([])
    objects = []
    for frame in spots.findall('SpotsInFrame'):
        for spot in frame.findall('Spot'):

            single_object = []
            for label in features:
                single_object.append(spot.get(label))

            objects.append(single_object)
    trajs = pd.DataFrame(objects, columns=features)
    trajs = trajs.astype(np.float)

    # Apply initial filtering
    initial_filter = root.find("Settings").find("InitialSpotFilter")

    trajs = filter_spots(trajs,
                         name=initial_filter.get('feature'),
                         value=float(initial_filter.get('value')),
                         isabove=True if initial_filter.get('isabove') == 'true' else False)

    # Apply filters
    spot_filters = root.find("Settings").find("SpotFilterCollection")

    for spot_filter in spot_filters.findall('Filter'):

        trajs = filter_spots(trajs,
                             name=spot_filter.get('feature'),
                             value=float(spot_filter.get('value')),
                             isabove=True if spot_filter.get('isabove') == 'true' else False)

    trajs = trajs.loc[:, object_labels.keys()]
    trajs.columns = [object_labels[k] for k in object_labels.keys()]
    trajs['label'] = np.arange(trajs.shape[0])

    # Get tracks
    if get_tracks:
        filtered_track_ids = [int(track.get('TRACK_ID')) for track in root.find('Model').find('FilteredTracks').findall('TrackID')]

        new_trajs = pd.DataFrame()
        label_id = 0
        trajs = trajs.set_index('spot_id')

        tracks = root.find('Model').find('AllTracks')
        for track in tracks.findall('Track'):

            track_id = int(track.get("TRACK_ID"))
            if track_id in filtered_track_ids:

                spot_ids = [(edge.get('SPOT_SOURCE_ID'), edge.get('SPOT_TARGET_ID'), edge.get('EDGE_TIME')) for edge in track.findall('Edge')]
                spot_ids = np.array(spot_ids).astype('float')
                spot_ids = pd.DataFrame(spot_ids, columns=['source', 'target', 'time'])
                spot_ids = spot_ids.sort_values(by='time')
                spot_ids = spot_ids.set_index('time')

                # Build graph
                graph = nx.Graph()
                for t, spot in spot_ids.iterrows():
                    graph.add_edge(int(spot['source']), int(spot['target']), attr_dict=dict(t=t))

                # Find graph extremities by checking if number of neighbors is equal to 1
                tracks_extremities = [node for node in graph.nodes() if len(graph.neighbors(node)) == 1]

                paths = []
                # Find all possible paths between extremities
                for source, target in itertools.combinations(tracks_extremities, 2):

                    # Find all path between two nodes
                    for path in nx.all_simple_paths(graph, source=source, target=target):

                        # Now we need to check wether this path respect the time logic contraint
                        # edges can only go in one direction of the time

                        # Build times vector according to path
                        t = []
                        for i, node_srce in enumerate(path[:-1]):
                            node_trgt = path[i+1]
                            t.append(graph.edge[node_srce][node_trgt]['t'])

                        # Will be equal to 1 if going to one time direction
                        if len(np.unique(np.sign(np.diff(t)))) == 1:
                            paths.append(path)

                # Add each individual trajectory to a new DataFrame called new_trajs
                for path in paths:
                    traj = trajs.loc[path].copy()
                    traj['label'] = label_id
                    label_id += 1

                    new_trajs = new_trajs.append(traj)

        trajs = new_trajs

    trajs.set_index(['t_stamp', 'label'], inplace=True)
    trajs = trajs.sort_index()

    return trajs


def filter_spots(spots, name, value, isabove):
    if isabove:
        spots = spots[spots[name] > value]
    else:
        spots = spots[spots[name] < value]

    return spots

In [2]:
# Load peaks and/or trajectories from xml 
trajs = trackmate_peak_import("/home/hadim/test.xml", get_tracks=True)

In [3]:
trajs


Out[3]:
max_intensity min_intensity q z w y mean_intensity x snr t std_intensity contrast median_intensity total_intensity
t_stamp label
0 0 166 0 3.539891 0 2.000000 112.285192 30.659794 104.458460 0.211005 0 32.747101 0.126995 23 2974
1 254 0 6.459367 0 19.000000 4.018656 41.773196 63.970888 0.469716 0 52.474697 0.418488 25 4052
2 220 0 6.275804 0 6.952403 116.359733 46.371134 116.289535 0.540710 0 51.661018 0.431017 24 4498
1 0 135 0 2.616775 0 2.000000 112.441575 25.845361 104.253699 0.345046 1 28.895768 0.238981 17 2507
1 239 0 6.811550 0 2.000000 6.173494 41.453608 64.120220 0.449295 1 51.783608 0.390102 24 4021
2 220 0 6.891733 0 6.796027 116.278536 47.288660 116.189521 0.595183 1 52.254776 0.489966 27 4587
2 0 152 0 2.260737 0 2.000000 112.406450 24.814433 104.228938 0.317349 2 28.759900 0.225346 17 2407
1 254 0 6.687568 0 2.000000 9.962219 40.958763 64.088871 0.480468 2 48.954894 0.402787 22 3973
2 220 1 6.748422 0 4.910432 116.072059 47.000000 116.239764 0.550095 2 51.127496 0.426945 25 4559
3 0 192 0 3.248708 0 2.000000 112.427749 30.824742 104.274101 0.125869 3 32.372831 0.070773 25 2990
1 254 0 9.269295 0 2.000000 12.601007 50.402062 63.622595 0.522690 3 61.153948 0.464334 26 4889
2 220 0 6.749822 0 4.841736 116.125925 47.649485 116.424832 0.523611 3 51.611740 0.395821 29 4622
4 0 127 0 3.127262 0 19.000000 112.374933 28.329897 104.234383 0.361629 4 28.219276 0.219673 18 2748
1 252 1 9.141627 0 2.000000 16.322334 52.917526 62.410494 0.506454 4 56.357614 0.369279 34 5133
2 220 0 6.377168 0 6.874828 115.948977 46.206186 116.465886 0.526452 4 49.541426 0.393196 27 4482
5 0 167 0 3.596664 0 2.000000 112.485475 30.422680 104.456023 0.374729 5 31.816805 0.243705 22 2951
1 255 0 9.244539 0 2.000000 19.492452 51.288660 59.503075 0.546240 5 61.284677 0.484451 25 4975
2 220 0 6.406635 0 6.813202 116.327674 47.742268 116.299262 0.453571 5 53.034242 0.336761 29 4631
6 0 189 0 3.289266 0 2.000000 112.921300 29.288660 104.585002 0.474971 6 30.741177 0.332024 20 2841
1 252 0 9.341927 0 19.000000 19.520002 52.061856 59.697994 0.540665 6 60.456736 0.457563 31 5050
2 220 0 6.743909 0 6.782126 116.130050 45.752577 116.325084 0.655052 6 50.858675 0.572522 23 4438
7 0 143 0 2.507370 0 15.114519 112.379669 27.546392 104.444239 0.443493 7 25.471398 0.257930 19 2672
1 241 0 8.990104 0 2.000000 21.636953 48.061856 57.560041 0.582806 7 58.766277 0.553531 26 4662
2 220 0 6.388138 0 2.000000 115.991250 46.804124 116.485707 0.499167 7 51.318783 0.376761 28 4540
8 0 147 0 2.828063 0 2.000000 112.275842 28.546392 104.506405 0.199144 8 28.478801 0.110292 21 2769
1 253 0 9.626597 0 2.000000 22.457981 51.494845 57.491175 0.526961 8 62.732090 0.472705 29 4995
2 220 0 6.871429 0 4.877331 115.988632 48.876289 116.413148 0.577965 8 48.988787 0.407752 28 4741
9 0 147 0 2.532444 0 19.000000 112.548939 26.268041 104.490235 0.377790 9 28.502747 0.257806 19 2548
1 248 0 8.167829 0 2.000000 25.449153 51.804124 61.807489 0.457569 9 58.306239 0.346801 29 5025
2 220 0 6.473447 0 7.136718 116.061436 47.876289 116.253786 0.498705 9 50.633746 0.358168 30 4644
... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ...
40 2 220 0 6.713731 0 4.923968 116.137285 45.639175 116.368568 0.575204 40 51.962764 0.486880 27 4427
4 245 0 9.056150 0 2.000000 117.411790 50.484536 51.427712 0.590702 40 58.907964 0.525857 30 4897
5 249 1 8.701788 0 2.000000 23.507749 46.432990 108.355721 0.528205 40 61.047268 0.531924 22 4504
41 0 130 0 2.441414 0 19.000000 112.225474 28.072165 104.337510 -0.019684 41 24.910777 -0.008658 22 2723
2 220 0 6.803139 0 19.000000 116.124281 48.134021 116.183281 0.501556 41 49.364425 0.346236 32 4669
4 251 2 9.592649 0 2.000000 120.580065 53.226804 51.504364 0.538996 41 63.616937 0.475156 27 5163
5 247 0 10.275146 0 4.811327 27.499036 53.587629 108.398969 0.557779 41 63.802389 0.497120 27 5198
42 0 143 0 2.344439 0 2.623352 112.488103 28.072165 104.034249 0.249303 42 26.362160 0.132578 22 2723
2 220 0 6.760175 0 4.889275 116.226037 48.577320 116.264016 0.437017 42 51.233297 0.299470 28 4712
5 255 1 9.347189 0 19.000000 31.439208 50.711340 108.468952 0.635266 42 63.593592 0.662017 27 4919
43 0 188 0 3.176369 0 2.000000 112.988285 28.876289 104.549988 0.231341 43 33.235667 0.153580 18 2801
2 220 0 6.644869 0 4.980755 116.036181 45.680412 116.418902 0.606213 43 52.053367 0.527635 24 4431
5 252 2 9.785413 0 2.000000 35.523132 53.319588 108.485461 0.467055 43 61.972532 0.372543 28 5172
44 0 170 0 2.919489 0 2.000000 112.334688 28.463918 104.494581 0.355945 44 31.855815 0.248721 23 2761
2 220 0 6.701843 0 6.846303 115.956364 46.639175 116.353914 0.535013 44 50.375710 0.406347 28 4524
45 0 166 0 2.896575 0 19.000000 112.595238 27.711340 104.143190 0.260705 45 31.496679 0.173927 18 2688
2 220 0 6.666502 0 2.000000 115.902789 47.226804 116.273541 0.547525 45 49.727069 0.404999 31 4581
5 244 1 9.545598 0 2.000000 39.440753 54.030928 108.363552 0.612014 45 58.974828 0.501518 30 5241
46 0 137 0 3.198929 0 2.000000 112.141280 29.443299 104.377814 0.219614 46 28.485365 0.118862 22 2856
2 220 0 6.879417 0 4.799302 116.274114 48.463918 116.344548 0.635785 46 50.471333 0.494902 27 4701
5 249 0 9.542833 0 2.000000 43.623788 49.731959 108.522496 0.475613 46 63.958404 0.440578 22 4824
47 0 190 0 3.443748 0 2.000000 112.118545 29.701031 104.412209 0.198849 47 33.384803 0.125817 20 2881
2 220 1 6.865911 0 4.982101 116.241586 48.979381 116.344167 0.525056 47 49.955392 0.365671 31 4751
5 255 0 9.344431 0 2.000000 47.632850 51.072165 108.368385 0.507265 47 60.515020 0.429648 29 4954
48 0 147 0 2.769981 0 2.731019 111.972274 27.134021 103.822645 0.299242 48 26.973223 0.174721 19 2632
2 220 0 6.701579 0 6.979972 116.006896 47.927835 116.252156 0.494262 48 50.181597 0.349076 30 4649
5 249 0 9.614925 0 2.000000 51.390749 51.536082 108.491702 0.488511 48 61.484934 0.411250 29 4999
49 0 145 0 2.966330 0 17.835591 112.446328 31.731959 103.895819 0.332995 49 29.037876 0.179748 25 3078
2 220 0 6.652123 0 6.734334 116.064747 47.268041 116.322570 0.591347 49 49.599545 0.449817 32 4585
5 254 0 9.402662 0 4.912973 55.509206 53.092784 108.475138 0.485509 49 58.506247 0.365199 29 5150

183 rows × 14 columns