use of ini.trakem2.persistence.FSLoader in project TrakEM2 by trakem2.
the class MatchIntensities method run.
/**
* @param layers
* @param radius
* @param scale
* @param numCoefficients
* @param lambda1
* @param lambda2
* @param neighborWeight
* @param roi
*/
public <M extends Model<M> & Affine1D<M>> void run(final List<Layer> layers, final int radius, final double scale, final int numCoefficients, final double lambda1, final double lambda2, final double neighborWeight, final Rectangle roi) throws InterruptedException, ExecutionException {
final int firstLayerIndex = layerset.getLayerIndex(layers.get(0).getId());
final int lastLayerIndex = layerset.getLayerIndex(layers.get(layers.size() - 1).getId());
// final PointMatchFilter filter = new RansacRegressionFilter();
final PointMatchFilter filter = new RansacRegressionReduceFilter();
/* collect patches */
Utils.log("Collecting patches ... ");
final ArrayList<Patch> patches = new ArrayList<Patch>();
for (final Layer layer : layers) patches.addAll((Collection) layer.getDisplayables(Patch.class, roi));
/* delete existing intensity coefficients */
Utils.log("Clearing existing intensity maps ... ");
for (final Patch p : patches) p.clearIntensityMap();
/* generate coefficient tiles for all patches
* TODO consider offering alternative models */
final HashMap<Patch, ArrayList<Tile<? extends M>>> coefficientsTiles = (HashMap) generateCoefficientsTiles(patches, new InterpolatedAffineModel1D<InterpolatedAffineModel1D<AffineModel1D, TranslationModel1D>, IdentityModel>(new InterpolatedAffineModel1D<AffineModel1D, TranslationModel1D>(new AffineModel1D(), new TranslationModel1D(), lambda1), new IdentityModel(), lambda2), numCoefficients * numCoefficients);
/* completed patches */
final HashSet<Patch> completedPatches = new HashSet<Patch>();
/* collect patch pairs */
Utils.log("Collecting patch pairs ... ");
final ArrayList<ValuePair<Patch, Patch>> patchPairs = new ArrayList<ValuePair<Patch, Patch>>();
for (final Patch p1 : patches) {
completedPatches.add(p1);
final Rectangle box1 = p1.getBoundingBox().intersection(roi);
final ArrayList<Patch> p2s = new ArrayList<Patch>();
/* across adjacent layers */
final int layerIndex = layerset.getLayerIndex(p1.getLayer().getId());
for (int i = Math.max(firstLayerIndex, layerIndex - radius); i <= Math.min(lastLayerIndex, layerIndex + radius); ++i) {
final Layer layer = layerset.getLayer(i);
if (layer != null)
p2s.addAll((Collection) layer.getDisplayables(Patch.class, box1));
}
for (final Patch p2 : p2s) {
/*
* if this patch had been processed earlier, all matches are
* already in
*/
if (completedPatches.contains(p2))
continue;
patchPairs.add(new ValuePair<Patch, Patch>(p1, p2));
}
}
final int numThreads = Integer.parseInt(layerset.getProperty("n_mipmap_threads", Integer.toString(Runtime.getRuntime().availableProcessors())));
Utils.log("Matching intensities using " + numThreads + " threads ... ");
final ExecutorService exec = Executors.newFixedThreadPool(numThreads);
final ArrayList<Future<?>> futures = new ArrayList<Future<?>>();
for (final ValuePair<Patch, Patch> patchPair : patchPairs) {
futures.add(exec.submit(new Matcher(roi, patchPair, (HashMap) coefficientsTiles, filter, scale, numCoefficients)));
}
for (final Future<?> future : futures) future.get();
/* connect tiles within patches */
Utils.log("Connecting coefficient tiles in the same patch ... ");
for (final Patch p1 : completedPatches) {
/* get the coefficient tiles */
final ArrayList<Tile<? extends M>> p1CoefficientsTiles = coefficientsTiles.get(p1);
for (int y = 1; y < numCoefficients; ++y) {
final int yr = numCoefficients * y;
final int yr1 = yr - numCoefficients;
for (int x = 0; x < numCoefficients; ++x) {
identityConnect(p1CoefficientsTiles.get(yr1 + x), p1CoefficientsTiles.get(yr + x), neighborWeight);
}
}
for (int y = 0; y < numCoefficients; ++y) {
final int yr = numCoefficients * y;
for (int x = 1; x < numCoefficients; ++x) {
final int yrx = yr + x;
identityConnect(p1CoefficientsTiles.get(yrx), p1CoefficientsTiles.get(yrx - 1), neighborWeight);
}
}
}
/* optimize */
Utils.log("Optimizing ... ");
final TileConfiguration tc = new TileConfiguration();
for (final ArrayList<Tile<? extends M>> coefficients : coefficientsTiles.values()) {
// for ( final Tile< ? > t : coefficients )
// if ( t.getMatches().size() == 0 )
// IJ.log( "bang" );
tc.addTiles(coefficients);
}
try {
tc.optimize(0.01f, iterations, iterations, 0.75f);
} catch (final NotEnoughDataPointsException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (final IllDefinedDataPointsException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
/* save coefficients */
final double[] ab = new double[2];
final FSLoader loader = (FSLoader) layerset.getProject().getLoader();
final String itsDir = loader.getUNUIdFolder() + "trakem2.its/";
for (final Entry<Patch, ArrayList<Tile<? extends M>>> entry : coefficientsTiles.entrySet()) {
final FloatProcessor as = new FloatProcessor(numCoefficients, numCoefficients);
final FloatProcessor bs = new FloatProcessor(numCoefficients, numCoefficients);
final Patch p = entry.getKey();
final double min = p.getMin();
final double max = p.getMax();
final ArrayList<Tile<? extends M>> tiles = entry.getValue();
for (int i = 0; i < numCoefficients * numCoefficients; ++i) {
final Tile<? extends M> t = tiles.get(i);
final Affine1D<?> affine = t.getModel();
affine.toArray(ab);
/* coefficients mapping into existing [min, max] */
as.setf(i, (float) ab[0]);
bs.setf(i, (float) ((max - min) * ab[1] + min - ab[0] * min));
}
final ImageStack coefficientsStack = new ImageStack(numCoefficients, numCoefficients);
coefficientsStack.addSlice(as);
coefficientsStack.addSlice(bs);
final String itsPath = itsDir + FSLoader.createIdPath(Long.toString(p.getId()), "it", ".tif");
new File(itsPath).getParentFile().mkdirs();
IJ.saveAs(new ImagePlus("", coefficientsStack), "tif", itsPath);
}
/* update mipmaps */
for (final Patch p : patches) p.getProject().getLoader().decacheImagePlus(p.getId());
final ArrayList<Future<Boolean>> mipmapFutures = new ArrayList<Future<Boolean>>();
for (final Patch p : patches) mipmapFutures.add(p.updateMipMaps());
for (final Future<Boolean> f : mipmapFutures) f.get();
Utils.log("Matching intensities done.");
}
use of ini.trakem2.persistence.FSLoader in project TrakEM2 by trakem2.
the class Patch method exportXML.
/**
* Opens and closes the tag and exports data. The image is saved in the directory provided in @param any as a String.
*/
@Override
public void exportXML(final StringBuilder sb_body, final String indent, final XMLOptions options) {
// TODO the Loader should handle the saving of images, not this class.
final String in = indent + "\t";
String path = null;
String path2 = null;
if (options.export_images) {
path = options.patches_dir + title;
// save image without overwriting, and add proper extension (.zip)
path2 = project.getLoader().exportImage(this, path, false);
// path2 will be null if the file exists already
}
sb_body.append(indent).append("<t2_patch\n");
String rel_path = null;
if (null != path && path.equals(path2)) {
// this happens when a DB project is exported. It may be a different path when it's a FS loader
// Utils.log2("p id=" + id + " path==path2");
rel_path = path2;
// TrakEM2 uses paths that always have '/' and never '\', so using java.io.File.separatorChar would be an error.
int i_slash = rel_path.lastIndexOf('/');
if (i_slash > 0) {
i_slash = rel_path.lastIndexOf('/', i_slash - 1);
if (-1 != i_slash) {
rel_path = rel_path.substring(i_slash + 1);
}
}
} else {
// Utils.log2("Setting rel_path to " + path2);
rel_path = path2;
}
// For FSLoader projects, saving a second time will save images as null unless calling it
if (null == rel_path) {
// Utils.log2("path2 was null");
final Object ob = project.getLoader().getPath(this);
path2 = null == ob ? null : (String) ob;
if (null == path2) {
// Utils.log2("ERROR: No path for Patch id=" + id + " and title: " + title);
// at least some clue for recovery
rel_path = title;
} else {
rel_path = path2;
}
}
// Utils.log("Patch path is: " + rel_path);
super.exportXML(sb_body, in, options);
final String[] RGB = Utils.getHexRGBColor(color);
int type = this.type;
if (-1 == this.type) {
Utils.log2("Retrieving type for p = " + this);
final ImagePlus imp = project.getLoader().fetchImagePlus(this);
if (null != imp)
type = imp.getType();
}
sb_body.append(in).append("type=\"").append(type).append("\"\n").append(in).append("file_path=\"").append(rel_path).append("\"\n").append(in).append("style=\"fill-opacity:").append(alpha).append(";stroke:#").append(RGB[0]).append(RGB[1]).append(RGB[2]).append(";\"\n").append(in).append("o_width=\"").append(o_width).append("\"\n").append(in).append("o_height=\"").append(o_height).append("\"\n");
if (null != original_path) {
sb_body.append(in).append("original_path=\"").append(original_path).append("\"\n");
}
sb_body.append(in).append("min=\"").append(min).append("\"\n");
sb_body.append(in).append("max=\"").append(max).append("\"\n");
final String pps = getPreprocessorScriptPath();
if (null != pps)
sb_body.append(in).append("pps=\"").append(project.getLoader().makeRelativePath(pps)).append("\"\n");
sb_body.append(in).append("mres=\"").append(meshResolution).append("\"\n");
if (hasCoordinateTransform()) {
sb_body.append(in).append("ct_id=\"").append(ct_id).append("\"\n");
}
if (hasAlphaMask()) {
sb_body.append(in).append("alpha_mask_id=\"").append(alpha_mask_id).append("\"\n");
}
sb_body.append(indent).append(">\n");
if (hasCoordinateTransform()) {
if (options.include_coordinate_transform) {
// Write an XML entry for the CoordinateTransform
char[] ct_chars = null;
try {
ct_chars = readCoordinateTransformFile();
} catch (final Exception e) {
IJError.print(e);
}
if (null != ct_chars) {
sb_body.append(ct_chars).append('\n');
} else {
Utils.log("ERROR: could not write the CoordinateTransform to the XML file!");
}
}
}
if (null != filters && filters.length > 0) {
// specify their own line termination
for (final IFilter f : filters) sb_body.append(f.toXML(in));
}
super.restXML(sb_body, in, options);
sb_body.append(indent).append("</t2_patch>\n");
}
use of ini.trakem2.persistence.FSLoader in project TrakEM2 by trakem2.
the class FSLoader method deleteStaleFiles.
/**
* Delete stale files under the {@link FSLoader#unuid} folder.
* These include "*.ct" files (for {@link CoordinateTransform})
* and "*.zip" files (for alpha mask images) that are not referenced from any {@link Patch}.
*/
@Override
public boolean deleteStaleFiles(boolean coordinate_transforms, boolean alpha_masks) {
boolean b = true;
final Project project = Project.findProject(this);
if (coordinate_transforms)
b = b && StaleFiles.deleteCoordinateTransforms(project);
if (alpha_masks)
b = b && StaleFiles.deleteAlphaMasks(project);
return b;
}
use of ini.trakem2.persistence.FSLoader in project TrakEM2 by trakem2.
the class Project method newFSProject.
public static Project newFSProject(String arg, TemplateThing template_root, String storage_folder, boolean autocreate_one_layer) {
if (Utils.wrongImageJVersion())
return null;
FSLoader loader = null;
try {
String dir_project = storage_folder;
if (null == dir_project || !new File(dir_project).isDirectory()) {
DirectoryChooser dc = new DirectoryChooser("Select storage folder");
dir_project = dc.getDirectory();
// user cancelled dialog
if (null == dir_project)
return null;
if (!Loader.canReadAndWriteTo(dir_project)) {
Utils.showMessage("Can't read/write to the selected storage folder.\nPlease check folder permissions.");
return null;
}
if (IJ.isWindows())
dir_project = dir_project.replace('\\', '/');
}
loader = new FSLoader(dir_project);
Project project = createNewProject(loader, !("blank".equals(arg) || "amira".equals(arg)), template_root);
// help the helpless users:
if (autocreate_one_layer && null != project && ControlWindow.isGUIEnabled()) {
Utils.log2("Creating automatic Display.");
// add a default layer
Layer layer = new Layer(project, 0, 1, project.layer_set);
project.layer_set.add(layer);
project.layer_tree.addLayer(project.layer_set, layer);
layer.recreateBuckets();
Display.createDisplay(project, layer);
}
try {
// waiting cheaply for asynchronous swing calls
Thread.sleep(200);
} catch (InterruptedException ie) {
ie.printStackTrace();
}
if ("amira".equals(arg) || "stack".equals(arg)) {
// forks into a task thread
loader.importStack(project.layer_set.getLayer(0), null, true);
}
project.restartAutosaving();
return project;
} catch (Exception e) {
IJError.print(e);
if (null != loader)
loader.destroy();
}
return null;
}
use of ini.trakem2.persistence.FSLoader in project TrakEM2 by trakem2.
the class Project method createSubproject.
/**
* Create a new subproject for the given layer range and ROI.
* Create a new Project using the given project as template. This means the DTD of the given project is copied, as well as the storage and mipmaps folders; everything else is empty in the new project.
*/
public Project createSubproject(final Rectangle roi, final Layer first, final Layer last, final boolean ignore_hidden_patches) {
try {
// The order matters.
final Project pr = new Project(new FSLoader(this.getLoader().getStorageFolder()));
pr.id = this.id;
// copy properties
pr.title = this.title;
pr.ht_props.putAll(this.ht_props);
// copy template
pr.root_tt = this.root_tt.clone(pr, true);
pr.template_tree = new TemplateTree(pr, pr.root_tt);
synchronized (pr.ht_unique_tt) {
pr.ht_unique_tt.clear();
pr.ht_unique_tt.putAll(root_tt.getUniqueTypes(new HashMap<String, TemplateThing>()));
}
TemplateThing project_template = new TemplateThing("project");
project_template.addChild(pr.root_tt);
pr.ht_unique_tt.put("project", project_template);
// create the layers templates
pr.createLayerTemplates();
// copy LayerSet and all involved Displayable objects
// (A two-step process to provide the layer_set pointer and all Layer pointers to the ZDisplayable to copy and crop.)
pr.layer_set = (LayerSet) this.layer_set.clone(pr, first, last, roi, false, true, ignore_hidden_patches);
LayerSet.cloneInto(this.layer_set, first, last, pr, pr.layer_set, roi, true);
// create layer tree
pr.root_lt = new LayerThing(Project.layer_set_template, pr, pr.layer_set);
pr.layer_tree = new LayerTree(pr, pr.root_lt);
// add layer nodes to the layer tree (solving chicken-and-egg problem)
pr.layer_set.updateLayerTree();
// copy project tree
pr.root_pt = this.root_pt.subclone(pr);
pr.project_tree = new ProjectTree(pr, pr.root_pt);
// not copying node expanded state.
// register
al_open_projects.add(pr);
// add to gui:
ControlWindow.add(pr, pr.template_tree, pr.project_tree, pr.layer_tree);
// Above, the id of each object is preserved from this project into the subproject.
// The abstract structure should be copied in full regardless, without the basic objects
// included if they intersect the roi.
// Regenerate mipmaps (blocks GUI from interaction other than navigation)
pr.loader.regenerateMipMaps(pr.layer_set.getDisplayables(Patch.class));
pr.restartAutosaving();
return pr;
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
Aggregations