Skip to content

Commit 87d409c

Browse files
committed
[feat] generalize methods to list
1 parent 49a17f8 commit 87d409c

File tree

5 files changed

+181
-45
lines changed

5 files changed

+181
-45
lines changed

README.md

Lines changed: 32 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,39 @@
77
## Installation
88
To install the module:
99
```
10+
git clone https://github.com/FastTrackOrg/FastAnalysis.git
11+
cd FastAnalysis
1012
pip install fastanalysis
1113
```
1214

1315
## Development
14-
The project is under active development and do not have public API documentation, a more or less complete API documentation can be generated using Sphinx.
16+
The project is under active development and do not have public API documentation, a more or less complete API documentation can be generated using Sphinx.
17+
18+
## Documentation
19+
20+
### Retrieve data from a tracking.txt file
21+
A tracking.txt file can be loaded and several method are available to select objects and frames:
22+
```
23+
import fastanalysis as fa
24+
25+
tracking = fa.Load("tracking.txt")
26+
fa.isObjectsInFrame(0, 100) # Check if object with id 0 is in the 100th frame
27+
fa.isObjectsInFrame([0, 1], 100) # Check if object with id 0 and 1 is in the 100th frame
28+
a = tracking.getObjectsInFrames(0, 100) # Select data of the object with id 0 in the 100th frame
29+
b = tracking.getObjectsInFrames([0,1], [100,101]) # Select data of the object with id 0 and 1 in the 100th and 101th frames
30+
c = tracking.getObjects(0) # Select data of the object with id 0 for all the frames
31+
d = tracking.getObjects([0,1]) # Select data of the object with id 0 and 1 for all the frames
32+
e = tracking.getFrame(100) # Select data for all the objects in the 100th frame
33+
f = tracking.getFrame([100,101]) # Select data for all the objects in the 100th and 101th frames
34+
```
35+
36+
### Export data
37+
```
38+
import fastanalysis as fa
39+
40+
tracking = fa.Load("tracking.txt")
41+
keys = fa.keys() # List saved features
42+
fa.saved("output.xlsx", delimiter='\t', keys=["xHead", "yHead", "imageNumber", "id"], ids=None, indexes=None, format="excel") # Saved a list of features for all the frames and all the objects in an excel file.
43+
fa.saved("output.txt", delimiter='\t', keys=None, ids=None, indexes=None, format="excel") # Saved all thefeatures for all the frames and all the objects in an csv file.
44+
```
45+
Two format are supported: csv and excel.

fastanalysis/load.py

Lines changed: 77 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -38,53 +38,103 @@ def getObjectNumber(self):
3838
maxObj = len(set(self.tracking.id.values))
3939
return maxObj
4040

41-
def getObject(self, iD):
42-
"""Get the data for the object with id.
41+
def getObjects(self, ids):
42+
"""Get the data for the objects with ids.
4343
44-
:param iD: Id of the object.
45-
:type index: int
46-
:return: Data for the object id.
44+
:param iD: Id or list of ids of objects.
45+
:type index: list | int
46+
:return: Data for the objects with ids.
4747
:rtype: DataFrame
4848
"""
49-
objectData = self.tracking[self.tracking.id == iD]
49+
if isinstance(ids, list):
50+
objectData = self.tracking[self.tracking.id.isin(ids)]
51+
else:
52+
objectData = self.tracking[self.tracking.id == ids]
5053
return objectData
5154

52-
def getFrame(self, index):
53-
"""Get the data for the image number index.
55+
def getFrames(self, indexes):
56+
"""Get the data for the images with number indexes.
5457
5558
:param index: Index of the image.
56-
:type index: int
57-
:return: Data for the image index.
59+
:type index: list | int
60+
:return: Data for the images with indexes.
5861
:rtype: DataFrame
5962
"""
60-
objectData = self.tracking[self.tracking.imageNumber == index]
63+
if isinstance(indexes, list):
64+
objectData = self.tracking[self.tracking.imageNumber.isin(indexes)]
65+
else:
66+
objectData = self.tracking[self.tracking.imageNumber == indexes]
6167
return objectData
6268

