Skip to content

Commit

Permalink
First commit
Browse files Browse the repository at this point in the history
  • Loading branch information
SebastienTs committed Dec 27, 2019
1 parent 1728e0f commit 76b5288
Show file tree
Hide file tree
Showing 4 changed files with 288 additions and 0 deletions.
64 changes: 64 additions & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
FROM python:3.6.9-stretch

# ---------------------------------------------------------------------------------------------------------------------
# Install Java
RUN apt-get update && apt-get install openjdk-8-jdk -y && apt-get clean

# ---------------------------------------------------------------------------------------------------------------------
# Install Cytomine python client
RUN git clone https://github.com/cytomine-uliege/Cytomine-python-client.git && \
cd /Cytomine-python-client && git checkout tags/v2.3.0.poc.1 && pip install . && \
rm -r /Cytomine-python-client

# ---------------------------------------------------------------------------------------------------------------------
# Install Neubias-W5-Utilities (annotation exporter, compute metrics, helpers,...)
RUN apt-get update && apt-get install libgeos-dev -y && apt-get clean
RUN git clone https://github.com/Neubias-WG5/neubiaswg5-utilities.git && \
cd /neubiaswg5-utilities/ && git checkout tags/v0.8.8 && pip install .

# install utilities binaries
RUN chmod +x /neubiaswg5-utilities/bin/*
RUN cp /neubiaswg5-utilities/bin/* /usr/bin/

# cleaning
RUN rm -r /neubiaswg5-utilities

# ---------------------------------------------------------------------------------------------------------------------
# Install FIJI
# Install virtual X server
RUN apt-get update && apt-get install -y unzip xvfb libx11-dev libxtst-dev libxrender-dev

# Install Fiji.
RUN wget https://downloads.imagej.net/fiji/Life-Line/fiji-linux64-20170530.zip
RUN unzip fiji-linux64-20170530.zip
RUN mv Fiji.app/ fiji

# create a sym-link with the name jars/ij.jar that is pointing to the current version jars/ij-1.nm.jar
RUN cd /fiji/jars && ln -s $(ls ij-1.*.jar) ij.jar

# Add fiji to the PATH
ENV PATH $PATH:/fiji

RUN mkdir -p /fiji/data

# Clean up
RUN rm fiji-linux64-20170530.zip

# ---------------------------------------------------------------------------------------------------------------------
# ImageJ plugin
# install FeatureJ
RUN cd /fiji/plugins && \
wget -O imagescience.jar \
https://imagescience.org/meijering/software/download/imagescience.jar

RUN cd /fiji/plugins && \
wget -O FeatureJ_.jar \
https://imagescience.org/meijering/software/download/FeatureJ_.jar

# ---------------------------------------------------------------------------------------------------------------------
# add the local files
ADD LapClosetPartTracker.ijm /fiji/macros/macro.ijm
ADD wrapper.py /app/wrapper.py

# set the entrypoint
ENTRYPOINT ["python", "/app/wrapper.py"]
97 changes: 97 additions & 0 deletions LapClosetPartTracker.ijm
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
// Author: Sébastien Tosi (IRB Barcelona)
// Contact: [email protected]
// Version: 1.0
// Date: 27/12/2019

// Path to input image and results
inputDir = "C:\\Users\\Seb\\Desktop\\in";
outputDir = "C:\\Users\\Seb\\Desktop\\out";

// Parameters for Cytopacq time-lapse
LapRad = 9;
Thr = 0.05;

// Read arguments from command line
arg = getArgument();
parts = split(arg, ",");
for(i=0; i<parts.length; i++)
{
nameAndValue = split(parts[i], "=");
if (indexOf(nameAndValue[0], "input")>-1) inputDir=nameAndValue[1];
if (indexOf(nameAndValue[0], "output")>-1) outputDir=nameAndValue[1];
if (indexOf(nameAndValue[0], "LapRad")>-1) LapRad=nameAndValue[1];
if (indexOf(nameAndValue[0], "Thr")>-1) Thr=nameAndValue[1];
}

images = getFileList(inputDir);
for(img=0; img<images.length; img++)
{

setBatchMode(true);

// Open image
FileName = images[img];
open(inputDir+File.separator+FileName);

// Workflow
run("FeatureJ Laplacian", "compute smoothing="+d2s(LapRad,0));
FilterID = getImageID();
for(i=0;i<nSlices;i++)
{
selectImage(FilterID);
setSlice(i+1);
run("Find Maxima...", "noise="+d2s(Thr,3)+" output=List exclude light");
NewX = newArray(nResults);
NewY = newArray(nResults);
for(j=0;j<nResults;j++)
{
NewX[j] = getResult("X",j);
NewY[j] = getResult("Y",j);
}
if(i==0)
{
newImage("Mask", "16-bit black", getWidth(), getHeight(), nSlices);
MaskID = getImageID();
NObjs = lengthOf(NewX);
for(j=0;j<lengthOf(NewX);j++)setPixel(NewX[j],NewY[j],j+1);
LastX = NewX;
LastY = NewY;
}
else
{
selectImage(MaskID);
setSlice(i+1);
LastX_buf = newArray(NObjs);
LastY_buf = newArray(NObjs);
for(j=0;j<NObjs;j++)
{
MinDst2 = 1/0;
Mink = 0;
for(k=0;k<lengthOf(NewX);k++)
{
Dst2 = (pow(NewX[k]-LastX[j],2)+pow(NewY[k]-LastY[j],2));
if(Dst2<MinDst2)
{
MinDst2 = Dst2;
Mink = k;
}
}
setPixel(NewX[Mink],NewY[Mink],j);
LastX_buf[j] = NewX[Mink];
LastY_buf[j] = NewY[Mink];
}
LastX = LastX_buf;
LastY = LastY_buf;
}
}

// Save label mask
selectImage(MaskID);
//run("Bio-Formats Exporter", "save="+outputDir+File.separator+FileName+" compression=Uncompressed");
save(outputDir+File.separator+FileName);

run("Close All");

}

setBatchMode("exit & display");
82 changes: 82 additions & 0 deletions descriptor.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
{
"name": "PartTracking-ImageJ",
"container-image": {
"image": "neubiaswg5/w_parttracking-imagej",
"type": "singularity"
},
"schema-version": "cytomine-0.1",
"description": "Particle tracking based on linking closest intensity minima detected from LoG filtered time-lapse.",
"command-line": "python wrapper.py CYTOMINE_HOST CYTOMINE_PUBLIC_KEY CYTOMINE_PRIVATE_KEY CYTOMINE_ID_PROJECT CYTOMINE_ID_SOFTWARE LAPRAD THR",
"inputs": [
{
"id": "cytomine_host",
"value-key": "@ID",
"command-line-flag": "--@id",
"name": "Cytomine host",
"description": "Cytomine server hostname",
"type": "String",
"optional": false,
"set-by-server": true
},
{
"id": "cytomine_public_key",
"value-key": "@ID",
"command-line-flag": "--@id",
"name": "Cytomine public key",
"description": "Cytomine public key",
"type": "String",
"optional": false,
"set-by-server": true
},
{
"id": "cytomine_private_key",
"value-key": "@ID",
"command-line-flag": "--@id",
"name": "Cytomine private key",
"description": "Cytomine private key",
"type": "String",
"optional": false,
"set-by-server": true
},
{
"id": "cytomine_id_project",
"value-key": "@ID",
"command-line-flag": "--@id",
"name": "Cytomine project id",
"description": "Cytomine project id",
"type": "String",
"optional": false,
"set-by-server": true
},
{
"id": "cytomine_id_software",
"value-key": "@ID",
"command-line-flag": "--@id",
"name": "Cytomine software id",
"description": "Cytomine software id",
"type": "String",
"optional": false,
"set-by-server": true
},
{
"id": "laprad",
"value-key": "@ID",
"command-line-flag": "--@id",
"name": "LoG Radius",
"description": "Radius for the LoG filter",
"type": "Number",
"default-value": 9,
"optional": true
},
{
"id": "thr",
"value-key": "@ID",
"command-line-flag": "--@id",
"name": "Threshold",
"description": "Particle detection threshold",
"type": "Number",
"default-value": 0.05,
"optional": true
}
]
}
45 changes: 45 additions & 0 deletions wrapper.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
import sys
from cytomine.models import Job
from subprocess import call
from neubiaswg5 import CLASS_PRTTRK
from neubiaswg5.helpers import NeubiasJob, prepare_data, upload_data, upload_metrics


def main(argv):
with NeubiasJob.from_cli(argv) as nj:
problem_cls = CLASS_PRTTRK
is_2d = True

nj.job.update(status=Job.RUNNING, progress=0, statusComment="Initialisation...")
in_images, gt_images, in_path, gt_path, out_path, tmp_path = prepare_data(problem_cls, nj, is_2d=is_2d, **nj.flags)

# 2. Call the image analysis workflow
nj.job.update(progress=25, statusComment="Launching workflow...")
command = "/usr/bin/xvfb-run ./ImageJ-linux64 -macro macro.ijm " \
"\"input={}, output={}, laprad={}, thr={}\" -batch".format(
in_path, out_path, nj.parameters.laprad, nj.parameters.thr)

return_code = call(command, shell=True, cwd="/fiji") # waits for the subprocess to return

if return_code != 0:
err_desc = "Failed to execute the ImageJ macro (return code: {})".format(return_code)
nj.job.update(progress=100, statusComment=err_desc)
raise ValueError(err_desc)

# 4. Create and upload annotations
nj.job.update(progress=70, statusComment="Uploading extracted annotation...")
upload_data(problem_cls, nj, in_images, out_path, **nj.flags, is_2d=is_2d, monitor_params={
"start": 70, "end": 90, "period": 0.1
})

# 5. Compute and upload the metrics
nj.job.update(progress=90, statusComment="Computing and uploading metrics (if necessary)...")
upload_metrics(problem_cls, nj, in_images, gt_path, out_path, tmp_path, **nj.flags)

# 6. End the job
nj.job.update(status=Job.TERMINATED, progress=100, statusComment="Finished.")


if __name__ == "__main__":
main(sys.argv[1:])

0 comments on commit 76b5288

Please sign in to comment.