How to simply compile a plugin (modified NeuronJ)?

Hi,

I’m trying to modify the NeuronJ plugin from @emeijering (https://imagescience.org/meijering/software/neuronj/, code is at https://github.com/imagescience/NeuronJ) to solve the issue I filed a while ago regarding the order of Next/Previous image opening with the keyboard shortcuts being botched on APFS-formatted drives (i.e. Macs running the last 2-3 versions of OSX). More on the issue here:
https://github.com/imagescience/NeuronJ/issues/2

Solving this is (likely) just adding a sorting step to the array listing the image file names in NeuronJ code, so I figured I could do it myself to streamline our workflow (people from our lab are doing quantification at home right now with the Covid lockdown…). I have downloaded the whole neuronJ repository as a zip, modified the NeuronJ_.java file to add the sorting step (import java.util.Arrays; at line 84 and Arrays.sort(NJ.workimages, String.CASE_INSENSITIVE_ORDER); at line 637).

Now my question is: what is a simple way to repackage the whole thing into an updated NeuronJ_.jar file to test it? Sorry for being such a noob but I know nothing about plugins (I’ve always used the Java API through ImageJ javascript). I remember trying a long time ago and spending hours with things like PATH and stuff so I figured I’d ask the pros here…

Thanks!

Hello Christophe -

Let me recommend the following low-overhead, old-school (but
possibly unpopular) method.

I am assuming some things:

You have successfully installed NeuronJ by copying NeuronJ_.jar
and imagescience.jar to your Fiji / ImageJ plugins folder and it
runs correctly.

You have javac and jar installed on your system.

You have the source file NeuronJ_.java, and you will only be
modifying this file.

First, as a nicety, extract the file plugins.config from NeuronJ_.jar,
or just use:

Plugins, "NeuronJ", NeuronJ_
Help>About Plugins, "NeuronJ...", NeuronJ_Website

Modify NeuronJ_.java as desired.

Compile it using javac:

javac -source 1.8 -target 1.8 -g -cp .:/<path_to_fiji_installation>/Fiji.app/jars/*:imagescience.jar NeuronJ_.java

The -source 1.8 -target 1.8 is because I am using java 9,
but ImageJ is java 8.

The cp is the important part. It sets the javac classpath to
use the ImageJ jars in your ImageJ installation, and also to
use imagescience.jar (which you won’t need to modify or
recompile unless you modify some of the imagescience
source files).

Run the javac command in a directory that has your modified
NeuronJ_.java file and the imagescience.jar file.

You should now have a bunch of class files (the same class files
that are in NeuronJ_.jar) in this directory, including NeuronJ_.class.

As a nicety, add plugins.config to this directory.

Now jar it all up running (in this same directory):

jar cfM NeuronJ_.jar *.class plugins.config

This creates NeuronJ_.jar containing the class files you just
compiled, and (as a nicety) plugins.config.

Copy NeuronJ_.jar to your Fiji / ImageJ plugins directory,
overwriting the original (and leave the original imagescience.jar
file in place in the plugins directory).

Restart Fiji / ImageJ to be able to launch your modified NeuronJ
plugin, Plugins > NeuronJ.

Thanks, mm

2 Likes

Hi, the above command results in a bunch of errors (100 exactly) suggesting that the compiler somehow needs to know about ImageJ but doesn’t. Any idea what I did incorrectly?

(base) NeuroCyto-CL1:NeuronJ christo$ javac -source 1.8 -target 1.8 -g -cp .:/Users/christo/Travail/Labo/Processing/ImageJ.app/plugins/jars/*:imagescience.jar NeuronJ_.java
NeuronJ_.java:1: error: package ij does not exist
import ij.IJ;
         ^
NeuronJ_.java:2: error: package ij does not exist
import ij.ImageJ;
         ^
NeuronJ_.java:3: error: package ij does not exist
import ij.Prefs;
         ^
NeuronJ_.java:4: error: package ij does not exist
import ij.ImagePlus;
         ^
NeuronJ_.java:5: error: package ij does not exist
import ij.ImageStack;
         ^
NeuronJ_.java:6: error: package ij does not exist
import ij.WindowManager;
         ^
NeuronJ_.java:7: error: package ij.gui does not exist
import ij.gui.GUI;
             ^
NeuronJ_.java:8: error: package ij.gui does not exist
import ij.gui.ImageCanvas;
             ^
NeuronJ_.java:9: error: package ij.gui does not exist
import ij.gui.ImageWindow;
             ^
NeuronJ_.java:10: error: package ij.gui does not exist
import ij.gui.PolygonRoi;
             ^
NeuronJ_.java:11: error: package ij.gui does not exist
import ij.gui.Roi;
             ^
NeuronJ_.java:12: error: package ij.gui does not exist
import ij.gui.Toolbar;
             ^
NeuronJ_.java:13: error: package ij.io does not exist
import ij.io.Opener;
            ^
NeuronJ_.java:14: error: package ij.io does not exist
import ij.io.RoiEncoder;
            ^
NeuronJ_.java:15: error: package ij.measure does not exist
import ij.measure.Calibration;
                 ^
NeuronJ_.java:16: error: package ij.plugin does not exist
import ij.plugin.BrowserLauncher;
                ^
NeuronJ_.java:17: error: package ij.plugin does not exist
import ij.plugin.PlugIn;
                ^
NeuronJ_.java:18: error: package ij.process does not exist
import ij.process.ByteProcessor;
                 ^
NeuronJ_.java:19: error: package ij.process does not exist
import ij.process.ColorProcessor;
                 ^
NeuronJ_.java:20: error: package ij.text does not exist
import ij.text.TextPanel;
              ^
NeuronJ_.java:21: error: package ij.text does not exist
import ij.text.TextWindow;
              ^
NeuronJ_.java:87: error: cannot find symbol
public final class NeuronJ_ implements PlugIn {
                                       ^
  symbol: class PlugIn
NeuronJ_.java:1140: error: cannot find symbol
final class TracingHandler extends Roi implements KeyListener, MouseListener, MouseMotionListener {
                                   ^
  symbol: class Roi
NeuronJ_.java:184: error: cannot find symbol
	static TextWindow grw = null;
	       ^
  symbol:   class TextWindow
  location: class NJ
NeuronJ_.java:185: error: cannot find symbol
	static TextWindow trw = null;
	       ^
  symbol:   class TextWindow
  location: class NJ
NeuronJ_.java:186: error: cannot find symbol
	static TextWindow vrw = null;
	       ^
  symbol:   class TextWindow
  location: class NJ
NeuronJ_.java:196: error: cannot find symbol
	static ImagePlus imageplus = null;
	       ^
  symbol:   class ImagePlus
  location: class NJ
NeuronJ_.java:205: error: cannot find symbol
	static void image(final ImagePlus imp) {
	                        ^
  symbol:   class ImagePlus
  location: class NJ
NeuronJ_.java:317: error: cannot find symbol
	static TextWindow logwin = null;
	       ^
  symbol:   class TextWindow
  location: class NJ
NeuronJ_.java:318: error: cannot find symbol
	static TextPanel logpan = null;
	       ^
  symbol:   class TextPanel
  location: class NJ
NeuronJ_.java:474: error: cannot find symbol
	private Toolbar previousToolbar;
	        ^
  symbol:   class Toolbar
  location: class TracingToolbar
NeuronJ_.java:475: error: cannot find symbol
	private ImagePlus imp;
	        ^
  symbol:   class ImagePlus
  location: class TracingToolbar
NeuronJ_.java:476: error: cannot find symbol
	private ImageWindow imw;
	        ^
  symbol:   class ImageWindow
  location: class TracingToolbar
NeuronJ_.java:1142: error: cannot find symbol
	private ImagePlus imp;
	        ^
  symbol:   class ImagePlus
  location: class TracingHandler
NeuronJ_.java:1143: error: cannot find symbol
	private ImageCanvas imc;
	        ^
  symbol:   class ImageCanvas
  location: class TracingHandler
NeuronJ_.java:1144: error: cannot find symbol
	private ImageWindow imw;
	        ^
  symbol:   class ImageWindow
  location: class TracingHandler
NeuronJ_.java:1145: error: cannot find symbol
	ByteProcessor ipgray;
	^
  symbol:   class ByteProcessor
  location: class TracingHandler
NeuronJ_.java:1179: error: cannot find symbol
	void attach(final ImagePlus impNew) {
	                  ^
  symbol:   class ImagePlus
  location: class TracingHandler
NeuronJ_.java:1307: error: cannot find symbol
	public ColorProcessor makeSnapshot(final boolean snapshotimage, final boolean snapshottracings) {
	       ^
  symbol:   class ColorProcessor
  location: class TracingHandler
NeuronJ_.java:4060: error: cannot find symbol
	void draw(final Graphics g, final ImageCanvas imc) {
	                                  ^
  symbol:   class ImageCanvas
  location: class Tracings
NeuronJ_.java:4137: error: cannot find symbol
	void values(final ByteProcessor bp, final Values values) {
	                  ^
  symbol:   class ByteProcessor
  location: class Tracing
NeuronJ_.java:4192: error: cannot find symbol
	void draw(final Graphics g, final ImageCanvas imc) {
	                                  ^
  symbol:   class ImageCanvas
  location: class Tracing
NeuronJ_.java:4296: error: cannot find symbol
	void values(final ByteProcessor bp, final Values values) {
	                  ^
  symbol:   class ByteProcessor
  location: class Segment
NeuronJ_.java:4316: error: cannot find symbol
	void draw(final Graphics g, final ImageCanvas imc, final Color color) {
	                                  ^
  symbol:   class ImageCanvas
  location: class Segment
NeuronJ_.java:3971: error: cannot find symbol
final class VectorField extends Roi implements KeyListener {
                                ^
  symbol: class Roi
NeuronJ_.java:3976: error: cannot find symbol
	VectorField(final ImagePlus imp, final float[][][] vf) {
	                  ^
  symbol:   class ImagePlus
  location: class VectorField
NeuronJ_.java:4632: error: cannot find symbol
	public float[][][] run(final ByteProcessor image, final boolean bright, final float scale) {
	                             ^
  symbol:   class ByteProcessor
  location: class Costs
NeuronJ_.java:103: error: cannot find symbol
	if (IJ.getVersion().compareTo(MINIJVERSION) < 0) {
	    ^
  symbol:   variable IJ
  location: class NeuronJ_
NeuronJ_.java:117: error: cannot find symbol
	if (IJ.getInstance() == null) {
	    ^
  symbol:   variable IJ
  location: class NeuronJ_
NeuronJ_.java:157: error: cannot find symbol
		log("Running on ImageJ version "+IJ.getVersion());
		                                 ^
  symbol:   variable IJ
  location: class NJ
NeuronJ_.java:161: error: cannot find symbol
		lasttool = Toolbar.getInstance().getToolId();
		           ^
  symbol:   variable Toolbar
  location: class NJ
NeuronJ_.java:162: error: cannot find symbol
		lastdoublebuffering = Prefs.doubleBuffer;
		                      ^
  symbol:   variable Prefs
  location: class NJ
NeuronJ_.java:163: error: cannot find symbol
		Prefs.doubleBuffer = true;
		^
  symbol:   variable Prefs
  location: class NJ
NeuronJ_.java:308: error: cannot find symbol
			logwin = new TextWindow(NAME+": Log",startupmsg,500,500);
			             ^
  symbol:   class TextWindow
  location: class NJ
NeuronJ_.java:322: error: cannot find symbol
		if (IJ.getInstance() == null) IJ.showMessage(NJ.NAME+": Error",message+".");
		    ^
  symbol:   variable IJ
  location: class NJ
NeuronJ_.java:322: error: cannot find symbol
		if (IJ.getInstance() == null) IJ.showMessage(NJ.NAME+": Error",message+".");
		                              ^
  symbol:   variable IJ
  location: class NJ
NeuronJ_.java:324: error: cannot find symbol
		IJ.showProgress(1.0);
		^
  symbol:   variable IJ
  location: class NJ
NeuronJ_.java:325: error: cannot find symbol
		IJ.showStatus("");
		^
  symbol:   variable IJ
  location: class NJ
NeuronJ_.java:330: error: cannot find symbol
	static void copyright() { IJ.showStatus(COPYRIGHT); }
	                          ^
  symbol:   variable IJ
  location: class NJ
NeuronJ_.java:334: error: cannot find symbol
		if (IJ.getInstance() == null) IJ.showMessage(NJ.NAME+": Note",message+".");
		    ^
  symbol:   variable IJ
  location: class NJ
NeuronJ_.java:334: error: cannot find symbol
		if (IJ.getInstance() == null) IJ.showMessage(NJ.NAME+": Note",message+".");
		                              ^
  symbol:   variable IJ
  location: class NJ
NeuronJ_.java:336: error: cannot find symbol
		IJ.showProgress(1.0);
		^
  symbol:   variable IJ
  location: class NJ
NeuronJ_.java:337: error: cannot find symbol
		IJ.showStatus("");
		^
  symbol:   variable IJ
  location: class NJ
NeuronJ_.java:344: error: cannot find symbol
		IJ.showProgress(1.0);
		^
  symbol:   variable IJ
  location: class NJ
NeuronJ_.java:345: error: cannot find symbol
		IJ.showStatus("");
		^
  symbol:   variable IJ
  location: class NJ
NeuronJ_.java:351: error: cannot find symbol
		Prefs.set("nj.appear",appear);
		^
  symbol:   variable Prefs
  location: class NJ
NeuronJ_.java:352: error: cannot find symbol
		Prefs.set("nj.scale",scale);
		^
  symbol:   variable Prefs
  location: class NJ
NeuronJ_.java:353: error: cannot find symbol
		Prefs.set("nj.gamma",gamma);
		^
  symbol:   variable Prefs
  location: class NJ
NeuronJ_.java:354: error: cannot find symbol
		Prefs.set("nj.snaprange",snaprange);
		^
  symbol:   variable Prefs
  location: class NJ
NeuronJ_.java:355: error: cannot find symbol
		Prefs.set("nj.dijkrange",dijkrange);
		^
  symbol:   variable Prefs
  location: class NJ
NeuronJ_.java:356: error: cannot find symbol
		Prefs.set("nj.halfsmoothrange",halfsmoothrange);
		^
  symbol:   variable Prefs
  location: class NJ
NeuronJ_.java:357: error: cannot find symbol
		Prefs.set("nj.subsamplefactor",subsamplefactor);
		^
  symbol:   variable Prefs
  location: class NJ
NeuronJ_.java:358: error: cannot find symbol
		Prefs.set("nj.linewidth",linewidth);
		^
  symbol:   variable Prefs
  location: class NJ
NeuronJ_.java:359: error: cannot find symbol
		Prefs.set("nj.activate",activate);
		^
  symbol:   variable Prefs
  location: class NJ
NeuronJ_.java:360: error: cannot find symbol
		Prefs.set("nj.usename",usename);
		^
  symbol:   variable Prefs
  location: class NJ
NeuronJ_.java:361: error: cannot find symbol
		Prefs.set("nj.autosave",autosave);
		^
  symbol:   variable Prefs
  location: class NJ
NeuronJ_.java:362: error: cannot find symbol
		Prefs.set("nj.log",log);
		^
  symbol:   variable Prefs
  location: class NJ
NeuronJ_.java:368: error: cannot find symbol
		appear = (int)Prefs.get("nj.appear",appear);
		              ^
  symbol:   variable Prefs
  location: class NJ
NeuronJ_.java:369: error: cannot find symbol
		scale = (float)Prefs.get("nj.scale",scale);
		               ^
  symbol:   variable Prefs
  location: class NJ
NeuronJ_.java:370: error: cannot find symbol
		gamma = (float)Prefs.get("nj.gamma",gamma);
		               ^
  symbol:   variable Prefs
  location: class NJ
NeuronJ_.java:371: error: cannot find symbol
		snaprange = (int)Prefs.get("nj.snaprange",snaprange);
		                 ^
  symbol:   variable Prefs
  location: class NJ
NeuronJ_.java:372: error: cannot find symbol
		dijkrange = (int)Prefs.get("nj.dijkrange",dijkrange);
		                 ^
  symbol:   variable Prefs
  location: class NJ
NeuronJ_.java:373: error: cannot find symbol
		halfsmoothrange = (int)Prefs.get("nj.halfsmoothrange",halfsmoothrange);
		                       ^
  symbol:   variable Prefs
  location: class NJ
NeuronJ_.java:374: error: cannot find symbol
		subsamplefactor = (int)Prefs.get("nj.subsamplefactor",subsamplefactor);
		                       ^
  symbol:   variable Prefs
  location: class NJ
NeuronJ_.java:375: error: cannot find symbol
		linewidth = (int)Prefs.get("nj.linewidth",linewidth);
		                 ^
  symbol:   variable Prefs
  location: class NJ
NeuronJ_.java:377: error: cannot find symbol
		activate = Prefs.get("nj.activate",activate);
		           ^
  symbol:   variable Prefs
  location: class NJ
NeuronJ_.java:378: error: cannot find symbol
		usename = Prefs.get("nj.usename",usename);
		          ^
  symbol:   variable Prefs
  location: class NJ
NeuronJ_.java:379: error: cannot find symbol
		autosave = Prefs.get("nj.autosave",autosave);
		           ^
  symbol:   variable Prefs
  location: class NJ
NeuronJ_.java:380: error: cannot find symbol
		log = Prefs.get("nj.log",log);
		      ^
  symbol:   variable Prefs
  location: class NJ
NeuronJ_.java:405: error: cannot find symbol
		IJ.showStatus("");
		^
  symbol:   variable IJ
  location: class NJ
NeuronJ_.java:406: error: cannot find symbol
		IJ.showProgress(1.0);
		^
  symbol:   variable IJ
  location: class NJ
NeuronJ_.java:407: error: cannot find symbol
		IJ.setTool(lasttool);
		^
  symbol:   variable IJ
  location: class NJ
NeuronJ_.java:408: error: cannot find symbol
		Prefs.doubleBuffer = lastdoublebuffering;
		^
  symbol:   variable Prefs
  location: class NJ
NeuronJ_.java:420: error: cannot find symbol
		IJ.log("Unexpected exception in "+NJ.NAME+" "+NJ.VERSION);
		^
  symbol:   variable IJ
  location: class Catcher
NeuronJ_.java:421: error: cannot find symbol
		IJ.log("Please send a copy of this message");
		^
  symbol:   variable IJ
  location: class Catcher
NeuronJ_.java:422: error: cannot find symbol
		IJ.log("and a description of how to reproduce it");
		^
  symbol:   variable IJ
  location: class Catcher
NeuronJ_.java:423: error: cannot find symbol
		IJ.log("to Erik Meijering: meijering@imagescience.org");
		^
  symbol:   variable IJ
  location: class Catcher
NeuronJ_.java:424: error: cannot find symbol
		IJ.log("OS version: "+System.getProperty("os.name")+" "+System.getProperty("os.version"));
		^
  symbol:   variable IJ
  location: class Catcher
NeuronJ_.java:425: error: cannot find symbol
		IJ.log("Java version: "+System.getProperty("java.version"));
		^
  symbol:   variable IJ
  location: class Catcher
NeuronJ_.java:426: error: cannot find symbol
		IJ.log("ImageJ version: "+IJ.getVersion());
		                          ^
  symbol:   variable IJ
  location: class Catcher
100 errors
(base) NeuroCyto-CL1:NeuronJ christo$ 

OK just realized that your instructions were for Fiji and I was trying with an ImageJ install, where the ij.jar is not in jars/

It worked. I feel so empowered! Thanks a lot for the help

1 Like

Glad that the good old way worked for you!

To make it easy for others to contribute, other projects in the ImageJ universe use Maven to create reproducible builds with a single line from the command prompt:

mvn clean install

I “mavenized” NeuronJ in a fork of the imagescience/NeuronJ repository and created this pull request:

… which will hopefully make it easier for others who run into similar issues as you first did, without requiring the separate steps of compiling and bundling as a jar that @mountain_man outlined above.


Please note that while the code is openly available, NeuronJ is not licensed under an open source license. From the LICENSE file:

IT IS NOT ALLOWED TO REDISTRIBUTE, SELL, OR LEASE THIS SOFTWARE, OR DERIVATIVE WORKS THEREOF, WITHOUT PERMISSION IN WRITING FROM THE COPYRIGHT HOLDER.

… meaning that in order to redistribute your changed version of NeuronJ, you’d have to ask @emeijering for explicit written permission first, as it is not granted by the current license.

@emeijering: Any chance that you’d like to make your work available under a more permissive license (it doesn’t need to allow commercial use, but at least allow redistribution under similar conditions, such as the GPL, for example)?