ijfx.ui.display.image.DefaultFXImageDisplay.java Source code

Java tutorial

Introduction

Here is the source code for ijfx.ui.display.image.DefaultFXImageDisplay.java

Source

/*
This file is part of ImageJ FX.
    
ImageJ FX 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.
    
ImageJ FX 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 ImageJ FX.  If not, see <http://www.gnu.org/licenses/>. 
    
 Copyright 2015,2016 Cyril MONGIS, Michael Knop
       
 */
package ijfx.ui.display.image;

import ijfx.core.image.DisplayRangeService;
import ijfx.core.timer.Timer;
import ijfx.core.timer.TimerService;
import ijfx.core.utils.AxisUtils;
import ijfx.ui.main.ImageJFX;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
import java.util.logging.Level;
import java.util.stream.IntStream;
import javafx.application.Platform;
import javafx.beans.property.IntegerProperty;
import javafx.beans.property.ReadOnlyProperty;
import javafx.beans.property.SimpleIntegerProperty;
import javafx.beans.property.adapter.JavaBeanDoubleProperty;
import javafx.beans.property.adapter.JavaBeanDoublePropertyBuilder;
import javafx.beans.property.adapter.JavaBeanObjectPropertyBuilder;
import javafx.beans.property.adapter.JavaBeanProperty;
import net.imagej.Dataset;
import net.imagej.axis.Axes;
import net.imagej.axis.AxisType;
import net.imagej.display.DatasetView;
import net.imagej.display.DefaultImageDisplay;
import net.imagej.display.ImageDisplayService;
import net.imglib2.display.ColorTable;
import org.apache.commons.lang3.ArrayUtils;
import org.scijava.Priority;
import org.scijava.display.Display;
import org.scijava.plugin.Parameter;
import org.scijava.plugin.Plugin;
import rx.subjects.PublishSubject;

/**
 *
 * @author Cyril MONGIS
 */
@Plugin(type = Display.class, priority = Priority.HIGH_PRIORITY)
public class DefaultFXImageDisplay extends DefaultImageDisplay implements FXImageDisplay {

    /*
    Services
     */
    @Parameter
    private ImageDisplayService imageDisplayService;

    @Parameter
    private DisplayRangeService displayRangeService;

    @Parameter
    private TimerService timerService;

    /*
    Properties
     */
    private JavaBeanProperty<ColorTable> currentLUTProperty;

    private JavaBeanDoubleProperty currentLUTMinProperty;

    private JavaBeanDoubleProperty currentLUTMaxProperty;

    private JavaBeanDoubleProperty datasetMinProperty;

    private JavaBeanDoubleProperty datasetMaxProperty;

    private JavaBeanProperty<Number> currentChannelProperty;

    private JavaBeanProperty<int[]> compositeChannelsProperty;

    private IntegerProperty refreshPerSecond = new SimpleIntegerProperty();

    private final PublishSubject<Integer> publishSubject = PublishSubject.create();

    private final ExecutorService refreshThread = Executors.newFixedThreadPool(1);

    private final Boolean updateLock = Boolean.TRUE;

    public DefaultFXImageDisplay() {
        super();

        publishSubject.observeOn(ImageJFX.getPublishSubjectScheduler()).buffer(1, TimeUnit.SECONDS)
                .subscribe(list -> Platform.runLater(() -> refreshPerSecond.setValue(list.size())));

    }

    private DatasetView getDatasetView() {

        return imageDisplayService.getActiveDatasetView(this);

    }

    private Dataset getDataset() {
        return getDatasetView().getData();
    }

    public void updateAsync() {
        refreshThread.execute(() -> {
            if (getDatasetView() == null) {
                return;
            }
            Timer timer = timerService.getTimer(FXImageDisplay.class);
            timer.start();
            getDatasetView().getProjector().map();

            update();
            timer.elapsed("projection");
        });
    }

    @Override
    public void setCurrentLUT(ColorTable table) {

        table = displayRangeService.getEquivalentTable(table);
        getDataset().setColorTable(table, getCurrentChannel());
        getDatasetView().setColorTable(table, getCurrentChannel());
        updateAsync();
        currentLUTProperty.fireValueChangedEvent();
    }

    @Override
    public ColorTable getCurrentLUT() {
        return displayRangeService.getEquivalentTable(getDatasetView().getColorTables().get(getCurrentChannel()));
    }

    @Override
    public JavaBeanProperty<ColorTable> currentLUTProperty() {
        if (currentLUTProperty == null) {
            currentLUTProperty = generateBean("currentLUT");
        }
        return currentLUTProperty;
    }

    @Override
    public void setCurrentLUTMin(double min) {

        getDatasetView().setChannelRange(getCurrentChannel(), min, getCurrentLUTMax());
        getDataset().setChannelMinimum(getCurrentChannel(), min);

        currentLUTMinProperty().fireValueChangedEvent();

        updateAsync();
    }

    @Override
    public double getCurrentLUTMin() {
        double value = getDatasetView().getChannelMin(getCurrentChannel());
        return value;
    }

    @Override
    public JavaBeanDoubleProperty currentLUTMinProperty() {
        if (currentLUTMinProperty == null) {
            currentLUTMinProperty = generateDoubleBean("currentLUTMin");
        }
        return currentLUTMinProperty;
    }

    @Override
    public void setCurrentLUTMax(double max) {

        getDatasetView().setChannelRange(getCurrentChannel(), getCurrentLUTMin(), max);
        getDataset().setChannelMaximum(getCurrentChannel(), max);

        currentLUTMaxProperty().fireValueChangedEvent();
        updateAsync();
    }

    @Override
    public double getCurrentLUTMax() {
        double max = getDatasetView().getChannelMax(getCurrentChannel());
        return max;
    }