63-
def getObjectInFrame(self, iD, index):
64-
"""Get the data for an object id is in a frame index.
69+
def getObjectsInFrames(self, ids, indexes):
70+
"""Get the data for objects ids in frames indexes.
6571
66-
:param iD: [Id of the object.]
67-
:type iD: int
68-
:param index: Index of the image.
69-
:type index: int
70-
:return: True if object id in frame index.
71-
:rtype: bool
72+
:param ids: Ids of objects.
73+
:type ids: list | int
74+
:param index: Indexex of images.
75+
:type index: list | int
76+
:return: Data for objects ids in frames indexes.
77+
:rtype: Dataframe
7278
"""
73-
data = self.tracking[(self.tracking.imageNumber == index)&(self.tracking.id == iD)]
79+
if not isinstance(indexes, list):
80+
indexes = [indexes]
81+
if not isinstance(ids, list):
82+
ids = [ids]
83+
data = self.tracking[(self.tracking.imageNumber.isin(indexes))&(self.tracking.id.isin(ids))]
7484
return data
7585

76-
def isObjectInFrame(self, iD, index):
86+
def isObjectsInFrame(self, ids, index):
7787
"""Check if an object id is in a frame index.
7888
79-
:param iD: Id of the object.
80-
:type index: int
89+
:param ids: Ids of objects.
90+
:type ids: list | int
8191
:param index: Index of the image.
8292
:type index: int
8393
:return: True if object id in frame index.
8494
:rtype: bool
8595
"""
86-
data = self.tracking[(self.tracking.imageNumber == index)&(self.tracking.id == iD)]
87-
if data.empty:
88-
return False
96+
isIn = []
97+
if isinstance(ids, list):
98+
for iD in ids:
99+
data = self.tracking[(self.tracking.imageNumber == index)&(self.tracking.id == iD)]
100+
if data.empty:
101+
isIn.append(False)
102+
else:
103+
isIn.append(True)
104+
return isIn
89105
else:
90-
return True
106+
data = self.tracking[(self.tracking.imageNumber == index)&(self.tracking.id == ids)]
107+
if data.empty:
108+
return False
109+
else:
110+
return True
111+
112+
def saved(self, path, delimiter='\t', keys=None, ids=None, indexes=None, fmt="csv"):
113+
"""Check if an object id is in a frame index.
114+
115+
:param path: Path to the saved file.
116+
:type path: str
117+
:param keys: List of features.
118+
:type keys: list
119+
:param ids: List of ids of object.
120+
:type ids: list
121+
:param indexes: List of indexes of images.
122+
:type indexes: list
123+
"""
124+
tracking = self.tracking
125+
if indexes:
126+
tracking = tracking[tracking.imageNumber.isin(indexes)]
127+
128+
if ids:
129+
tracking = tracking[tracking.id.isin(ids)]
130+
131+
if keys:
132+
tracking = tracking[keys]
133+
134+
if fmt == "csv":
135+
tracking.to_csv(path, sep=delimiter, index=False)
136+
elif fmt == "excel":
137+
tracking.to_excel(path, index=False)
138+
139+
140+

fastanalysis/tests/test_load.py

Lines changed: 69 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -20,35 +20,88 @@ def test_object_number():
2020
objectNumber = load.Load("tests/tracking.txt").getObjectNumber()
2121
assert objectNumber == 207
2222

23-
def test_get_object():
23+
def test_get_objects():
2424
"""Test get the data for an object"""
2525
reference = pandas.read_csv("tests/tracking.txt", sep='\t')
26-
tracking = load.Load("tests/tracking.txt").getObject(0)
26+
tracking = load.Load("tests/tracking.txt").getObjects(0)
2727
pandas.testing.assert_frame_equal(tracking, reference[reference.id==0])
28-
tracking = load.Load("tests/tracking.txt").getObject(1)
29-
pandas.testing.assert_frame_equal(tracking, reference[reference.id==1])
28+
tracking = load.Load("tests/tracking.txt").getObjects([0, 1])
29+
pandas.testing.assert_frame_equal(tracking, reference[(reference.id==1)|(reference.id==0)])
3030

31-
def test_get_frame():
31+
def test_get_frames():
3232
"""Test get the data for a frame"""
3333
reference = pandas.read_csv("tests/tracking.txt", sep='\t')
34-
tracking = load.Load("tests/tracking.txt").getFrame(10)
34+
tracking = load.Load("tests/tracking.txt").getFrames(10)
3535
pandas.testing.assert_frame_equal(tracking, reference[reference.imageNumber==10])
36-
tracking = load.Load("tests/tracking.txt").getFrame(1)
37-
pandas.testing.assert_frame_equal(tracking, reference[reference.imageNumber==1])
36+
tracking = load.Load("tests/tracking.txt").getFrames([1, 10])
37+
pandas.testing.assert_frame_equal(tracking, reference[(reference.imageNumber==1)|(reference.imageNumber==10)])
3838

39-
def test_get_object_in_frame():
39+
def test_get_objects_in_frames():
4040
"""Test get the data for an frame"""
4141
reference = pandas.read_csv("tests/tracking.txt", sep='\t')
42-
tracking = load.Load("tests/tracking.txt").getObjectInFrame(0, 200)
42+
tracking = load.Load("tests/tracking.txt").getObjectsInFrames(0, 200)
4343
pandas.testing.assert_frame_equal(tracking, reference[(reference.imageNumber==200)&(reference.id==0)])
44-
tracking = load.Load("tests/tracking.txt").getObjectInFrame(1, 100)
45-
pandas.testing.assert_frame_equal(tracking, reference[(reference.imageNumber==100)&(reference.id==1)])
44+
tracking = load.Load("tests/tracking.txt").getObjectsInFrames([1, 2], [0, 100])
45+
pandas.testing.assert_frame_equal(tracking, reference[((reference.imageNumber==100)|(reference.imageNumber==0))&((reference.id==1)|(reference.id==2))])
4646

47-
def test_is_object_in_frame():
48-
"""Test get the data for an frame"""
47+
def test_is_objects_in_frame():
48+
"""Test check if objects in frame"""
4949
reference = pandas.read_csv("tests/tracking.txt", sep='\t')
50-
tracking = load.Load("tests/tracking.txt").isObjectInFrame(0, 0)
50+
tracking = load.Load("tests/tracking.txt").isObjectsInFrame(0, 0)
5151
assert tracking
52-
tracking = load.Load("tests/tracking.txt").isObjectInFrame(0, 1500)
52+
tracking = load.Load("tests/tracking.txt").isObjectsInFrame(0, 1500)
5353
assert not tracking
5454

55+
def test_export_csv():
56+
"""Test set the data in a file"""
57+
reference = pandas.read_csv("tests/tracking.txt", sep='\t')
58+
tracking = load.Load("tests/tracking.txt")
59+
60+
tracking.saved("tests/test.csv")
61+
test = pandas.read_csv("tests/test.csv", sep='\t')
62+
pandas.testing.assert_frame_equal(reference, test)
63+
64+
tracking.saved("tests/test.csv", delimiter=',')
65+
test = pandas.read_csv("tests/test.csv", sep=',')
66+
pandas.testing.assert_frame_equal(reference, test)
67+
68+
tracking.saved("tests/test.csv", keys=["imageNumber"])
69+
test = pandas.read_csv("tests/test.csv", sep='\t')
70+
pandas.testing.assert_frame_equal(reference[["imageNumber"]], test)
71+
72+
tracking.saved("tests/test.csv", indexes=[1])
73+
test = pandas.read_csv("tests/test.csv", sep='\t')
74+
pandas.testing.assert_frame_equal(reference[reference.imageNumber==1].reset_index(drop=True), test)
75+
76+
tracking.saved("tests/test.csv", ids=[0])
77+
test = pandas.read_csv("tests/test.csv", sep='\t')
78+
pandas.testing.assert_frame_equal(reference[reference.id==0].reset_index(drop=True), test)
79+
80+
tracking.saved("tests/test.csv", ids=[0], indexes=[0])
81+
test = pandas.read_csv("tests/test.csv", sep='\t')
82+
pandas.testing.assert_frame_equal(reference[(reference.id==0) & (reference.imageNumber==0)].reset_index(drop=True), test)
83+
84+
def test_export_excel():
85+
"""Test set the data in an excel file"""
86+
reference = pandas.read_csv("tests/tracking.txt", sep='\t')
87+
tracking = load.Load("tests/tracking.txt")
88+
89+
tracking.saved("tests/test.xlsx", fmt="excel")
90+
test = pandas.read_excel("tests/test.xlsx")
91+
pandas.testing.assert_frame_equal(reference, test)
92+
93+
tracking.saved("tests/test.xlsx", keys=["imageNumber"], fmt="excel")
94+
test = pandas.read_excel("tests/test.xlsx")
95+
pandas.testing.assert_frame_equal(reference[["imageNumber"]], test)
96+
97+
tracking.saved("tests/test.xlsx", indexes=[1], fmt="excel")
98+
test = pandas.read_excel("tests/test.xlsx")
99+
pandas.testing.assert_frame_equal(reference[reference.imageNumber==1].reset_index(drop=True), test)
100+
101+
tracking.saved("tests/test.xlsx", ids=[0], fmt="excel")
102+
test = pandas.read_excel("tests/test.xlsx")
103+
pandas.testing.assert_frame_equal(reference[reference.id==0].reset_index(drop=True), test)
104+
105+
tracking.saved("tests/test.xlsx", ids=[0], indexes=[0], fmt="excel")
106+
test = pandas.read_excel("tests/test.xlsx")
107+
pandas.testing.assert_frame_equal(reference[(reference.id==0) & (reference.imageNumber==0)].reset_index(drop=True), test)

requirements/conda.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1 +1,3 @@
11
pandas
2+
xlrd
3+
openpyxl

setup.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
description="A python library to open the tracking data from FastTrack the tracking software",
99
url="https://github.com/FastTrackOrg/FastAnalysis",
1010
packages=['fastanalysis'],
11-
install_requires=['pandas', 'numpy', 'matplotlib'],
11+
install_requires=['pandas', 'numpy', 'matplotlib', 'xlrd', 'openpyxl'],
1212
license='MIT',
1313
python_requires='>=3.6',
1414
zip_safe=False

0 commit comments

Comments
 (0)