All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.actelion.research.orbit.imageAnalysis.utils.OrbitUtils Maven / Gradle / Ivy

Go to download

Orbit, a versatile image analysis software for biological image-based quantification

There is a newer version: 3.15
Show newest version
/*
 *     Orbit, a versatile image analysis software for biological image-based quantification.
 *     Copyright (C) 2009 - 2018 Idorsia Pharmaceuticals Ltd., Hegenheimermattweg 91, CH-4123 Allschwil, Switzerland.
 *
 *     This program is free software: you can redistribute it and/or modify
 *     it under the terms of the GNU General Public License as published by
 *     the Free Software Foundation, either version 3 of the License, or
 *     (at your option) any later version.
 *
 *     This program is distributed in the hope that it will be useful,
 *     but WITHOUT ANY WARRANTY; without even the implied warranty of
 *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *     GNU General Public License for more details.
 *
 *     You should have received a copy of the GNU General Public License
 *     along with this program.  If not, see .
 *
 */

package com.actelion.research.orbit.imageAnalysis.utils;

import ch.qos.logback.classic.Level;
import com.actelion.research.orbit.beans.RawAnnotation;
import com.actelion.research.orbit.beans.RawDataFile;
import com.actelion.research.orbit.beans.RawMeta;
import com.actelion.research.orbit.dal.IOrbitImage;
import com.actelion.research.orbit.dal.IOrbitImageMultiChannel;
import com.actelion.research.orbit.exceptions.OrbitImageServletException;
import com.actelion.research.orbit.imageAnalysis.components.RecognitionFrame;
import com.actelion.research.orbit.imageAnalysis.dal.DALConfig;
import com.actelion.research.orbit.imageAnalysis.dal.localImage.LocalFileFilter;
import com.actelion.research.orbit.imageAnalysis.features.TissueFeatures;
import com.actelion.research.orbit.imageAnalysis.features.TissueFeaturesCircular;
import com.actelion.research.orbit.imageAnalysis.mask.IOrbitMaskModelBased;
import com.actelion.research.orbit.imageAnalysis.models.*;
import com.actelion.research.orbit.imageAnalysis.tasks.ExclusionMapGen;
import com.actelion.research.orbit.imageAnalysis.tasks.OrbitWorker;
import com.actelion.research.orbit.utils.ChannelToHue;
import com.actelion.research.orbit.utils.RawUtilsCommon;
import imageJ.Colour_Deconvolution;
import org.jaitools.tilecache.DiskCachedTile;
import org.jaitools.tiledimage.DiskMemImageOrbit;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.media.jai.PlanarImage;
import javax.swing.*;
import javax.swing.event.ChangeListener;
import java.awt.*;
import java.awt.image.*;
import java.io.*;
import java.net.URI;
import java.net.URL;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.sql.SQLException;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.List;

public class OrbitUtils {
    // label:  OrbitImageAnalysis28
    public static final String VERSION_STR = getVersion() + (ScaleoutMode.SCALEOUTMODE.get() ? "G" : "") + (OrbitUtils.DEVELOPMENTMODE ? " DEVELOPMENT" : "");
    public static final boolean DEVELOPMENTMODE = false;
    public static long SLEEP_TILE = 0; // 13*1000L;
    public static long SLEEP_TASK = 0; //2*60*1000L;

    public static final boolean TILEMODE = false;
    public static final boolean OFFLINE_MODE = false;
    public static final boolean DARKUI = true;
    public static final boolean AUTO_LOAD_FLUO_CHANNELS = false;
    public static final boolean DEEPORBIT = false;
    public static final int UNDEF_COLOR = -16777216; // =black(0,0,0) -> used for RecognitionFrame classImage as null/"out-of-ROI" class

    public static final String TAG = "OrbitImageAnalysis" + VERSION_STR.replaceAll("\\.", "");
    public static final double EPSILON = 0.000001d;
    public static final int TILE_SIZE = ScaleoutMode.SCALEOUTMODE.get() ? 256 : 256; // 512:256 for writing tiles
    public static final int TILE_SIZE_DEFAULT = 512;
    public static final long PLANAR_IMAGE_CACHE = Runtime.getRuntime().maxMemory() / 7L;  // JAI cache
    public static final long DISK_IMAGE_CACHE = Runtime.getRuntime().maxMemory() / 5L;   // DiskMemImage cache
    // see OrbitTiledImage2.initCache for 3rd cache (the main tile cache). Currently uses maxMem/2 memory
    public static final boolean DISK_IMAGE_AUTO_FLUSH = false;
    public static final double ACCURACY_WARNING = 85d;
    private static Logger logger = LoggerFactory.getLogger(OrbitUtils.class);
    private static final ThreadLocal dateFormat = new ThreadLocal() {
        @Override
        protected SimpleDateFormat initialValue() {
            return new SimpleDateFormat("HH:mm:ss");
        }
    };
    public static final int ANNOTATION_GROUPS = 20;
    public static final String muMeter = (char) 181 + "m";
    public static final String muMeterUnicode = "\u00B5";
    public static final String squareMuMeter = muMeter + (char) 178;