    @Override
    public JavaBeanDoubleProperty currentLUTMaxProperty() {
        if (currentLUTMaxProperty == null) {
            currentLUTMaxProperty = generateDoubleBean("currentLUTMax");
        }
        return currentLUTMaxProperty;
    }

    @Override
    public double getDatasetMin() {

        double min = displayRangeService.getDatasetMinimum(getDatasetView().getData(), getCurrentChannel())
                .doubleValue();

        return min;

    }

    @Override
    public double getDatasetMax() {
        double max = displayRangeService.getDatasetMaximum(getDatasetView().getData(), getCurrentChannel())
                .doubleValue();
        return max;
    }

    @Override
    public JavaBeanDoubleProperty datasetMinProperty() {
        if (datasetMinProperty == null) {
            datasetMinProperty = generateDoubleBean("datasetMin");
        }
        return datasetMinProperty;
    }

    //Dummy functions
    public void setDatasetMin(double min) {
    }

    //Dummy functions
    public void setDatasetMax(double max) {
    }

    @Override
    public JavaBeanDoubleProperty datasetMaxProperty() {
        if (datasetMaxProperty == null) {
            datasetMaxProperty = generateDoubleBean("datasetMax");
        }
        return datasetMaxProperty;
    }

    /*
    Current channel
     */
    @Override
    public void setCurrentChannel(int channel) {
        if (AxisUtils.hasAxisType(this, Axes.CHANNEL)) {

            setPosition(channel, Axes.CHANNEL);

            updateAsync();
        } else {
            datasetMinProperty().fireValueChangedEvent();
            datasetMaxProperty().fireValueChangedEvent();
            currentLUTProperty().fireValueChangedEvent();
            currentLUTMinProperty().fireValueChangedEvent();
            currentLUTMaxProperty().fireValueChangedEvent();
        }
    }

    @Override
    public void setPosition(long position, AxisType axisType) {
        super.setPosition(position, axisType);
        if (Axes.CHANNEL.equals(axisType)) {
            currentChannelProperty().fireValueChangedEvent();

            datasetMinProperty().fireValueChangedEvent();
            datasetMaxProperty().fireValueChangedEvent();

            currentLUTProperty().fireValueChangedEvent();
            currentLUTMinProperty().fireValueChangedEvent();
            currentLUTMaxProperty().fireValueChangedEvent();
            currentLUTMinProperty().fireValueChangedEvent();
            currentLUTMaxProperty().fireValueChangedEvent();

        }
    }

    @Override
    public JavaBeanProperty<Number> currentChannelProperty() {
        if (currentChannelProperty == null) {
            currentChannelProperty = generateBean("currentChannel");
        }
        return currentChannelProperty;
    }

    @Override
    public int getCurrentChannel() {
        if (AxisUtils.hasAxisType(this, Axes.CHANNEL)) {
            return getIntPosition(Axes.CHANNEL);
        } else {
            return 0;
        }
    }

    /*
    Channel activation
     */
    public void setCompositeChannels(int[] channels) {
        for (int i = 0; i != getChannelNumber(); i++) {
            setChannelComposite(i, ArrayUtils.contains(channels, i), true);
        }
        compositeChannelsProperty().fireValueChangedEvent();
    }

    public int[] getCompositeChannels() {
        if (getDatasetView().getProjector() == null) {
            return new int[0];
        }
        return IntStream.range(0, getChannelNumber()).filter(i -> getDatasetView().getProjector().isComposite(i))
                .toArray();
    }

    public void setChannelComposite(int channel, boolean activated) {
        setChannelComposite(channel, activated, false);
    }

    public void setChannelComposite(int channel, boolean activated, boolean silent) {
        getDatasetView().getProjector().setComposite(channel, activated);

        if (!silent) {
            compositeChannelsProperty().fireValueChangedEvent();
        }
    }

    public JavaBeanProperty<int[]> compositeChannelsProperty() {
        if (compositeChannelsProperty == null) {
            compositeChannelsProperty = generateBean("compositeChannels");
            localize(new long[2]);
        }
        return compositeChannelsProperty;
    }

    /*
    Helper classes
     */
    public int getChannelNumber() {

        if (AxisUtils.hasAxisType(this, Axes.CHANNEL)) {
            return (int) dimension(dimensionIndex(Axes.CHANNEL));
        } else {
            return 1;
        }
    }

    private <T> JavaBeanProperty<T> generateBean(String name) {
        try {
            return JavaBeanObjectPropertyBuilder.create().bean(this).name(name).build();
        } catch (Exception e) {
            ImageJFX.getLogger().log(Level.SEVERE, null, e);
        }
        return null;
    }

    private <T> JavaBeanDoubleProperty generateDoubleBean(String name) {
        try {
            return JavaBeanDoublePropertyBuilder.create().bean(this).name(name).build();
        } catch (Exception e) {
            ImageJFX.getLogger().log(Level.SEVERE, null, e);
        }
        return null;
    }

    private <T> ReadOnlyProperty<T> generateReadOnlyBean(String name) {
        try {
            return JavaBeanObjectPropertyBuilder.create().bean(this).name(name).build();
        } catch (Exception e) {
            ImageJFX.getLogger().log(Level.SEVERE, null, e);
        }
        return null;
    }

    @Override
    public void update() {
        publishSubject.onNext(1);
        checkLUProperties();
        super.update();
    }

    public void checkProperties() {
        currentLUTProperty().fireValueChangedEvent();
    }

    private void checkLUProperties() {

        currentLUTMinProperty().fireValueChangedEvent();
        currentLUTMaxProperty().fireValueChangedEvent();

    }

    public IntegerProperty refreshPerSecond() {
        return refreshPerSecond;
    }
}