use of ini.trakem2.display.Layer in project TrakEM2 by trakem2.
the class Loader method importImage.
/**
* Import a new image at the given coordinates; does not puts it into any layer, unless it's a stack -in which case importStack is called with the current front layer of the given project as target. If a path is not provided it will be asked for.
*/
public Patch importImage(final Project project, final double x, final double y, String path, final boolean synch_mipmap_generation) {
if (null == path) {
final OpenDialog od = new OpenDialog("Import image", "");
final String name = od.getFileName();
if (null == name || 0 == name.length())
return null;
String dir = od.getDirectory().replace('\\', '/');
if (!dir.endsWith("/"))
dir += "/";
path = dir + name;
} else {
path = path.replace('\\', '/');
}
// avoid opening trakem2 projects
if (path.toLowerCase().endsWith(".xml")) {
Utils.showMessage("Cannot import " + path + " as a stack.");
return null;
}
releaseToFit(new File(path).length() * 3);
IJ.redirectErrorMessages();
final ImagePlus imp = openImagePlus(path);
if (null == imp)
return null;
if (imp.getNSlices() > 1) {
// a stack!
final Layer layer = Display.getFrontLayer(project);
if (null == layer)
return null;
importStack(layer, x, y, imp, true, path, true);
return null;
}
if (0 == imp.getWidth() || 0 == imp.getHeight()) {
Utils.showMessage("Can't import image of zero width or height.");
flush(imp);
return null;
}
final Patch p = new Patch(project, imp.getTitle(), x, y, imp);
addedPatchFrom(path, p);
// WARNING may be altered concurrently
last_opened_path = path;
if (isMipMapsRegenerationEnabled()) {
if (synch_mipmap_generation) {
try {
// wait
regenerateMipMaps(p).get();
} catch (final Exception e) {
IJError.print(e);
}
} else
// queue for regeneration
regenerateMipMaps(p);
}
return p;
}
use of ini.trakem2.display.Layer in project TrakEM2 by trakem2.
the class Loader method importGrid.
/**
* Import a grid of images and put them in the layer. If the directory (@param dir) is null, it'll be asked for.
*/
public Bureaucrat importGrid(final Layer layer, String dir) {
try {
String file = null;
if (null == dir) {
final String[] dn = Utils.selectFile("Select first image");
if (null == dn)
return null;
dir = dn[0];
file = dn[1];
}
// char digit digit
String convention = "cdd";
boolean chars_are_columns = true;
// examine file name
/*
if (file.matches("\\A[a-zA-Z]\\d\\d.*")) { // one letter, 2 numbers
//means:
// \A - beggining of input
// [a-zA-Z] - any letter upper or lower case
// \d\d - two consecutive digits
// .* - any row of chars
ini_grid_convention = true;
}
*/
// ask for chars->rows, numbers->columns or viceversa
final GenericDialog gd = new GenericDialog("Conventions");
gd.addStringField("file_name_contains:", "");
gd.addNumericField("base_x: ", 0, 3);
gd.addNumericField("base_y: ", 0, 3);
gd.addMessage("Use: x(any), c(haracter), d(igit)");
gd.addStringField("convention: ", convention);
final String[] cr = new String[] { "columns", "rows" };
gd.addChoice("characters are: ", cr, cr[0]);
gd.addMessage("[File extension ignored]");
// as asked by Joachim Walter
gd.addNumericField("bottom-top overlap: ", 0, 3);
gd.addNumericField("left-right overlap: ", 0, 3);
gd.addCheckbox("link_images", false);
gd.addCheckbox("montage with phase correlation", false);
gd.addCheckbox("homogenize_contrast", true);
final Component[] c = { (Component) gd.getSliders().get(gd.getSliders().size() - 2), (Component) gd.getNumericFields().get(gd.getNumericFields().size() - 2), (Component) gd.getSliders().get(gd.getSliders().size() - 1), (Component) gd.getNumericFields().get(gd.getNumericFields().size() - 1), (Component) gd.getChoices().get(gd.getChoices().size() - 1) };
// enable the checkbox to control the slider and its associated numeric field:
Utils.addEnablerListener((Checkbox) gd.getCheckboxes().get(gd.getCheckboxes().size() - 1), c, null);
// gd.addCheckbox("Apply non-linear deformation", false);
gd.showDialog();
if (gd.wasCanceled()) {
return null;
}
// collect data
// filter away files not containing this tag
final String regex = gd.getNextString();
// the base x,y of the whole grid
final double bx = gd.getNextNumber();
final double by = gd.getNextNumber();
// if (!ini_grid_convention) {
convention = gd.getNextString().toLowerCase();
// }
if (/*!ini_grid_convention && */
(null == convention || convention.equals("") || -1 == convention.indexOf('c') || -1 == convention.indexOf('d'))) {
// TODO check that the convention has only 'cdx' chars and also that there is an island of 'c's and of 'd's only.
Utils.showMessage("Convention '" + convention + "' needs both c(haracters) and d(igits), optionally 'x', and nothing else!");
return null;
}
chars_are_columns = (0 == gd.getNextChoiceIndex());
final double bt_overlap = gd.getNextNumber();
final double lr_overlap = gd.getNextNumber();
final boolean link_images = gd.getNextBoolean();
final boolean stitch_tiles = gd.getNextBoolean();
final boolean homogenize_contrast = gd.getNextBoolean();
// start magic
// get ImageJ-openable files that comply with the convention
final File images_dir = new File(dir);
if (!(images_dir.exists() && images_dir.isDirectory())) {
Utils.showMessage("Something went wrong:\n\tCan't find directory " + dir);
return null;
}
final String[] file_names = images_dir.list(new ImageFileFilter(regex, convention));
if (null == file && file_names.length > 0) {
// the 'selected' file
file = file_names[0];
}
Utils.showStatus("Adding " + file_names.length + " patches.", false);
if (0 == file_names.length) {
Utils.log("Zero files match the convention '" + convention + "'");
return null;
}
// How to: select all files, and order their names in a double array as they should be placed in the Display. Then place them, displacing by offset, and resizing if necessary.
// gather image files:
final Montage montage = new Montage(convention, chars_are_columns);
montage.addAll(file_names);
// an array of Object[] arrays, of unequal length maybe, each containing a column of image file names
final ArrayList<String[]> cols = montage.getCols();
// !@#$%^&*
final String dir_ = dir;
final double bt_overlap_ = bt_overlap;
final double lr_overlap_ = lr_overlap;
final String file_ = file;
return Bureaucrat.createAndStart(new Worker.Task("Insert grid", true) {
@Override
public void exec() {
StitchingTEM.PhaseCorrelationParam pc_param = null;
if (stitch_tiles) {
pc_param = new StitchingTEM.PhaseCorrelationParam();
pc_param.setup(layer);
}
insertGrid(layer, dir_, file_, file_names.length, cols, bx, by, bt_overlap_, lr_overlap_, link_images, stitch_tiles, homogenize_contrast, pc_param, this);
}
}, layer.getProject());
} catch (final Exception e) {
IJError.print(e);
}
return null;
}
use of ini.trakem2.display.Layer in project TrakEM2 by trakem2.
the class Loader method getFlatAWTImage.
/**
* @param layer The layer from which to collect visible Displayable instances that intersect the srcRect.
* @param srcRect_ Rectangle in World coordinates representing the field of view to paint into the image, and defines the width and height of the image together with the scale.
* @param scale Value between 0 and 1.
* @param c_alphas Which color channels to include when painting Patch instances that hold an RGB image.
* @param type Either ImagePlus.GRAY8 or ImagePlus.COLOR_RGB
* @param clazz Include only Displayable instances of this class; use Displayable.class for all.
* @param al_displ List of Displayable instances to include. Use null to include all visible intersected by srcRect.
* @param quality Whether to attempt to create a larger image and then scale it down with area averaging for best quality.
* @param background The color of the areas of the image where no Displayable paints.
* @param active Whether to paint a particular Displayable instance in an active state (as if it was selected in the UI).
* @return
*/
public Image getFlatAWTImage(final Layer layer, final Rectangle srcRect_, final double scale, final int c_alphas, final int type, final Class<?> clazz, List<? extends Displayable> al_displ, boolean quality, final Color background, final Displayable active) {
try {
// dimensions
int w = 0;
int h = 0;
Rectangle srcRect = (null == srcRect_) ? null : (Rectangle) srcRect_.clone();
if (null != srcRect) {
w = srcRect.width;
h = srcRect.height;
} else {
w = (int) Math.ceil(layer.getLayerWidth());
h = (int) Math.ceil(layer.getLayerHeight());
srcRect = new Rectangle(0, 0, w, h);
}
Utils.log2("Loader.getFlatImage: using rectangle " + srcRect);
/*
* output size including excess space for not entirely covered
* pixels
*/
final int ww = (int) Math.ceil(w * scale);
final int hh = (int) Math.ceil(h * scale);
/* The size of the buffered image to be generated */
final int biw, bih;
final double scaleP, scalePX, scalePY;
// on scaling down to output resolution.
if (quality) {
if (ww * hh >= Math.pow(2, 30)) {
// 1 GB
// While perhaps scale could be increased to an image size of up to 2 GB, it is not advisable
scaleP = scalePX = scalePY = scale;
quality = false;
biw = ww;
bih = hh;
Utils.log("Can't use 'quality' flag for getFlatAWTImage: would be too large");
// If the image is larger than 2 GB, it will thrown a NegativeArraySizeException below and stop.
} else {
// Max area: the smallest of the srcRect at 100x magnification and 1 GB
final double max_area = Math.min(srcRect.width * srcRect.height, Math.pow(2, 30));
final double ratio = ww / (double) hh;
// area = w * h
// ratio = w / h
// w = ratio * h
// area = ratio * h * h
// h = sqrt(area / ratio)
// scaleP is then the ratio between the real-world height and the target height
// (And clamp to a maximum of 1.0: above makes no sense)
scaleP = Math.min(1.0, srcRect.height / Math.sqrt(max_area / ratio));
biw = (int) Math.ceil(ww / scale);
bih = (int) Math.ceil(hh / scale);
/* compensate for excess space due to ceiling */
scalePX = (double) biw / (double) ww * scale;
scalePY = (double) bih / (double) hh * scale;
Utils.log("getFlatAWTImage -- scale: " + scale + "; quality scale: " + scaleP);
}
} else {
scaleP = scalePX = scalePY = scale;
biw = ww;
bih = hh;
}
// estimate image size
final long n_bytes = (long) ((biw * bih * (ImagePlus.GRAY8 == type ? 1.0 : /*byte*/
4.0)));
Utils.log2("Flat image estimated size in bytes: " + Long.toString(n_bytes) + " w,h : " + (int) Math.ceil(biw) + "," + (int) Math.ceil(bih) + (quality ? " (using 'quality' flag: scaling to " + scale + " is done later with area averaging)" : ""));
releaseToFit(n_bytes);
// go
BufferedImage bi = null;
switch(type) {
case ImagePlus.GRAY8:
bi = new BufferedImage(biw, bih, BufferedImage.TYPE_BYTE_INDEXED, GRAY_LUT);
break;
case ImagePlus.COLOR_RGB:
bi = new BufferedImage(biw, bih, BufferedImage.TYPE_INT_ARGB);
break;
default:
Utils.log2("Left bi,icm as null");
break;
}
final Graphics2D g2d = bi.createGraphics();
g2d.setColor(background);
g2d.fillRect(0, 0, bi.getWidth(), bi.getHeight());
g2d.setRenderingHint(RenderingHints.KEY_ALPHA_INTERPOLATION, RenderingHints.VALUE_ALPHA_INTERPOLATION_QUALITY);
// TODO Stephan, test if that introduces offset vs nearest neighbor
g2d.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BICUBIC);
// to smooth edges of the images
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
g2d.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
g2d.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);
ArrayList<ZDisplayable> al_zdispl = null;
if (null == al_displ) {
al_displ = new ArrayList<Displayable>(layer.find(clazz, srcRect, true, true));
al_zdispl = new ArrayList<ZDisplayable>((Collection) layer.getParent().findZDisplayables(clazz, layer, srcRect, true, true));
} else {
// separate ZDisplayables into their own array
al_displ = new ArrayList<Displayable>(al_displ);
final HashSet<ZDisplayable> az = new HashSet<ZDisplayable>();
for (final Iterator<?> it = al_displ.iterator(); it.hasNext(); ) {
final Object ob = it.next();
if (ob instanceof ZDisplayable) {
it.remove();
az.add((ZDisplayable) ob);
}
}
// order ZDisplayables by their stack order
final ArrayList<ZDisplayable> al_zdispl2 = layer.getParent().getZDisplayables();
for (final Iterator<ZDisplayable> it = al_zdispl2.iterator(); it.hasNext(); ) {
if (!az.contains(it.next()))
it.remove();
}
al_zdispl = al_zdispl2;
}
// prepare the canvas for the srcRect and magnification
final AffineTransform at_original = g2d.getTransform();
final AffineTransform atc = new AffineTransform();
atc.scale(scalePX, scalePY);
atc.translate(-srcRect.x, -srcRect.y);
at_original.preConcatenate(atc);
g2d.setTransform(at_original);
// Utils.log2("will paint: " + al_displ.size() + " displ and " + al_zdispl.size() + " zdispl");
// int total = al_displ.size() + al_zdispl.size();
int count = 0;
boolean zd_done = false;
final List<Layer> layers = layer.getParent().getColorCueLayerRange(layer);
for (final Displayable d : al_displ) {
// paint the ZDisplayables before the first label, if any
if (!zd_done && d instanceof DLabel) {
zd_done = true;
for (final ZDisplayable zd : al_zdispl) {
if (!zd.isOutOfRepaintingClip(scaleP, srcRect, null)) {
zd.paint(g2d, srcRect, scaleP, active == zd, c_alphas, layer, layers);
}
count++;
// Utils.log2("Painted " + count + " of " + total);
}
}
if (!d.isOutOfRepaintingClip(scaleP, srcRect, null)) {
d.paintOffscreen(g2d, srcRect, scaleP, active == d, c_alphas, layer, layers);
// Utils.log("painted: " + d + "\n with: " + scaleP + ", " + c_alphas + ", " + layer);
} else {
// Utils.log2("out: " + d);
}
count++;
// Utils.log2("Painted " + count + " of " + total);
}
if (!zd_done) {
zd_done = true;
for (final ZDisplayable zd : al_zdispl) {
if (!zd.isOutOfRepaintingClip(scaleP, srcRect, null)) {
zd.paint(g2d, srcRect, scaleP, active == zd, c_alphas, layer, layers);
}
count++;
// Utils.log2("Painted " + count + " of " + total);
}
}
// ensure enough memory is available for the processor and a new awt from it
// locks on its own
releaseToFit((long) (n_bytes * 2.3));
try {
if (quality) {
// need to scale back down
Image scaled = null;
if (!isMipMapsRegenerationEnabled() || scale >= 0.499) {
// there are no proper mipmaps above 50%, so there's need for SCALE_AREA_AVERAGING.
// very slow, but best by far
scaled = bi.getScaledInstance(ww, hh, Image.SCALE_AREA_AVERAGING);
if (ImagePlus.GRAY8 == type) {
// getScaledInstance generates RGB images for some reason.
final BufferedImage bi8 = new BufferedImage(ww, hh, BufferedImage.TYPE_BYTE_GRAY);
bi8.createGraphics().drawImage(scaled, 0, 0, null);
scaled.flush();
scaled = bi8;
}
} else {
// faster, but requires gaussian blurred images (such as the mipmaps)
if (bi.getType() == BufferedImage.TYPE_BYTE_INDEXED) {
scaled = new BufferedImage(ww, hh, bi.getType(), GRAY_LUT);
} else {
scaled = new BufferedImage(ww, hh, bi.getType());
}
final Graphics2D gs = (Graphics2D) scaled.getGraphics();
// gs.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BICUBIC);
gs.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR);
gs.drawImage(bi, 0, 0, ww, hh, null);
}
bi.flush();
return scaled;
} else {
// else the image was made scaled down already, and of the proper type
return bi;
}
} catch (final OutOfMemoryError oome) {
Utils.log("Not enough memory to create the ImagePlus. Try scaling it down or not using the 'quality' flag.");
}
} catch (final Exception e) {
IJError.print(e);
}
return null;
}
use of ini.trakem2.display.Layer in project TrakEM2 by trakem2.
the class ProjectTiler method createRetiledSibling.
/**
* Take a {@link Project}, a size for the image tiles, and a target directory,
* and create a new copy of the current project in that folder but with the underlying
* images converted to tiles with a translation-only transform (saved as zipped TIFFs,
* with extension ".tif.zip").
* The new, returned {@link Project} represents the given project but with much
* simpler transformations (just translation) for the images and a defined size for
* the latter, which helps a lot regarding storage space of the XML (and parsing and
* saving time) and performance when browsing layers (keep in mind that, for a 32k x 32k image,
* at 100% zoom one would have to load a 32k x 32k image and render just a tiny bit
* of it). The copied Project preserves the ID of the {@link Layer}s of the original
* {@link Project}, as well as the dimensions; this means the copy is a sibling of
* the original, and it is possible to send segmentations from one to the other "as is"
* (directly, without having to transform along with the images which would not be possible).
*
* Image files are stored as
*
* The non-image objects of the given project are copied into the new project as well.
*
* @param srcProject The project to create a sibling of.
* @param targetDirectory The directory in which to create all the necessary data and mipmap folders for the new Project.
* @param tileWidth The width of the tiles to create for the data of the new project.
* @param tileHeight The height of the tiles.
* @param exportImageType Any of {@link ImagePlus#GRAY8}, {@link ImagePlus#GRAY16} or {@link ImagePlus#COLOR_RGB}, otherwise an {@link IllegalArgumentException} is thrown.
* @param onlyVisibleImages Whether to consider visible images only.
* @param nExportThreads Number of layers to export in parallel. Use a small number when original images are huge (such as larger than 4096 x 4096 pixels).
* @param createMipMaps Whether to generate the mipmaps when done or not.
*
* @throws Exception IllegalArgumentException When {@code exportImageType} is not {@link ImagePlus#GRAY16} or {@link ImagePlus#COLOR_RGB}, or when the directory exists and cannot be written to.
*/
public static final Project createRetiledSibling(final Project srcProject, final String targetDirectory, final int tileWidth, final int tileHeight, final int exportImageType, final boolean onlyVisibleImages, final int nExportThreads, final boolean createMipMaps) throws Exception {
// Validate exportImageType
switch(exportImageType) {
case ImagePlus.GRAY8:
case ImagePlus.GRAY16:
case ImagePlus.COLOR_RGB:
break;
default:
throw new IllegalArgumentException("Can only accept GRAY8, GRAY16 or COLOR_RGB as values for 'exportImageType'!");
}
// Validate targetDirectory
final File fdir = new File(targetDirectory);
if (fdir.exists()) {
if (!fdir.isDirectory() || !fdir.canWrite())
throw new IllegalArgumentException("Invalid directory: not a directory or cannot write to: " + targetDirectory);
} else {
if (!fdir.mkdirs()) {
throw new IllegalArgumentException("Cannot create directory at: " + targetDirectory);
}
}
final String targetDir = Utils.fixDir(targetDirectory);
// Create "data" directory
final String dataDir = new StringBuilder(targetDir).append("data/").toString();
final File fDataDir = new File(dataDir);
if (fDataDir.exists() && (!fDataDir.isDirectory() || !fDataDir.canWrite())) {
throw new IllegalArgumentException("Cannot create or write to 'data' directory in the targetDirectory at: " + targetDir);
} else {
fDataDir.mkdir();
}
// Create new Project, plain, without any automatic creation of a Layer or a Display
final Project newProject = Project.newFSProject("blank", null, targetDir, false);
final LayerSet newLayerSet = newProject.getRootLayerSet();
newLayerSet.setCalibration(srcProject.getRootLayerSet().getCalibrationCopy());
if (!createMipMaps) {
Utils.log("MipMaps are DISABLED:\n --> When done, right-click and choose 'Display - Properties...' and enable mipmaps,\n and then run 'Project - Regenerate all mipmaps'\n");
newProject.getLoader().setMipMapsRegeneration(false);
Utils.log("mipmaps enabled? " + newProject.getLoader().isMipMapsRegenerationEnabled());
}
// Copy the Template Tree of types
newProject.resetRootTemplateThing(srcProject.getRootTemplateThing().clone(newProject, true), null);
for (final TemplateThing tt : newProject.getRootTemplateThing().getUniqueTypes(new HashMap<String, TemplateThing>()).values()) {
newProject.addUniqueType(tt);
}
// Clone layers with the exact same IDs, so that the two projects are siblings at the layer-level:
// (Being siblings allows for treelines, arealists, etc. to be transferred from one to another "as is").
final List<Layer> srcLayers = srcProject.getRootLayerSet().getLayers();
final List<Layer> newLayers = new ArrayList<Layer>();
for (final Layer srcLayer : srcLayers) {
final Layer newLayer = new Layer(newProject, srcLayer.getId(), srcLayer.getZ(), srcLayer.getThickness());
// to update the ID generator in FSLoader
newLayer.addToDatabase();
newLayerSet.add(newLayer);
newLayers.add(newLayer);
newProject.getRootLayerThing().addChild(new LayerThing(newProject.getRootLayerThing().getChildTemplate("layer"), newProject, newLayer));
}
newProject.getLayerTree().rebuild();
// Update the LayerSet
newLayerSet.setDimensions(srcProject.getRootLayerSet().getLayerWidth(), srcProject.getRootLayerSet().getLayerHeight(), LayerSet.NORTHWEST);
Display.updateLayerScroller(newLayerSet);
Display.update(newLayerSet);
// Copy template from the src Project
// (It's done after creating layers so the IDs will not collide with those of the Layers)
newProject.resetRootTemplateThing(srcProject.getRootTemplateThing().clone(newProject, false), null);
// Export tiles as new Patch instances, creating new image files in disk
final int numThreads = Math.max(1, Math.min(nExportThreads, Runtime.getRuntime().availableProcessors()));
int i = 0;
for (final Layer srcLayer : srcLayers) {
Utils.log("Processing layer " + (i + 1) + "/" + srcLayers.size() + " -- " + new Date());
final int layerIndex = i++;
// Create subDirectory
final String dir = dataDir + "/" + layerIndex + "/";
new File(dir).mkdir();
// Create a new Layer with the same Z and thickness
final Layer newLayer = newLayers.get(layerIndex);
// Export layer tiles
final ArrayList<Patch> patches = new ArrayList<Patch>();
if (ImagePlus.GRAY16 == exportImageType) {
Process.progressive(ExportUnsignedShort.exportTiles(srcLayer, tileWidth, tileHeight, onlyVisibleImages), new CountingTaskFactory<Callable<ExportedTile>, Patch>() {
public Patch process(final Callable<ExportedTile> c, final int index) {
try {
// Create the tile
final ExportedTile t = c.call();
// Store the file
final String title = layerIndex + "-" + index;
final String path = dir + title + ".tif.zip";
final ImagePlus imp = new ImagePlus(title, t.sp);
if (!new FileSaver(imp).saveAsZip(path)) {
throw new Exception("Could not save tile: " + path);
}
// Create a Patch
final Patch patch = new Patch(newProject, title, t.x, t.y, imp);
patch.setLocked(true);
newProject.getLoader().addedPatchFrom(path, patch);
return patch;
} catch (Exception e) {
IJError.print(e);
return null;
}
}
}, patches, numThreads);
} else {
// GRAY8 or COLOR_RGB: created from mipmaps
Process.progressive(tileSequence(srcLayer, tileWidth, tileHeight, onlyVisibleImages), new CountingTaskFactory<Rectangle, Patch>() {
@Override
public Patch process(final Rectangle bounds, final int index) {
try {
// Create the tile
final ImagePlus imp = srcLayer.getProject().getLoader().getFlatImage(srcLayer, bounds, 1.0, -1, exportImageType, Patch.class, null, false, Color.black);
final String title = layerIndex + "-" + index;
imp.setTitle(title);
final String path = dir + title + ".tif.zip";
if (!new FileSaver(imp).saveAsZip(path)) {
throw new Exception("Could not save tile: " + path);
}
// Create a Patch
final Patch patch = new Patch(newProject, title, bounds.x, bounds.y, imp);
patch.setLocked(true);
newProject.getLoader().addedPatchFrom(path, patch);
return patch;
} catch (Exception e) {
IJError.print(e);
return null;
}
}
}, patches, numThreads);
}
// Add all Patches to the new Layer
for (final Patch p : patches) {
newLayer.add(p);
}
}
// Copy all segmentations "As is"
final ProjectThing root = srcProject.getRootProjectThing();
if (null != root.getChildren() && !root.getChildren().isEmpty()) {
final ProjectThing source_pt = srcProject.getRootProjectThing().getChildren().get(0);
// "As is"
final int transfer_mode = 0;
final ProjectThing landing_parent = newProject.getRootProjectThing();
srcProject.getProjectTree().rawSendToSiblingProject(source_pt, transfer_mode, newProject, landing_parent);
}
// Copy all floating text labels
i = 0;
for (final Layer srcLayer : srcLayers) {
for (final DLabel srcLabel : srcLayer.getAll(DLabel.class)) {
newLayers.get(i++).add(srcLabel.clone(newProject, false));
}
}
if (createMipMaps) {
final LinkedList<Future<?>> fus = new LinkedList<Future<?>>();
final int batch = Runtime.getRuntime().availableProcessors();
for (final Layer newLayer : newLayers) {
for (final Patch p : newLayer.getAll(Patch.class)) {
fus.add(p.updateMipMaps());
// Don't build-up too much
if (fus.size() > batch * 3) {
while (fus.size() > batch) {
try {
fus.removeFirst().get();
} catch (Exception e) {
IJError.print(e);
}
}
}
}
}
Utils.wait(fus);
}
// Save:
newProject.saveAs(targetDir + "exported.xml", false);
return newProject;
}
use of ini.trakem2.display.Layer in project TrakEM2 by trakem2.
the class StaleFiles method delete.
/**
* Generic method called by other methods of this class.
*/
public static final boolean delete(final Project project, final String topDir, final Path g) {
if (null == topDir)
return true;
// Collect the set of files to keep
final HashSet<String> keepers = new HashSet<String>();
for (final Layer l : project.getRootLayerSet().getLayers()) {
for (final Patch p : l.getAll(Patch.class)) {
String path = g.get(p);
if (null != path)
keepers.add(path);
}
}
// Iterate all directories, recursively
final String extension = g.extension();
final LinkedList<File> subdirs = new LinkedList<File>();
subdirs.add(new File(topDir));
final AtomicInteger counter = new AtomicInteger(0);
final ExecutorService exec = Utils.newFixedThreadPool(Math.max(2, Runtime.getRuntime().availableProcessors()), "Stale-file-remover");
while (!subdirs.isEmpty()) {
final File fdir = subdirs.removeFirst();
final String absPath = fdir.getAbsolutePath();
for (final String s : fdir.list()) {
final String path = absPath + "/" + s;
if (s.endsWith(extension)) {
if (keepers.contains(path))
continue;
// Else, delete the file, which is by definition stale
exec.submit(new Runnable() {
public void run() {
if (!new File(path).delete()) {
Utils.log2("Failed to delete: " + path);
counter.incrementAndGet();
}
}
});
} else {
final File f = new File(path);
if (f.isDirectory()) {
subdirs.add(f);
}
}
}
}
// Do not accept more tasks, but execute all submitted tasks
exec.shutdown();
// Wait maximum for an unreasonable amount of time
try {
exec.awaitTermination(1, TimeUnit.DAYS);
} catch (InterruptedException e) {
IJError.print(e);
}
if (counter.get() > 0) {
Utils.log("ERROR: failed to delete " + counter.get() + " files.\n See the stdout log for details.");
}
return 0 == counter.get();
}
Aggregations