Skip to content

Commit 76b5288

Browse files
committed
First commit
1 parent 1728e0f commit 76b5288

File tree

4 files changed

+288
-0
lines changed

4 files changed

+288
-0
lines changed

Dockerfile

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
FROM python:3.6.9-stretch
2+
3+
# ---------------------------------------------------------------------------------------------------------------------
4+
# Install Java
5+
RUN apt-get update && apt-get install openjdk-8-jdk -y && apt-get clean
6+
7+
# ---------------------------------------------------------------------------------------------------------------------
8+
# Install Cytomine python client
9+
RUN git clone https://github.com/cytomine-uliege/Cytomine-python-client.git && \
10+
cd /Cytomine-python-client && git checkout tags/v2.3.0.poc.1 && pip install . && \
11+
rm -r /Cytomine-python-client
12+
13+
# ---------------------------------------------------------------------------------------------------------------------
14+
# Install Neubias-W5-Utilities (annotation exporter, compute metrics, helpers,...)
15+
RUN apt-get update && apt-get install libgeos-dev -y && apt-get clean
16+
RUN git clone https://github.com/Neubias-WG5/neubiaswg5-utilities.git && \
17+
cd /neubiaswg5-utilities/ && git checkout tags/v0.8.8 && pip install .
18+
19+
# install utilities binaries
20+
RUN chmod +x /neubiaswg5-utilities/bin/*
21+
RUN cp /neubiaswg5-utilities/bin/* /usr/bin/
22+
23+
# cleaning
24+
RUN rm -r /neubiaswg5-utilities
25+
26+
# ---------------------------------------------------------------------------------------------------------------------
27+
# Install FIJI
28+
# Install virtual X server
29+
RUN apt-get update && apt-get install -y unzip xvfb libx11-dev libxtst-dev libxrender-dev
30+
31+
# Install Fiji.
32+
RUN wget https://downloads.imagej.net/fiji/Life-Line/fiji-linux64-20170530.zip
33+
RUN unzip fiji-linux64-20170530.zip
34+
RUN mv Fiji.app/ fiji
35+
36+
# create a sym-link with the name jars/ij.jar that is pointing to the current version jars/ij-1.nm.jar
37+
RUN cd /fiji/jars && ln -s $(ls ij-1.*.jar) ij.jar
38+
39+
# Add fiji to the PATH
40+
ENV PATH $PATH:/fiji
41+
42+
RUN mkdir -p /fiji/data
43+
44+
# Clean up
45+
RUN rm fiji-linux64-20170530.zip
46+
47+
# ---------------------------------------------------------------------------------------------------------------------
48+
# ImageJ plugin
49+
# install FeatureJ
50+
RUN cd /fiji/plugins && \
51+
wget -O imagescience.jar \
52+
https://imagescience.org/meijering/software/download/imagescience.jar
53+
54+
RUN cd /fiji/plugins && \
55+
wget -O FeatureJ_.jar \
56+
https://imagescience.org/meijering/software/download/FeatureJ_.jar
57+
58+
# ---------------------------------------------------------------------------------------------------------------------
59+
# add the local files
60+
ADD LapClosetPartTracker.ijm /fiji/macros/macro.ijm
61+
ADD wrapper.py /app/wrapper.py
62+
63+
# set the entrypoint
64+
ENTRYPOINT ["python", "/app/wrapper.py"]

LapClosetPartTracker.ijm

Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
// Author: Sébastien Tosi (IRB Barcelona)
2+
// Contact: [email protected]
3+
// Version: 1.0
4+
// Date: 27/12/2019
5+
6+
// Path to input image and results
7+
inputDir = "C:\\Users\\Seb\\Desktop\\in";
8+
outputDir = "C:\\Users\\Seb\\Desktop\\out";
9+
10+
// Parameters for Cytopacq time-lapse
11+
LapRad = 9;
12+
Thr = 0.05;
13+
14+
// Read arguments from command line
15+
arg = getArgument();
16+
parts = split(arg, ",");
17+
for(i=0; i<parts.length; i++)
18+
{
19+
nameAndValue = split(parts[i], "=");
20+
if (indexOf(nameAndValue[0], "input")>-1) inputDir=nameAndValue[1];
21+
if (indexOf(nameAndValue[0], "output")>-1) outputDir=nameAndValue[1];
22+
if (indexOf(nameAndValue[0], "LapRad")>-1) LapRad=nameAndValue[1];
23+
if (indexOf(nameAndValue[0], "Thr")>-1) Thr=nameAndValue[1];
24+
}
25+
26+
images = getFileList(inputDir);
27+
for(img=0; img<images.length; img++)
28+
{
29+
30+
setBatchMode(true);
31+
32+
// Open image
33+
FileName = images[img];
34+
open(inputDir+File.separator+FileName);
35+
36+
// Workflow
37+
run("FeatureJ Laplacian", "compute smoothing="+d2s(LapRad,0));
38+
FilterID = getImageID();
39+
for(i=0;i<nSlices;i++)
40+
{
41+
selectImage(FilterID);
42+
setSlice(i+1);
43+
run("Find Maxima...", "noise="+d2s(Thr,3)+" output=List exclude light");
44+
NewX = newArray(nResults);
45+
NewY = newArray(nResults);
46+
for(j=0;j<nResults;j++)
47+
{
48+
NewX[j] = getResult("X",j);
49+
NewY[j] = getResult("Y",j);
50+
}
51+
if(i==0)
52+
{
53+
newImage("Mask", "16-bit black", getWidth(), getHeight(), nSlices);
54+
MaskID = getImageID();
55+
NObjs = lengthOf(NewX);
56+
for(j=0;j<lengthOf(NewX);j++)setPixel(NewX[j],NewY[j],j+1);
57+
LastX = NewX;
58+
LastY = NewY;
59+
}
60+
else
61+
{
62+
selectImage(MaskID);
63+
setSlice(i+1);
64+
LastX_buf = newArray(NObjs);
65+
LastY_buf = newArray(NObjs);
66+
for(j=0;j<NObjs;j++)
67+
{
68+
MinDst2 = 1/0;
69+
Mink = 0;
70+
for(k=0;k<lengthOf(NewX);k++)
71+
{
72+
Dst2 = (pow(NewX[k]-LastX[j],2)+pow(NewY[k]-LastY[j],2));
73+
if(Dst2<MinDst2)
74+
{
75+
MinDst2 = Dst2;
76+
Mink = k;
77+
}
78+
}
79+
setPixel(NewX[Mink],NewY[Mink],j);
80+
LastX_buf[j] = NewX[Mink];
81+
LastY_buf[j] = NewY[Mink];
82+
}
83+
LastX = LastX_buf;
84+
LastY = LastY_buf;
85+
}
86+
}
87+
88+
// Save label mask
89+
selectImage(MaskID);
90+
//run("Bio-Formats Exporter", "save="+outputDir+File.separator+FileName+" compression=Uncompressed");
91+
save(outputDir+File.separator+FileName);
92+
93+
run("Close All");
94+
95+
}
96+
97+
setBatchMode("exit & display");

descriptor.json

Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
{
2+
"name": "PartTracking-ImageJ",
3+
"container-image": {
4+
"image": "neubiaswg5/w_parttracking-imagej",
5+
"type": "singularity"
6+
},
7+
"schema-version": "cytomine-0.1",
8+
"description": "Particle tracking based on linking closest intensity minima detected from LoG filtered time-lapse.",
9+
"command-line": "python wrapper.py CYTOMINE_HOST CYTOMINE_PUBLIC_KEY CYTOMINE_PRIVATE_KEY CYTOMINE_ID_PROJECT CYTOMINE_ID_SOFTWARE LAPRAD THR",
10+
"inputs": [
11+
{
12+
"id": "cytomine_host",
13+
"value-key": "@ID",
14+
"command-line-flag": "--@id",
15+
"name": "Cytomine host",
16+
"description": "Cytomine server hostname",
17+
"type": "String",
18+
"optional": false,
19+
"set-by-server": true
20+
},
21+
{
22+
"id": "cytomine_public_key",
23+
"value-key": "@ID",
24+
"command-line-flag": "--@id",
25+
"name": "Cytomine public key",
26+
"description": "Cytomine public key",
27+
"type": "String",
28+
"optional": false,
29+
"set-by-server": true
30+
},
31+
{
32+
"id": "cytomine_private_key",
33+
"value-key": "@ID",
34+
"command-line-flag": "--@id",
35+
"name": "Cytomine private key",
36+
"description": "Cytomine private key",
37+
"type": "String",
38+
"optional": false,
39+
"set-by-server": true
40+
},
41+
{
42+
"id": "cytomine_id_project",
43+
"value-key": "@ID",
44+
"command-line-flag": "--@id",
45+
"name": "Cytomine project id",
46+
"description": "Cytomine project id",
47+
"type": "String",
48+
"optional": false,
49+
"set-by-server": true
50+
},
51+
{
52+
"id": "cytomine_id_software",
53+
"value-key": "@ID",
54+
"command-line-flag": "--@id",
55+
"name": "Cytomine software id",
56+
"description": "Cytomine software id",
57+
"type": "String",
58+
"optional": false,
59+
"set-by-server": true
60+
},
61+
{
62+
"id": "laprad",
63+
"value-key": "@ID",
64+
"command-line-flag": "--@id",
65+
"name": "LoG Radius",
66+
"description": "Radius for the LoG filter",
67+
"type": "Number",
68+
"default-value": 9,
69+
"optional": true
70+
},
71+
{
72+
"id": "thr",
73+
"value-key": "@ID",
74+
"command-line-flag": "--@id",
75+
"name": "Threshold",
76+
"description": "Particle detection threshold",
77+
"type": "Number",
78+
"default-value": 0.05,
79+
"optional": true
80+
}
81+
]
82+
}

wrapper.py

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
import sys
2+
from cytomine.models import Job
3+
from subprocess import call
4+
from neubiaswg5 import CLASS_PRTTRK
5+
from neubiaswg5.helpers import NeubiasJob, prepare_data, upload_data, upload_metrics
6+
7+
8+
def main(argv):
9+
with NeubiasJob.from_cli(argv) as nj:
10+
problem_cls = CLASS_PRTTRK
11+
is_2d = True
12+
13+
nj.job.update(status=Job.RUNNING, progress=0, statusComment="Initialisation...")
14+
in_images, gt_images, in_path, gt_path, out_path, tmp_path = prepare_data(problem_cls, nj, is_2d=is_2d, **nj.flags)
15+
16+
# 2. Call the image analysis workflow
17+
nj.job.update(progress=25, statusComment="Launching workflow...")
18+
command = "/usr/bin/xvfb-run ./ImageJ-linux64 -macro macro.ijm " \
19+
"\"input={}, output={}, laprad={}, thr={}\" -batch".format(
20+
in_path, out_path, nj.parameters.laprad, nj.parameters.thr)
21+
22+
return_code = call(command, shell=True, cwd="/fiji") # waits for the subprocess to return
23+
24+
if return_code != 0:
25+
err_desc = "Failed to execute the ImageJ macro (return code: {})".format(return_code)
26+
nj.job.update(progress=100, statusComment=err_desc)
27+
raise ValueError(err_desc)
28+
29+
# 4. Create and upload annotations
30+
nj.job.update(progress=70, statusComment="Uploading extracted annotation...")
31+
upload_data(problem_cls, nj, in_images, out_path, **nj.flags, is_2d=is_2d, monitor_params={
32+
"start": 70, "end": 90, "period": 0.1
33+
})
34+
35+
# 5. Compute and upload the metrics
36+
nj.job.update(progress=90, statusComment="Computing and uploading metrics (if necessary)...")
37+
upload_metrics(problem_cls, nj, in_images, gt_path, out_path, tmp_path, **nj.flags)
38+
39+
# 6. End the job
40+
nj.job.update(status=Job.TERMINATED, progress=100, statusComment="Finished.")
41+
42+
43+
if __name__ == "__main__":
44+
main(sys.argv[1:])
45+

0 commit comments

Comments
 (0)