README.md 6.35 KB
Newer Older
François  LAURENT's avatar
François LAURENT committed
1
# PlanarLarvae.jl
2

François  LAURENT's avatar
François LAURENT committed
3
4
[![Build Status](https://gitlab.pasteur.fr/Nyx/PlanarLarvae.jl/badges/main/pipeline.svg)](https://gitlab.pasteur.fr/Nyx/PlanarLarvae.jl/pipelines)
[![Coverage](https://gitlab.pasteur.fr/Nyx/PlanarLarvae.jl/badges/main/coverage.svg)](https://gitlab.pasteur.fr/Nyx/PlanarLarvae.jl/commits/main)
François  LAURENT's avatar
François LAURENT committed
5
6
[![License: MIT](https://img.shields.io/badge/license-MIT-blue.svg)](https://gitlab.pasteur.fr/nyx/planarlarvae.jl/-/blob/main/LICENSE)
[![Documentation](https://img.shields.io/badge/docs-main-9cf.svg)](http://nyx.pages.pasteur.fr/planarlarvae.jl/)
François  LAURENT's avatar
François LAURENT committed
7

8

François  LAURENT's avatar
François LAURENT committed
9
This package features reading utilities for *spine* and *outline* files
François  LAURENT's avatar
François LAURENT committed
10
11
12
generated by the [Choreography](https://github.com/Ichoran/choreography) (or *Chore.jar*) program,
for *table.csv* files generated by [FIMTrack](https://www.uni-muenster.de/Informatik.AGRisse/media/fim-media.html) v2,
and for *trx.mat* files generated by [JBM's automatic tagger](https://github.com/DecBayComp/Pipeline_action_analysis_t5_pasteur_janelia).
13

François  LAURENT's avatar
François LAURENT committed
14
It provides basic datatypes for 2D spine- and outline-based descriptions of the larva,
15
16
and similarly features basic functionalities for discrete behavior tags with, notably,
support for JSON label files.
17

François  LAURENT's avatar
François LAURENT committed
18
## Reading files
19

François  LAURENT's avatar
François LAURENT committed
20
21
22
23
24
Records are read from *spine*/*outline* files and *trx.mat* files as named tuples
stored for every timestamp.

Records are specified as pairs of a name and a record type.
Record types can be any of `Spine`, `Outline` and `BehaviorTags`.
25
For example:
26
27

```julia
François  LAURENT's avatar
François LAURENT committed
28
using PlanarLarvae, PlanarLarvae.Chore
François  LAURENT's avatar
François LAURENT committed
29
30
31
32
33
using LazyArtifacts

sample_files = joinpath(artifact"chore_sample_output", "chore_sample_output")
runs = read_chore_files((:spine=>Spine, :outline=>Outline), sample_files)
```
34
35
36
37
38

`read_chore_files` returns a dictionary of runs (actually a single run),
that itself is a dictionary of larva with IDs as keys and timeseries of states
as values:

François  LAURENT's avatar
François LAURENT committed
39
40
41
42
43
44
```@example
run, larvae = first(runs)
larva_id, track = first(larvae)
timestamp, spine_outline = first(track)
typeof(spine_outline)
```
45
46
47

Choreography files do not include behavior tags. These can be found in *trx.mat* files:

François  LAURENT's avatar
François LAURENT committed
48
```@example
François  LAURENT's avatar
François LAURENT committed
49
50
using PlanarLarvae.Trxmat

François  LAURENT's avatar
François LAURENT committed
51
runs = read_trxmat((:spine=>Spine, :outline=>Outline, :tags=>BehaviorTags), artifact"sample_trxmat_file")
François  LAURENT's avatar
François LAURENT committed
52

François  LAURENT's avatar
François LAURENT committed
53
54
larvastate = first(eachstate(runs))
show(larvastate.tags)
François  LAURENT's avatar
François LAURENT committed
55
56
```

François  LAURENT's avatar
François LAURENT committed
57
58
59
60
61
62
63
64
FIMTrack files do not include behavior tags either, and outlines are not stored.
They are reconstructed from the spine points and associated radii:

```@example
using PlanarLarvae.FIMTrack

sample_file = joinpath(artifact"sample_fimtrack_tables", "collision_sample_table.csv")

65
tracks = read_fimtrack((:spine=>Spine, :outline=>Outline), sample_file; framerate=30)
François  LAURENT's avatar
François LAURENT committed
66
67
68
69
70

example_track = tracks[1]
example_state = example_track[3.6]
```

François  LAURENT's avatar
François LAURENT committed
71
72
73
74
75
76
77
## Geometries

Spines and outlines are [Meshes.jl](https://github.com/JuliaGeometry/Meshes.jl) geometries,
`Chain` and `PolyArea` objects respectively.
As a consequence, the [Meshes.jl](https://github.com/JuliaGeometry/Meshes.jl) interface is leveraged:

```@example
78
79
80
81
82
using Meshes

myoutline = outline([56.375, 20.625, 56.375, 20.75, 56.375, 20.875, 56.375, 21.0, 56.375, 21.125, 56.5, 21.125, 56.5, 21.25, 56.5, 21.375, 56.625, 21.375, 56.625, 21.375, 56.75, 21.375, 56.875, 21.375, 56.875, 21.375, 57.0, 21.25, 57.0, 21.25, 57.0, 21.125, 57.125, 21.125, 57.125, 21.0, 57.125, 20.875, 57.25, 20.875, 57.25, 20.75, 57.25, 20.625, 57.25, 20.5, 57.25, 20.375, 57.375, 20.375, 57.375, 20.25, 57.375, 20.125, 57.375, 20.0, 57.5, 20.0, 57.5, 19.875, 57.5, 19.75, 57.5, 19.625, 57.5, 19.5, 57.5, 19.375, 57.625, 19.375, 57.625, 19.25, 57.625, 19.125, 57.625, 19.0, 57.625, 18.875, 57.625, 18.75, 57.5, 18.75, 57.5, 18.75, 57.375, 18.75, 57.375, 18.750, 57.25, 18.875, 57.25, 18.875, 57.125, 18.875, 57.125, 19.0, 57.0, 19.0, 57.0, 19.125, 57.0, 19.25, 56.875, 19.25, 56.875, 19.375, 56.75, 19.375, 56.75, 19.5, 56.75, 19.625, 56.625, 19.625, 56.625, 19.75, 56.625, 19.875, 56.625, 20.0, 56.5, 20.0, 56.5, 20.125, 56.5, 20.25, 56.5, 20.375, 56.5, 20.5])
```
```@example
83
Meshes.centroid(myoutline)
84
85
86
87
88
89
90
91
```
```@example
boundingbox(myoutline)
```
```@example
area(myoutline)
```
```@example
92
PlanarLarvae.centroid(myoutline) ∈ myoutline
93
94
```
etc.
François  LAURENT's avatar
François LAURENT committed
95

François  LAURENT's avatar
François LAURENT committed
96
`PlanarLarvae` defines its own `centroid` function, hence the necessary prefixing.
97
98
99
100
101
The two functions equal in the case of an outline.
However, if a spine is available in the representation of a larva state,
then `PlanarLarvae.centroid` returns the midpoint of the spine, which is a departure
from the geometric-only `Meshes.centroid`.

François  LAURENT's avatar
François LAURENT committed
102
103
104
105
106
107
## Behavior tags

Behavior tags are loaded as `BehaviorTags` objects that implement the `AbstractSet` interface.

A subset of the available behavior tags can be loaded from a `trx.mat` file passing an instanciated `BehaviorTags` as specification:
```@example
François  LAURENT's avatar
François LAURENT committed
108
read_trxmat((:tags=>BehaviorTags([:run, :cast, :hunch, :back, :roll]),), artifact"sample_trxmat_file");
François  LAURENT's avatar
François LAURENT committed
109
110
```

François  LAURENT's avatar
François LAURENT committed
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
## JSON files

Time series of behavior tags are stored in *json* files as in the following example, with parts of the file escaped using `[...]`:

```
{
  "metadata": {
    "id": "20140918_170215",
    "tracker": "t15",
    "genotype": "GMR_SS02113",
    "effector": "UAS_Chrimson_Venus_X_0070",
    "protocol": "r_LED100_30s2x15s30s#n#n#n@100",
    "date_time": "20140918_170215",
    "filename": "[...].outline"
  },
  "units": {
    "t": "s"
  },
  "labels": {
    "names": ["run","bend","stop","hunch","back","roll"],
    "colors": ["#000000","#ff0000","#00ff00","#0000ff","#00ffff","#ffff00"]
  },
  "dependencies": [
    {
      "filename": "[...].spine",
      "sha1": "d5ac8809357ee28b1d87ef030910c5517ef53231"
    },
    {
      "filename": "[...].outline",
      "sha1": "4aa067203bd6471f0dcdd21490731865e83e7447"
    }
  ],
  "data": [
    {
      "id": "2",
      "t": [9.389,9.468,[...]],
      "labels": [1,1,[...]]
    },
    [...]
  ]
}
```

The `data` array lists the different moving objects (larvae) with their `id` (as a string) and time series of timestamps (float array `t`) and associated labels (array `labels`).

Labels may be names (strings or arrays of strings) or encoded as indices in a global `labels/names` array, starting from index `1` (integers or arrays of integers).

The above format is inspired by the [WCON](https://github.com/openworm/tracker-commons/blob/master/discuss/Formats.md#json-as-a-candidate-format=) proposal.
Such a file can be made WCON-compliant prefixing occurences of `labels` and `dependencies` by `@`; in addition, `x` and `y` should be added to `units` and every objects in `data`.