    private static boolean w32_ = System.getProperty("os.name").toLowerCase().startsWith("windows");
    private static boolean linux_ = System.getProperty("os.name").toLowerCase().startsWith("linux");
    private static boolean mac_ = System.getProperty("os.name").toLowerCase().contains("mac");

    public static final String MODEL_ENDING = ".omo"; // filename ending of orbit models
    public static final String remoteNameSpace = "orbit/temp";
    public static final String orbitHelpURL = "http://www.orbit.bio/help";
    public static final String orbitTutorialsURL = "http://www.orbit.bio/tutorials";
    public static final String orbitImageProviderURL = "http://www.orbit.bio/setup";

    public static final String CHANNEL_NAME_ALL = "";

    public static final String CHANNEL_NAME2HUE = "channel_name2hue_";

    static {
        Logger root = LoggerFactory.getLogger("com.actelion.research");
        if (root instanceof ch.qos.logback.classic.Logger)   // can only set if logback implementation
            ((ch.qos.logback.classic.Logger) root).setLevel(DEVELOPMENTMODE ? Level.DEBUG : Level.INFO);

        if (ScaleoutMode.SCALEOUTMODE.get()) {
            DALConfig.getImageProvider().setPooledConnectionEnabled(false);
            DALConfig.getImageProvider().setDBConnectionName("OrbitGridJob");
        }


    }

    public final static double getVersion() {
        try (InputStreamReader in = new InputStreamReader(OrbitUtils.class.getResourceAsStream("/version.txt"));
             BufferedReader reader = new BufferedReader(in);) {
            String s = reader.readLine();
            s = s.trim();
            double version = Double.parseDouble(s);
            return version;
        } catch (Exception e) {
            e.printStackTrace();
            return 0;
        }
    }

    public static boolean isOME_TIFF(String filename) {
        if (filename==null) return false;
        String fn = filename.toLowerCase();
        if (fn.endsWith("ome.tiff")||fn.endsWith("ome.tif")||fn.endsWith("ome.tf2")||fn.endsWith("ome.tf8")||fn.endsWith("ome.btf")) return true;
        else return false;
    }


    /**
     * replaces " " by "_" in channelName
     * @param channelName
     * @return
     */
    public static String cleanChannelName(String channelName) {
        if (channelName==null) return null;
        channelName = channelName.trim();
        channelName = channelName.replaceAll(";","_");
        //channelName = channelName.replaceAll(" ","_");
        return channelName;
    }

    /**
     * returns the hueMap merged with the user defined custom hue map (priority)
     */
    public static Map getMergedHueMap() {
        Map hm = new HashMap<>(ChannelToHue.hueMap);
        hm.putAll(ChannelToHue.userHueMap);
        return hm;
    }

    public static float[] getHues(final String[] channelNames, final Map hueMap) {
        if (channelNames==null) return null;
        if (hueMap==null) return null;
        float[] hues = new float[channelNames.length];
        for (int c=0; c0) {
            float[] hueMap = new float[multiChannelImage.getChannelNames().length];
            for (int c=0; c0 && multiChannelImage.getChannelNames()!=null && multiChannelImage.getChannelNames().length>0) {
            HashSet activeChannelLookup = new HashSet<>(Arrays.asList(featureDescription.getActiveFluoChannels()));
            float[] channelContributions = new float[multiChannelImage.getChannelNames().length];
            for (int c=0; c rmList = DALConfig.getImageProvider().LoadRawMetasByRawDataFileAndName(rdfId, RawUtilsCommon.STR_META_IMAGE_SCALE);
            scale = Double.parseDouble(rmList.get(0).getValue());
        } catch (Exception e) {
            logger.info("could not load image scale for image " + rdfId);
        }
        return scale;
    }

    public static ScaleAndUnit getImageScaleAndUnit(RawDataFile rdf) {
        double scale = 0d;
        String unit = "pixel";
        if (rdf != null) {
            scale = loadImageScale(rdf.getRawDataFileId());
        }
        if (scale == 0d) {
            scale = 1d;
            unit = "pixel";
        } else {
            unit = OrbitUtils.muMeterUnicode;
        }
        ScaleAndUnit sau = new ScaleAndUnit(scale, scale * scale, unit, unit + (char) 178);
        return sau;
    }


    public static boolean isInROI(int x, int y, Shape ROI, ExclusionMapGen exclusionMapGen) {
        if ((ROI == null) || (ROI.contains(x, y))) {
            if ((exclusionMapGen == null) || /*(exclusionMapGen.useForSegmentation()) ||*/ (!exclusionMapGen.isExcluded(x, y) || ((ROI != null) && (ROI instanceof ShapeAnnotationList) && (((ShapeAnnotationList) ROI)).containsExplicit(x, y)))) {
                return true;
            }
        }
        return false;
    }


    /**
     * Fuzzy check if a tile is inside the ROI. It only checks if one corner or the center of the tile is inside the ROI.
     * Might return false if a few pixels of the tile are inside the ROI!
     */
    public static boolean isTileInROI(int tileX, int tileY, final PlanarImage image, Shape ROI, ExclusionMapGen exclusionMapGen) {
        Rectangle rect = image.getTileRect(tileX,tileY);
        if (isInROI((int)rect.getMinX(),(int)rect.getMinY(),ROI,exclusionMapGen)) return true;   // top-left
        if (isInROI((int)rect.getMaxX(),(int)rect.getMinY(),ROI,exclusionMapGen)) return true;   // top-right
        if (isInROI((int)rect.getMinX(),(int)rect.getMaxY(),ROI,exclusionMapGen)) return true;   // bottom-left
        if (isInROI((int)rect.getMaxX(),(int)rect.getMaxY(),ROI,exclusionMapGen)) return true;   // bottom-right
        if (isInROI((int)rect.getCenterX(),(int)rect.getCenterY(),ROI,exclusionMapGen)) return true;   // bottom-right
        return false;
    }

    /**
     * Loads the combined annotation ROI. Set annotationGroup to 0 to load the annotations of all annotation groups.
     *
     * @param rdfId
     * @param annotationGroup
     * @return
     * @throws SQLException
     */
    public static IScaleableShape loadAnnotationROI(int rdfId, int annotationGroup) throws Exception {
        return loadAnnotationROI(rdfId, annotationGroup, false);
    }

    /**
     * Loads the combined annotation ROI. Set annotationGroup to 0 to load the annotations of all annotation groups.
     *
     * @param rdfId
     * @param annotationGroup
     * @return
     * @throws SQLException
     */
    public static IScaleableShape loadAnnotationROI(int rdfId, int annotationGroup, boolean otherGroupROIAsExclusion) throws Exception {
        return loadAnnotationROI(rdfId, annotationGroup, otherGroupROIAsExclusion, false);
    }


    /**
     * Loads the combined annotation ROI. Set annotationGroup to 0 to load the annotations of all annotation groups.
     *
     * @param rdfId
     * @param annotationGroup
     * @return
     * @throws SQLException
     */
    public static IScaleableShape loadAnnotationROI(int rdfId, int annotationGroup, boolean otherGroupROIAsExclusion, boolean exclusionsForAllGroups) throws Exception {
        List annotations = DALConfig.getImageProvider().LoadRawAnnotationsByRawDataFile(rdfId, RawAnnotation.ANNOTATION_TYPE_IMAGE);
        if (annotations != null && annotations.size() > 0) {
            IScaleableShape roi = new ShapeAnnotationList(annotations, annotationGroup, null, otherGroupROIAsExclusion, exclusionsForAllGroups);
            return roi;      // bounds can be null - this is explicitely allowed!
        } else return null;
    }

    public static double getROISize(RecognitionFrame rf, ExclusionMapGen exclMapGen) {
        double mumPP = rf.getMuMeterPerPixel() > 0 ? rf.getMuMeterPerPixel() : 1d;
        return OrbitUtils.getROISize(rf.bimg.getImage(), rf.getROI(), exclMapGen, mumPP);
    }

    public static double getROISize(OrbitTiledImage2 img, Shape roi, ExclusionMapGen exclusionMapGen, double mumPerPixel) {
        Rectangle bounds = img.getBounds();
        if (roi != null) {
            if (roi instanceof IScaleableShape) {
                roi = ((IScaleableShape) roi).getScaledInstance(100d, new Point(0, 0));
            }
            Rectangle roiBounds = roi.getBounds();
            if (roiBounds != null && roiBounds.getMinX() > 0 && roiBounds.getMinY() > 0)
                bounds.setLocation(roiBounds.x, roiBounds.y);
            if (roiBounds != null && roiBounds.getMaxX() < bounds.getMaxX() && roiBounds.getMaxY() < bounds.getMaxY())
                bounds.setSize(roiBounds.getSize());
        }
        return getROISize(img.getWidth(), img.getHeight(), bounds, roi, exclusionMapGen, mumPerPixel);
    }

    /**
     * Computes the ROI area in square mu meter. If bounds is null imgWidth*imgHeight*mumPerPixel*mumPerPixel will be returned.
     *
     * @param imgWidth
     * @param imgHeight
     * @param bounds
     * @param roi
     * @param exclusionMapGen
     * @param mumPerPixel
     * @return
     */
    public static double getROISize(int imgWidth, int imgHeight, Rectangle bounds, Shape roi, ExclusionMapGen exclusionMapGen, double mumPerPixel) {
        double mumPPSquare = mumPerPixel * mumPerPixel;
        if (bounds == null) {
            return (double) imgWidth * imgHeight * mumPPSquare;
        }
        if (roi == null && exclusionMapGen == null) {
            return bounds.getWidth() * bounds.getHeight() * mumPPSquare;
        }
        //System.out.println("minX:"+bounds.getMinX()+" maxX:"+bounds.getMaxX()+" minY:"+bounds.getMinY()+" maxY:"+bounds.getMaxY());
        if (roi != null) {
            if (roi instanceof IScaleableShape) {
                roi = ((IScaleableShape) roi).getScaledInstance(100d, new Point(0, 0));
            }
        }

        long pixelInROI = 0;
        double size = bounds.getWidth() * bounds.getHeight();
        final int inc = size < (5000 * 5000d) ? 1 : 3;
        for (int y = (int) bounds.getMinY(); y < bounds.getMaxY(); y += inc) {
            for (int x = (int) bounds.getMinX(); x < bounds.getMaxX(); x += inc) {
                if ((isInROI(x, y, roi, exclusionMapGen))) {
                    pixelInROI++;
                }
            }
            //System.out.println("y: "+y);
        }
        pixelInROI *= inc * inc;
        double area = (double) pixelInROI * mumPPSquare;
        //System.out.println("roiBB: "+roi.getBounds()+"  pixel: "+pixelInROI+"  mumPP: "+mumPerPixel+"  mumPPSquare: "+mumPPSquare);
        return area;
    }


    /**
     * formats time in seconds.
     *
     * @param s
     * @return
     */
    public static String formatTime(double s) {
        String d = "";
        if (s > 3600 * 24) {
            d = Integer.toString((int) (s / (3600 * 24))) + "d +";
            s -= 3600 * 24;
        }
        return d + dateFormat.get().format(new Date((long) s * 1000L - 3600000));
    }

    public static List buildDefaultClassShapes() {
        List classShapes = new ArrayList(3);
        classShapes.add(new ClassShape("Background", Color.darkGray, ClassShape.SHAPETYPE_POLYGONEXT));
        classShapes.add(new ClassShape("Celltype 1", RecognitionFrame.getColorByNum(1), ClassShape.SHAPETYPE_POLYGONEXT));
        classShapes.add(new ClassShape("Celltype 2", RecognitionFrame.getColorByNum(2), ClassShape.SHAPETYPE_POLYGONEXT));
        return classShapes;
    }

    public static List buildCellCountClassShapes() {
        List classShapes = new ArrayList(3);
        classShapes.add(new ClassShape("Background", Color.darkGray, ClassShape.SHAPETYPE_POLYGONEXT));
        classShapes.add(new ClassShape("Border", RecognitionFrame.getColorByNum(1), ClassShape.SHAPETYPE_POLYGONEXT));
        classShapes.add(new ClassShape("Cells", RecognitionFrame.getColorByNum(2), ClassShape.SHAPETYPE_POLYGONEXT));
        return classShapes;
    }


    /**
     * creates a new list of classShapes with cloned classShapes. The shapeList will be an empty list.
     *
     * @param classShapes
     * @return
     */
    public static List cloneClassShapes(List classShapes) {
        return cloneClassShapes(classShapes, false);
    }

    /**
     * creates a new list of classShapes with cloned classShapes.
     *
     * @param classShapes
     * @return
     */
    public static List cloneClassShapes(List classShapes, boolean keepShapes) {
        if (classShapes == null) return null;
        List csList = Collections.synchronizedList(new ArrayList(classShapes.size()));
        for (ClassShape cs : classShapes) {
            ClassShape newShape = cs.clone();
            if (!keepShapes)
                newShape.setShapeList(Collections.synchronizedList(new ArrayList())); // store empty list to save memory
            csList.add(newShape);
        }
        return csList;
    }

    

    /*
     * returns the available temp disk space in byte.
     */
    public static long getTempDiskSpace() {
        if (ScaleoutMode.SCALEOUTMODE.get()) return 100 * 1024 * 1024L;
        long space = -1L;
        try {
            File f = File.createTempFile("orbit", null);
            File tmpDir = f.getParentFile();
            space = tmpDir.getFreeSpace();
            f.delete();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return space;
    }

    public static String getTempDir() {
        String s = null;
        try {
            File f = File.createTempFile("orbit", null);
            s = f.getParentFile().getAbsolutePath();
            f.delete();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return s;
    }


    public static void cleanUpTemp() {
        if (DiskMemImageOrbit.getCommonTileCache() != null)
            DiskMemImageOrbit.getCommonTileCache().flush();
        //DiskMemImage.getCommonTileCache().removeNullTiles();

        //manually remove existing temp files
        try {
            File f = File.createTempFile(DiskCachedTile.FILE_PREFIX, DiskCachedTile.FILE_SUFFIX, DiskCachedTile.getCacheFolder());
            File tmpDir = f.getParentFile();
            f.delete();
            logger.debug("Cleaning up tile temp folder: " + tmpDir + "... ");
            if (tmpDir != null) {
                FilenameFilter filter = new FilenameFilter() {
                    public boolean accept(File dir, String name) {
                        return name.startsWith(DiskCachedTile.FILE_PREFIX) ||
                                name.startsWith("jai-FCSS-");
                    }
                };
                File[] files = tmpDir.listFiles(filter);
                if ((files != null) && (files.length > 0)) {
                    for (File tf : files) {
                        if (tf.isFile()) tf.deleteOnExit(); // delete file when vm terminates
                        //System.out.println(tf);
                    }
                }
            }
            logger.trace("done.");

        } catch (IOException e) {
            e.printStackTrace();
        }

    }

    /**
     * Parses the params for key and returns value. The params have to be in the form
     * -key1 value1 -key2 value2 ... 
* Everything is treated as string.
* If the key is not found or params is null or params.length<2 null will be returned. * * @param key * @param params * @return */ public static String parseParams(String key, String[] params) { if (params == null) return null; if (params.length < 2) return null; for (int i = 0; i < params.length - 1; i++) { if (params[i].equalsIgnoreCase("-" + key) && (!params[i + 1].startsWith("-"))) { return params[i + 1]; } } return null; } public static double parseDouble(String s, double NanValue) { double d = NanValue; try { d = Double.parseDouble(s.replaceAll(",", "\\.")); } catch (Exception e) { d = NanValue; } return d; } public static int parseInt(String s, int NanValue) { int i = NanValue; try { i = Integer.parseInt(s); } catch (Exception e) { i = NanValue; } return i; } /** * returns the position (starting from 0) of a wellname with leading 0, e.g. A01 -> 0,0 (A1 also works) * * @param wellName * @return */ public static Point getWellPos(String wellName) throws IllegalArgumentException { if (wellName == null || wellName.length() < 2) throw new IllegalArgumentException("not a valid wellname: " + wellName); int y = wellName.charAt(0) - (byte) ('A'); String s = String.valueOf(wellName.charAt(1)); if (wellName.length() > 2) { s += wellName.charAt(2); } try { int x = Integer.parseInt(s); return new Point(x - 1, y); } catch (Exception e) { throw new IllegalArgumentException("not a valid wellname: " + wellName); } } /** * returns the well name (e.g. A01) based on the well position (x,y) (x and y starting from 0) * * @param x * @param y * @return */ public static String getWellName(int x, int y) { char wy = ((char) (y + (byte) ('A'))); String wellName = wy + "" + String.format("%1$02d", x + 1); return wellName; } /** * returns the well name (e.g. A1) based on the well position (x,y) (x and y starting from 0) * * @param x * @param y * @return */ public static String getWellNameShort(int x, int y) { char wy = ((char) (y + (byte) ('A'))); String wellName = wy + "" + String.format("%1$01d", x + 1); return wellName; } /** * waits until worker.isDone or worker.isCancelled is true * * @param worker */ public static void waitForWorker(OrbitWorker worker) { while ((!worker.isDone()) || worker.isCancelled()) { try { Thread.sleep(100); } catch (InterruptedException e) { e.printStackTrace(); } } } /** * creates a html document, lines beginning with # are headings and lines with multi tabs are table blocks. * * @return */ public static String text2SmartHtml(String text) { final String sep = "\t"; String color = OrbitUtils.DARKUI ? " color=white" : ""; StringBuilder sb = new StringBuilder(); sb.append(""); boolean tableBlock = false; String s; String lines[] = text.split("\\r?\\n"); for (String line : lines) { if (line.trim().startsWith("#")) { if (tableBlock) { tableBlock = false; sb.append(""); } s = line.trim().replaceFirst("#", "

") + "

"; sb.append(s); } else { String[] tabs = line.split(sep); if (tabs != null && tabs.length > 1) { // table block if (!tableBlock) { // header tableBlock = true; sb.append(""); for (String col : tabs) { sb.append(""); } sb.append(""); } else { // data sb.append(""); for (String col : tabs) { sb.append(""); } sb.append(""); } } else { if (tableBlock) { tableBlock = false; sb.append("
" + col + "
" + col + "
"); } sb.append(line + "
"); } } } sb.append(""); return sb.toString(); } /** * returns a new e.g. file (or annotation) name so that it is a unique name. It appends (1), (2)... at the end. * * @param otherNames * @return */ public static String getNewName(String name, HashSet otherNames) { if (otherNames.contains(name)) { int copyNr = 1; String newName = name; String subName = name; if (newName.length() >= 3 && newName.endsWith(")")) { int idx = newName.lastIndexOf("("); if (idx <= newName.length() - 2) { try { String sub = newName.substring(idx + 1, newName.length() - 1); copyNr = Integer.parseInt(sub) + 1; } catch (Exception e) { } subName = newName.substring(0, idx); } } while (otherNames.contains(newName = subName + "(" + copyNr + ")")) { copyNr++; } return newName; } return name; } public static double log2(double d) { return Math.log(d) / Math.log(2d); } /** * returns true if the image dimensions <= 3000x3000, otherwise false * * @param image * @return */ public static boolean isSmallImage(RenderedImage image) { return (((long) image.getWidth() * image.getHeight()) <= (3000L * 3000L)); } public static String getTag() { return TAG; } public static void openPdfUrl(String url) { logger.trace("trying to open pdf in external viewer"); try { if (Desktop.isDesktopSupported()) { Desktop.getDesktop().browse(new URI(url)); } else { File tmp = File.createTempFile("Orbit_", ".pdf"); tmp.deleteOnExit(); OutputStream os = new FileOutputStream(tmp); RawUtilsCommon.getContentToOutputstream(new URL(url), os); os.close(); openPdf(tmp.getAbsolutePath()); } } catch (Exception ex) { logger.error("error showing pdf file: " + ex.getMessage()); } } public static void openPdf(String filename) { if (new File(filename).exists()) { try { String os = System.getProperty("os.name").toLowerCase(); if (os.startsWith("windows")) { Runtime.getRuntime().exec("cmd /c start " + filename); } else if (os.startsWith("mac")) { Runtime.getRuntime().exec("open " + filename); } else { // assume linux Runtime.getRuntime().exec("acroread " + filename); } } catch (IOException e) { logger.error("cannot open pdf: " + e.getMessage()); } } } public static JFileChooser buildOpenFileFileChooser() { return buildOpenFileFileChooser(null); } public static JFileChooser buildOpenFileFileChooser(final ChangeListener seriesChangeListener) { JFileChooser fileChooser = new JFileChooser(); ImagePreviewWithSeries preview = new ImagePreviewWithSeries(fileChooser, seriesChangeListener); fileChooser.setAccessory(preview); fileChooser.setMultiSelectionEnabled(true); fileChooser.setDialogTitle("Open File(s)"); fileChooser.setFileSelectionMode(JFileChooser.FILES_ONLY); fileChooser.setFileFilter(new javax.swing.filechooser.FileFilter() { LocalFileFilter filter = new LocalFileFilter(); @Override public boolean accept(File f) { return filter.accept(f); } @Override public String getDescription() { return "Image Files (jpg,jp2,png,bmp,pcx,tga,dcm,tif,tiff,tf2,tf8,btf,svs,ndpi,ndpis,czi,afi,ims,vsi,scn,sld)"; } }); return fileChooser; } /** * Returns the MD5 of the fist 50mb (max) of a file. * @param fileName * @return * @throws NoSuchAlgorithmException * @throws IOException */ public static String getDigest(String fileName) throws NoSuchAlgorithmException, IOException { long startT = System.currentTimeMillis(); int maxLen = 1024*1024*50; // 1MB String res = ""; MessageDigest md = MessageDigest.getInstance("MD5"); File file = new File(fileName); int len = (int)Math.min(file.length(),maxLen); byte[] buffer = new byte[len]; FileInputStream fis = null; try { fis = new FileInputStream(file); fis.read(buffer); md.update(buffer); byte[] digest = md.digest(); res = encodeHexString(digest); } finally { try { if (fis!=null) fis.close(); } catch (IOException e) { } } long usedT = System.currentTimeMillis()-startT; System.out.println("usedTime: "+usedT); return res; } final protected static char[] HEXARRAY = "0123456789abcdef".toCharArray(); public static String encodeHexString( byte[] bytes ) { char[] hexChars = new char[bytes.length * 2]; for (int j = 0; j < bytes.length; j++) { int v = bytes[j] & 0xFF; hexChars[j * 2] = HEXARRAY[v >>> 4]; hexChars[j * 2 + 1] = HEXARRAY[v & 0x0F]; } return new String(hexChars); } public static String generateUniqueFilename(String prefix, String ending) { return prefix + UUID.randomUUID().toString() + ending; } /** * Used for classification / quantification. * Apply raster modifications like color deconvolution. * The output will be a ModifiedRaster. If the input is already a ModifiedRaster, no modification will be done. * * @param readRaster * @return */ public static Raster getModifiedRaster(final Raster readRaster, final FeatureDescription featureDescription, final ColorModel colorModel, final int level) { return getModifiedRaster(readRaster, featureDescription, colorModel, false, 0, 0, "", level); } /** * Used for classification / quantification. * Apply raster modifications like color deconvolution. * The output will be a ModifiedRaster. If the input is already a ModifiedRaster, no modification will be done. * tileX, tileY and name are just for caching. * As raster identifier the raster hashcode will be appended to the name. * * @param readRaster * @return */ public static Raster getModifiedRaster(final Raster readRaster, final FeatureDescription featureDescription, final ColorModel colorModel, boolean useCache, int tileX, int tileY, String name, int level) { if ((!(readRaster instanceof ModifiedRaster)) && (featureDescription.getDeconvChannel() > 0)) { PointAndName key = new PointAndName(tileX, tileY, name + readRaster.hashCode(),level, 100, 100, 100, 0, 0, 0, 0, null, null, null, null, true, true, true, featureDescription.getDeconvChannel(), featureDescription.getDeconvName(),null, true, null); Raster cachedRaster = null; if (useCache) OrbitTiledImage2.tileCache.getIfPresent(key); if (cachedRaster != null) { return cachedRaster; } else { Rectangle oriBounds = readRaster.getBounds(); WritableRaster r = Raster.createWritableRaster(readRaster.getSampleModel(), readRaster.getDataBuffer(), new Point(readRaster.getMinX(), readRaster.getMinY())); r.setDataElements(0, 0, readRaster); WritableRaster wr = Raster.createWritableRaster(r.getSampleModel(), r.getDataBuffer(), new Point(0, 0)); BufferedImage bb = new BufferedImage(colorModel, wr, colorModel.isAlphaPremultiplied(), null); if (featureDescription.getDeconvChannel() > 0) { bb = Colour_Deconvolution.getProcessedImage(bb, featureDescription.getDeconvName(), featureDescription.getDeconvChannel() - 1, null); } ModifiedRaster rbb = new ModifiedRaster(bb.getRaster().createTranslatedChild(oriBounds.x, oriBounds.y)); if (useCache) OrbitTiledImage2.tileCache.put(key, rbb); return rbb; } } else return readRaster; } /** * returns null if no image adjustments are available in db * * @param rdfId * @return * @throws SQLException */ public static ImageAdjustments getAndParseImageAdjustments(int rdfId) throws Exception { List rms = DALConfig.getImageProvider().LoadRawMetasByRawDataFileAndName(rdfId, RawUtilsCommon.STR_META_IMAGEADJUSTMENTS); if (rms != null && rms.size() > 0) { RawMeta rm = rms.get(0); return parseImageAdjustments(rm.getValue()); } return null; } /** * parses imageAdjustment values, e.g. bri:0;con:232;r:0;g:0;b:0;gamma:100;deconvChan:0;deconvName:H&E * * @param vals * @return */ public static ImageAdjustments parseImageAdjustments(String vals) { int gamma = 100; int brightness = 0; int contrast = 100; int red = 0; int green = 0; int blue = 0; int deconvChannel = 0; String deconvName = Colour_Deconvolution.DECONV_NONE; float[] channelContributions = null; String[] split = vals.split(";"); if (split != null && split.length >= 5) { brightness = Integer.parseInt(split[0].split(":")[1]); contrast = Integer.parseInt(split[1].split(":")[1]); red = Integer.parseInt(split[2].split(":")[1]); green = Integer.parseInt(split[3].split(":")[1]); blue = Integer.parseInt(split[4].split(":")[1]); if (split.length > 5) gamma = Integer.parseInt(split[5].split(":")[1]); if (split.length > 6) deconvChannel = Integer.parseInt(split[6].split(":")[1]); if (split.length > 7) deconvName = split[7].split(":")[1]; if (split.length > 8) { if (split[8].split(":")[0].equalsIgnoreCase("channelContributions")) { String[] contribs = split[8].split(":")[1].split("_"); // e.g. 1.5699999_0.79999995 if (contribs!=null) { channelContributions = new float[contribs.length]; for (int c=0; c;con:;r:;g:;b:;gamma:;deconvChan:;deconvName:. Current string is " + vals); } ImageAdjustments ia = new ImageAdjustments(); ia.setBrightness(brightness); ia.setContrast(contrast); ia.setGamma(gamma); ia.setRed(red); ia.setGreen(green); ia.setBlue(blue); ia.setDeconvChannel(deconvChannel); ia.setDeconvName(deconvName); ia.setChannelContributions(channelContributions); return ia; } public static class ImageAdjustments implements Serializable { private int gamma = 100; private int brightness = 0; private int contrast = 100; private int red = 0; private int green = 0; private int blue = 0; private int deconvChannel = 0; private String deconvName = Colour_Deconvolution.DECONV_NONE; private float[] channelContributions; public ImageAdjustments() { } public int getBlue() { return blue; } public void setBlue(int blue) { this.blue = blue; } public int getBrightness() { return brightness; } public void setBrightness(int brightness) { this.brightness = brightness; } public int getContrast() { return contrast; } public void setContrast(int contrast) { this.contrast = contrast; } public int getDeconvChannel() { return deconvChannel; } public void setDeconvChannel(int deconvChannel) { this.deconvChannel = deconvChannel; } public String getDeconvName() { return deconvName; } public void setDeconvName(String deconvName) { this.deconvName = deconvName; } public int getGamma() { return gamma; } public void setGamma(int gamma) { this.gamma = gamma; } public int getGreen() { return green; } public void setGreen(int green) { this.green = green; } public int getRed() { return red; } public void setRed(int red) { this.red = red; } public float[] getChannelContributions() { return channelContributions; } public void setChannelContributions(float[] channelContributions) { this.channelContributions = channelContributions; } } /** * used to store pre-computed min,max values */ public static class ImageAdjustCachedParams implements Serializable { private double gammaMin = 0; private double gammaMax = 0; private boolean gammaExtremaSet = false; private double contrastAverage = 0; private boolean contrastAverageSet = false; public double getContrastAverage() { return contrastAverage; } public void setContrastAverage(double contrastAverage) { this.contrastAverage = contrastAverage; } public boolean isContrastAverageSet() { return contrastAverageSet; } public void setContrastAverageSet(boolean contrastAverageSet) { this.contrastAverageSet = contrastAverageSet; } public boolean isGammaExtremaSet() { return gammaExtremaSet; } public void setGammaExtremaSet(boolean gammaExtremaSet) { this.gammaExtremaSet = gammaExtremaSet; } public double getGammaMax() { return gammaMax; } public void setGammaMax(double gammaMax) { this.gammaMax = gammaMax; } public double getGammaMin() { return gammaMin; } public void setGammaMin(double gammaMin) { this.gammaMin = gammaMin; } } public static class ScaleAndUnit implements Serializable { private double scale = 1d; private double scaleSquare = 1d; private String unit = OrbitUtils.muMeterUnicode; private String unitSquare = unit + (char) 178; public ScaleAndUnit() { } public ScaleAndUnit(double scale, double scaleSquare, String unit, String unitSquare) { this.scale = scale; this.scaleSquare = scaleSquare; this.unit = unit; this.unitSquare = unitSquare; } public double getScale() { return scale; } public void setScale(double scale) { this.scale = scale; } public double getScaleSquare() { return scaleSquare; } public void setScaleSquare(double scaleSquare) { this.scaleSquare = scaleSquare; } public String getUnit() { return unit; } public void setUnit(String unit) { this.unit = unit; } public String getUnitSquare() { return unitSquare; } public void setUnitSquare(String unitSquare) { this.unitSquare = unitSquare; } } public static void main(String[] args) throws IOException, NoSuchAlgorithmException { String fn = "d:\\pic\\4059.svs"; String digest = OrbitUtils.getDigest(fn); System.out.println(digest); } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy