text:
package org.earthtime.plots.evolution;

import Jama.Matrix;
import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Cursor;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Shape;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseWheelEvent;
import java.awt.geom.Path2D;
import java.awt.geom.Point2D;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.io.UnsupportedEncodingException;
import java.io.Writer;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import java.util.SortedSet;
import java.util.Vector;
import java.util.stream.Collectors;
import java.util.stream.DoubleStream;
import javax.swing.JMenuItem;
import javax.swing.JPopupMenu;
import org.apache.batik.apps.rasterizer.SVGConverter;
import org.apache.batik.apps.rasterizer.SVGConverterException;
import org.apache.batik.dom.GenericDOMImplementation;
import org.apache.batik.svggen.SVGGraphics2D;
import org.apache.batik.svggen.SVGGraphics2DIOException;
import org.apache.commons.math3.analysis.interpolation.LinearInterpolator;
import org.apache.commons.math3.analysis.polynomials.PolynomialSplineFunction;
import static org.earthtime.UPb_Redux.ReduxConstants.SEAWATER_GREEN;
import org.earthtime.UPb_Redux.dateInterpretation.concordia.PlottingDetailsDisplayInterface;
import org.earthtime.UPb_Redux.valueModels.SampleDateModel;
import org.earthtime.UPb_Redux.valueModels.ValueModel;
import org.earthtime.dataDictionaries.RadDates;
import org.earthtime.dataDictionaries.UThAnalysisMeasures;
import org.earthtime.fractions.ETFractionInterface;
import org.earthtime.plots.AbstractDataView;
import org.earthtime.plots.PlotAxesSetupInterface;
import org.earthtime.plots.evolution.openSystem.OpenSystemIsochronModelEntry;
import org.earthtime.plots.evolution.openSystem.OpenSystemIsochronTableModel;
import org.earthtime.plots.evolution.seaWater.SeaWaterInitialDelta234UTableModel;
import org.earthtime.plots.isochrons.IsochronModel;
import org.earthtime.projects.ProjectSample;
import org.earthtime.reportViews.ReportUpdaterInterface;
import org.earthtime.samples.SampleInterface;
import org.earthtime.utilities.TicGeneratorForAxes;
import org.w3c.dom.DOMImplementation;
import org.w3c.dom.Document;

/**
 *
 * @author James F. Bowring
 */
public final class EvolutionPlotPanel extends AbstractDataView implements PlottingDetailsDisplayInterface {

    protected transient ReportUpdaterInterface reportUpdater;

    private static SampleInterface sample;
    private static boolean showMatrix = true;

    private double[] annumIsochrons;
    private double[] ar48icntrs;
    private boolean ar48icntrsDsplayAsDeltaUnits;
    private boolean yAxisDisplayAsDeltaUnits;

    private double[][] xEndPointsD;
    private double[][] yEndPointsD;

    private double[][] tv;
    private double[][][] xy;
    private double[][][] dardt;
    private double[][] tvsw;
    private double[][][] xysw;
    private double[][][] dardtsw;

    private double[][] tvLabels;
    private double[][][] xyLabels;

    private List<OpenSystemIsochronTableModel> openSystemIsochronModelsList;

    public EvolutionPlotPanel(SampleInterface mySample, ReportUpdaterInterface reportUpdater) {
        super();

        this.leftMargin = 40;
        this.topMargin = 40;
        this.graphWidth = 500;
        this.graphHeight = 500;
        this.xLocation = 0;

        this.showMe = true;

        this.setBounds(xLocation, 0, graphWidth + leftMargin * 2, graphHeight + topMargin * 2);

        setOpaque(true);

        setBackground(Color.white);
        this.sample = mySample;
        this.reportUpdater = reportUpdater;

        this.selectedFractions = new Vector<>();
        this.excludedFractions = new Vector<>();

        this.annumIsochrons = new double[]{};
        this.ar48icntrs = new double[]{};
        this.xAxisMax = 0;
        this.yAxisMax = 0;
        this.xEndPointsD = new double[][]{{}};
        this.yEndPointsD = new double[][]{{}};
        this.tv = new double[][]{{}};
        this.xy = new double[0][0][0];
        this.dardt = new double[0][0][0];
        this.tvLabels = new double[][]{{}};
        this.xyLabels = new double[0][0][0];

        this.ticsYaxis = new BigDecimal[0];
        this.ticsXaxis = new BigDecimal[0];

        this.eastResizing = false;
        this.southResizing = false;

        this.zoomCount = 0;

        putInImageModePan();

        this.showCenters = true;
        this.showLabels = false;

        this.yAxisDisplayAsDeltaUnits = false;

        openSystemIsochronModelsList = new ArrayList<>();

        addMouseListener(this);
        addMouseMotionListener(this);
        addMouseWheelListener(this);

    }

    @Override
    public void paintComponent(Graphics g) {
        if (showMe) {
            super.paintComponent(g);

            paint((Graphics2D) g, false);
        }
    }

    public void paint(Graphics2D g2d, boolean svgStyle) {
        if (showMe) {
            paintInit(g2d);

            //draw component border
            g2d.setPaint(Color.blue);
            g2d.drawRect(0, 0, (int) graphWidth + leftMargin * 2 - 1, (int) graphHeight + topMargin * 2 - 1);

            // draw graph border
            g2d.setPaint(Color.black);
            g2d.drawRect(leftMargin, topMargin, (int) graphWidth, (int) graphHeight);

            // draw isochrons
            double[] yItercepts = new double[xEndPointsD[0].length];
            double[] slopes = new double[xEndPointsD[0].length];
            g2d.setPaint(Color.red);
            for (int i = 0; i < annumIsochrons.length; i++) {
                slopes[i] = (yEndPointsD[1][i] - yEndPointsD[0][i]) / (xEndPointsD[1][i] - xEndPointsD[0][i]);
                yItercepts[i] = yEndPointsD[0][i] - slopes[i] * xEndPointsD[0][i];

                Shape isochronLine = new Path2D.Double();
                g2d.setStroke(new BasicStroke(1.75f));
                ((Path2D) isochronLine).moveTo(//
                        mapX(xEndPointsD[0][i]), //
                        mapY(yItercepts[i] + slopes[i] * xEndPointsD[0][i]));
                ((Path2D) isochronLine).lineTo( //
                        mapX(getMaxX_Display()), //
                        mapY(yItercepts[i] + slopes[i] * getMaxX_Display()));

                if ((i == (annumIsochrons.length - 1))
                        && annumIsochrons[i] >= 10e10) {
                    g2d.setPaint(Color.black);
                }
                g2d.draw(isochronLine);

            }

            // draw initDelta234U contour lines
            g2d.setPaint(Color.blue);
            // determine what curves should plot
            int lowIndex = 0;
            int highIndex = ar48icntrs.length;
            for (int index = 0; index < ar48icntrs.length; index++) {
                if (Math.abs(ar48icntrs[index]) < getMinY_Display()) {
                    lowIndex = index;
                    if (lowIndex == 1) {
                        lowIndex = 0;
                    }
                }
                if (Math.abs(ar48icntrs[index]) < getMaxY_Display()) {
                    highIndex = Math.min(ar48icntrs.length - 1, index + 6 + (zoomCount / 10) * 1);
                }
            }
            for (int i = lowIndex; i < highIndex; i++) {
                boolean labelPrinted = false;

                if (ar48icntrs[i] >= 0.0) {
                    Path2D curvedP = new Path2D.Double(Path2D.WIND_NON_ZERO);
                    curvedP.moveTo(
                            (float) mapX(xy[i][0][0]),
                            (float) mapY(xy[i][1][0]));

                    for (int j = 1; j < tv[i].length; j++) {
                        double deltaTOver3 = (tv[i][j] - tv[i][j - 1]) / 3;

                        curvedP.curveTo(//
                                (float) mapX(xy[i][0][j - 1] + deltaTOver3 * dardt[i][0][j - 1]),
                                (float) mapY(xy[i][1][j - 1] + deltaTOver3 * dardt[i][1][j - 1]),
                                (float) mapX(xy[i][0][j] - deltaTOver3 * dardt[i][0][j]),
                                (float) mapY(xy[i][1][j] - deltaTOver3 * dardt[i][1][j]),
                                (float) mapX(xy[i][0][j]),
                                (float) mapY(xy[i][1][j]));
                    }
                    g2d.draw(curvedP);

                    for (int j = 1; j < tvLabels[i].length; j++) {
                        String displayString = "";
                        if (ar48icntrsDsplayAsDeltaUnits) {
                            displayString = new BigDecimal((Math.abs(ar48icntrs[i]) - 1.0) * 1000.0).setScale(1, RoundingMode.HALF_UP).toPlainString();
                        } else {
                            displayString = new BigDecimal(Math.abs(ar48icntrs[i])).setScale(3, RoundingMode.HALF_UP).toPlainString();
                        }
                        if (!labelPrinted && (xyLabels[i][0][j - 1] > getMinX_Display()) && (ar48icntrs[i] > 0.0)) {
                            double angleOfText = (Math.atan(xyLabels[i][1][j - 1] - xyLabels[i][1][j]) / (xyLabels[i][0][j - 1] - xyLabels[i][0][j]));
                            g2d.rotate(-angleOfText, leftMargin + 20, mapY(xyLabels[i][1][j - 1]));
                            g2d.drawString(displayString, leftMargin + 10, (float) mapY(xyLabels[i][1][j - 1]) - 5);
                            g2d.rotate(angleOfText, leftMargin + 20, mapY(xyLabels[i][1][j - 1]));
                            labelPrinted = true;
                        }
                    }
                }
            }

            // opensystem isochrons
            if (!openSystemIsochronModelsList.isEmpty()) {
                //LinearInterpolator linearInterpolator = new LinearInterpolator();

                for (OpenSystemIsochronTableModel ositm : openSystemIsochronModelsList) {
                    // for each model, we use the seawaater model to calculate the open isochrons
                    if (ositm.isShowOpenIsochrons()) {
                        //double[] dates = ositm.getSeaWaterInitialDelta234UTableModel().getArrayOfDates();
                        //double[] deltas = ositm.getSeaWaterInitialDelta234UTableModel().getArrayOfDeltasAsRatios();
                        //PolynomialSplineFunction psfSeaWater = linearInterpolator.interpolate(dates, deltas);

                        for (OpenSystemIsochronModelEntry osime : ositm.getEntryList()) {
                            double age = osime.getAgeInKa() * 1000.0;
                            double ar234U_238Uisw = ositm.getSeaWaterInitialDelta234UTableModel().calculateAr234U_238Uisw(age);
                            double isoPctLoss = osime.getPctLoss();
                            double isoStartR = osime.getrStart();
                            double isoEndR = osime.getrEnd();

                            Point2D.Double openIsoPointStart = calculateOpenSystemIsochronEndPoint(age, ar234U_238Uisw, isoStartR, isoPctLoss);
                            Point2D.Double openIsoPointEnd = calculateOpenSystemIsochronEndPoint(age, ar234U_238Uisw, isoEndR, isoPctLoss);

                            Shape isochronLine = new Path2D.Double();
                            g2d.setStroke(new BasicStroke(2.0f));
                            ((Path2D) isochronLine).moveTo(//
                                    mapX(openIsoPointStart.getX()), //
                                    mapY(openIsoPointStart.getY()));
                            ((Path2D) isochronLine).lineTo( //
                                    mapX(openIsoPointEnd.getX()), //
                                    mapY(openIsoPointEnd.getY()));

                            g2d.setPaint(ositm.getDisplayColor());

                            g2d.draw(isochronLine);
                        }
                    }

                    if (ositm.isShowSeawaterModel()) {

                        // uppper envelope
                        buildSeawaterModelPlot(ositm.getSeaWaterInitialDelta234UTableModel(), 1);
                        Path2D curvedP = new Path2D.Double(Path2D.WIND_NON_ZERO);
                        curvedP.moveTo(
                                (float) mapX(xysw[0][0][0]),
                                (float) mapY(xysw[0][1][0]));

                        for (int j = 1; j < tvsw[0].length; j++) {
                            double deltaTOver3 = (tvsw[0][j] - tvsw[0][j - 1]) / 3;

                            curvedP.curveTo(//
                                    (float) mapX(xysw[0][0][j - 1] + deltaTOver3 * dardtsw[0][0][j - 1]),
                                    (float) mapY(xysw[0][1][j - 1] + deltaTOver3 * dardtsw[0][1][j - 1]),
                                    (float) mapX(xysw[0][0][j] - deltaTOver3 * dardtsw[0][0][j]),
                                    (float) mapY(xysw[0][1][j] - deltaTOver3 * dardtsw[0][1][j]),
                                    (float) mapX(xysw[0][0][j]),
                                    (float) mapY(xysw[0][1][j]));
                        }

                        // lower envelope
                        buildSeawaterModelPlot(ositm.getSeaWaterInitialDelta234UTableModel(), -1);
                        //curvedP = new Path2D.Double(Path2D.WIND_NON_ZERO);
                        int hiIndex = tvsw[0].length - 1;
                        curvedP.lineTo(
                                (float) mapX(xysw[0][0][hiIndex]),
                                (float) mapY(xysw[0][1][hiIndex]));

                        for (int j = hiIndex - 1; j >= 0; j--) {
                            double deltaTOver3 = (tvsw[0][j + 1] - tvsw[0][j]) / 3;

                            curvedP.curveTo(//
                                    (float) mapX(xysw[0][0][j + 1] + deltaTOver3 * dardtsw[0][0][j + 1]),
                                    (float) mapY(xysw[0][1][j + 1] + deltaTOver3 * dardtsw[0][1][j + 1]),
                                    (float) mapX(xysw[0][0][j] - deltaTOver3 * dardtsw[0][0][j]),
                                    (float) mapY(xysw[0][1][j] - deltaTOver3 * dardtsw[0][1][j]),
                                    (float) mapX(xysw[0][0][j]),
                                    (float) mapY(xysw[0][1][j]));
                        }

                        curvedP.closePath();

                        g2d.setPaint(new Color(213, 255, 232));
                        g2d.setStroke(new BasicStroke(1.5f));
                        g2d.fill(curvedP);

                        // seawater
                        buildSeawaterModelPlot(ositm.getSeaWaterInitialDelta234UTableModel(), 0);
                        curvedP = new Path2D.Double(Path2D.WIND_NON_ZERO);
                        curvedP.moveTo(
                                (float) mapX(xysw[0][0][0]),
                                (float) mapY(xysw[0][1][0]));

                        for (int j = 1; j < tvsw[0].length; j++) {
                            double deltaTOver3 = (tvsw[0][j] - tvsw[0][j - 1]) / 3;

                            curvedP.curveTo(//
                                    (float) mapX(xysw[0][0][j - 1] + deltaTOver3 * dardtsw[0][0][j - 1]),
                                    (float) mapY(xysw[0][1][j - 1] + deltaTOver3 * dardtsw[0][1][j - 1]),
                                    (float) mapX(xysw[0][0][j] - deltaTOver3 * dardtsw[0][0][j]),
                                    (float) mapY(xysw[0][1][j] - deltaTOver3 * dardtsw[0][1][j]),
                                    (float) mapX(xysw[0][0][j]),
                                    (float) mapY(xysw[0][1][j]));
                        }
                        g2d.setPaint(SEAWATER_GREEN);
                        g2d.setStroke(new BasicStroke(2.f));
                        g2d.draw(curvedP);

                    }
                }
            }

            // END opensystem isochrons
            // ellipses
            g2d.setPaint(Color.black);

            Color includedBorderColor = Color.BLACK;
            Color includedCenterColor = new Color(255, 0, 0);
            float includedCenterSize = 3.0f;
            String ellipseLabelFont = "Monospaced";
            String ellipseLabelFontSize = "12";

            for (ETFractionInterface f : selectedFractions) {
                if (!f.isRejected()) {
                    generateEllipsePathIII(//
                            f,
                            f.getAnalysisMeasure(UThAnalysisMeasures.ar230Th_238Ufc.getName()),
                            f.getAnalysisMeasure(UThAnalysisMeasures.ar234U_238Ufc.getName()),
                            2.0f);
                    if (f.getErrorEllipsePath() != null) {
                        boolean included
                                = ((ProjectSample) sample).calculateIfEllipseIncluded(
                                        f.getRadiogenicIsotopeDateByName(RadDates.date.getName()).getValue().movePointLeft(3).doubleValue(),
                                        f.getAnalysisMeasure(UThAnalysisMeasures.delta234Ui.getName()).getValue().doubleValue());
                        plotAFraction(g2d,
                                svgStyle,
                                f,
                                includedBorderColor,
                                0.5f,
                                included ? includedCenterColor : new Color(211, 211, 211),
                                includedCenterSize,
                                ellipseLabelFont,
                                ellipseLabelFontSize,
                                showCenters,
                                showLabels);
                    }
                }
            }

            // draw zoom box if in use
            if (isInImageModeZoom()
                    && (Math.abs(zoomMaxX - zoomMinX) * Math.abs(zoomMinY - zoomMaxY)) > 0) {
                g2d.setStroke(new BasicStroke(2.0f));
                g2d.setColor(Color.red);
                g2d.drawRect(//
                        Math.min(zoomMinX, zoomMaxX),
                        Math.min(zoomMaxY, zoomMinY),
                        Math.abs(zoomMaxX - zoomMinX),
                        Math.abs(zoomMinY - zoomMaxY));
            }

            // resets clipping
            try {
                drawAxesAndTics(g2d, yAxisDisplayAsDeltaUnits);
            } catch (Exception e) {
            }

            // label axes
            String xAxisLabel = "[230Th/238U]t";
            g2d.setFont(new Font("Monospaced", Font.BOLD, 18));
            double xAxisLabelLength = calculateLengthOfStringPlot(g2d, xAxisLabel);

            String yAxisLabel = "[234U/238U]t";//axes[1].getAxisLabel();
            double yAxisLabelLength = calculateLengthOfStringPlot(g2d, yAxisLabel);

            g2d.setFont(new Font("Monospaced", Font.BOLD, 12));
            g2d.drawString("230",
                    leftMargin + (int) (graphWidth / 2.0) - (int) (xAxisLabelLength / 2.0) + 10,
                    topMargin + (int) graphHeight + 30);
            g2d.drawString("238",
                    leftMargin + (int) (graphWidth / 2.0) - (int) (xAxisLabelLength / 2.0) + 65,
                    topMargin + (int) graphHeight + 30);
            g2d.drawString("t",
                    leftMargin + (int) (graphWidth / 2.0) - (int) (xAxisLabelLength / 2.0) + 105,
                    topMargin + (int) graphHeight + 40);

            g2d.setFont(new Font("Monospaced", Font.BOLD, 18));
            g2d.drawString("[",
                    leftMargin + (int) (graphWidth / 2.0) - (int) (xAxisLabelLength / 2.0),
                    topMargin + (int) graphHeight + 35);
            g2d.drawString("Th/",
                    leftMargin + (int) (graphWidth / 2.0) - (int) (xAxisLabelLength / 2.0) + 30,
                    topMargin + (int) graphHeight + 35);
            g2d.drawString("U]",
                    leftMargin + (int) (graphWidth / 2.0) - (int) (xAxisLabelLength / 2.0) + 85,
                    topMargin + (int) graphHeight + 35);

            // y axis
            g2d.rotate(-Math.PI / 2.0);

            if (yAxisDisplayAsDeltaUnits) {
                g2d.setFont(new Font("Monospaced", Font.BOLD, 18));
                g2d.drawString("\u03B4234U \u2030",
                        -(topMargin / 2 + (int) (graphHeight / 2.0) + (int) (yAxisLabelLength / 2.0) - 10),
                        leftMargin - 20);
            } else {
                g2d.setFont(new Font("Monospaced", Font.BOLD, 12));
                g2d.drawString("234",
                        -(topMargin / 2 + (int) (graphHeight / 2.0) + (int) (yAxisLabelLength / 2.0) - 10),
                        leftMargin - 25);
                g2d.drawString("238",
                        -(topMargin / 2 + (int) (graphHeight / 2.0) + (int) (yAxisLabelLength / 2.0) - 55),
                        leftMargin - 25);
                g2d.drawString("t",
                        -(topMargin / 2 + (int) (graphHeight / 2.0) + (int) (yAxisLabelLength / 2.0) - 95),
                        leftMargin - 15);

                g2d.setFont(new Font("Monospaced", Font.BOLD, 18));
                g2d.drawString("[",
                        -(topMargin / 2 + (int) (graphHeight / 2.0) + (int) (yAxisLabelLength / 2.0)),
                        leftMargin - 20);
                g2d.drawString("U/",
                        -(topMargin / 2 + (int) (graphHeight / 2.0) + (int) (yAxisLabelLength / 2.0) - 30),
                        leftMargin - 20);
                g2d.drawString("U]",
                        -(topMargin / 2 + (int) (graphHeight / 2.0) + (int) (yAxisLabelLength / 2.0) - 75),
                        leftMargin - 20);
            }

            g2d.rotate(Math.PI / 2.0);

            // draw and label isochron axes - top and right
            g2d.setFont(new Font("Monospaced", Font.BOLD, 12));

            for (int i = 0; i < annumIsochrons.length; i++) {

                String label = " " + new BigDecimal(annumIsochrons[i]).movePointLeft(3).setScale(0, RoundingMode.HALF_UP).toPlainString() + " ka";
                // set infinity label
                if (annumIsochrons[i] >= 10e10) {
                    label = " \u221E";
                }

                double rotateAngle = StrictMath.atan(slopes[i]);

                double labelX = ((yItercepts[i] + slopes[i] * getMaxX_Display()) < (getMaxY_Display() - 0.000)) ? getMaxX_Display() : (getMaxY_Display() - yItercepts[i]) / slopes[i];
                double labelY = slopes[i] * labelX + yItercepts[i];
                float displacementFactorX = 0f;
                float displacementFactorY = -6f;

                if ((labelX >= getMinX_Display()) && (labelX <= getMaxX_Display()) && (labelY > getMinY_Display())) {
                    g2d.rotate(-rotateAngle,
                            (float) mapX(labelX),
                            (float) mapY(yItercepts[i] + slopes[i] * (labelX)));

                    g2d.drawString(label,
                            (float) mapX(labelX) + displacementFactorX,
                            (float) mapY(yItercepts[i] + slopes[i] * (labelX)) - displacementFactorY);

                    g2d.rotate(rotateAngle,
                            (float) mapX(labelX),
                            (float) mapY(yItercepts[i] + slopes[i] * (labelX)));
                }
            }

        }

    }

    @Override
    public void preparePanel(boolean doReset) {
        setOpenSystemIsochronModelsList(((ProjectSample) sample).updateListOfOpenIsochronModels());

        if (doReset) {

            removeAll();

            maxX = (xAxisMax == 0) ? 1.5 : xAxisMax;
            xAxisMax = maxX;
            maxY = (yAxisMax == 0) ? 2.0 : yAxisMax;
            yAxisMax = maxY;

            showTight();
        }

        putInImageModePan();
        repaint();
    }

    public void showTight() {
        // determine default zoom
        zoomMaxX = 0;
        zoomMaxY = 0;
        zoomMinX = 0;
        zoomMinY = 0;

        displayOffsetX = 0.0;
        displayOffsetY = 0.0;
        minX = Double.MAX_VALUE;
        maxX = -Double.MAX_VALUE;
        minY = Double.MAX_VALUE;
        maxY = -Double.MAX_VALUE;
        for (ETFractionInterface f : selectedFractions) {
            if (!f.isRejected()) {

                double xAxisRatio = f.getLegacyActivityRatioByName(UThAnalysisMeasures.ar230Th_238Ufc.getName()).getValue().doubleValue();
                double xAxis2Sigma = f.getLegacyActivityRatioByName(UThAnalysisMeasures.ar230Th_238Ufc.getName()).getTwoSigmaAbs().doubleValue();
                minX = Math.min(minX, xAxisRatio - 2.0 * xAxis2Sigma);
                maxX = Math.max(maxX, xAxisRatio + 2.0 * xAxis2Sigma);

                double yAxisRatio = f.getLegacyActivityRatioByName(UThAnalysisMeasures.ar234U_238Ufc.getName()).getValue().doubleValue();
                double yAxis2Sigma = f.getLegacyActivityRatioByName(UThAnalysisMeasures.ar234U_238Ufc.getName()).getTwoSigmaAbs().doubleValue();
                minY = Math.min(minY, yAxisRatio - 2.0 * yAxis2Sigma);
                maxY = Math.max(maxY, yAxisRatio + 2.0 * yAxis2Sigma);
            }
        }

        // maintain 2/1.5 aspect ratio
        if (getRangeY_Display() / getRangeX_Display() < 2.0 / 1.5) {
            // increase Y
            double yDelta = (2.0 / 1.5) * getRangeX_Display() - getRangeY_Display();
            minY -= yDelta / 2.0;
            maxY += yDelta / 2.0;

            zoomCount = (int) Math.min(10.0, 10.0 / getRangeY_Display());
        } else {
            // increase x
            double xDelta = (1.5 / 2.0) * getRangeY_Display() - getRangeX_Display();
            minX -= xDelta / 2.0;
            maxX += xDelta / 2.0;

            zoomCount = (int) Math.min(10.0, 10.0 / getRangeX_Display());
        }

        buildIsochronsAndInitDelta234UContours();

        generateCustomTics();

        repaint();
        validate();

    }

    public void showLoose() {
        // determine default zoom
        zoomMaxX = 0;
        zoomMaxY = 0;
        zoomMinX = 0;
        zoomMinY = 0;

        displayOffsetX = 0.0;
        displayOffsetY = 0.0;

        zoomCount = 0;

        minX = 0.0;
        maxX = 1.5;
        xAxisMax = maxX;

        minY = 0.0;
        maxY = 2.0;
        yAxisMax = maxY;

        buildIsochronsAndInitDelta234UContours();

        generateCustomTics();

        repaint();
        validate();
    }

    public void buildIsochronsAndInitDelta234UContours() {
        // math adapted from Noah's matlab code
        ValueModel sampleDateModel = ((SampleDateModel) sample.getSampleDateModelByName("DEFAULT"));
        SortedSet<IsochronModel> selectedIsochrons = ((SampleDateModel) sampleDateModel).getIsochronModels();
        List<Double> annumList = new ArrayList<>();
        Iterator<IsochronModel> isochronIterator = selectedIsochrons.iterator();
        while (isochronIterator.hasNext()) {
            IsochronModel isochronModel = isochronIterator.next();
            if (((SampleDateModel) sampleDateModel).isAutomaticIsochronSelection()) {
                isochronModel.setVisible(
                        (zoomCount >= 0) ? (isochronModel.getDensityLevel() <= (zoomCount / 4))
                                : (isochronModel.getDensityLevel() == 0));
            }
            if (isochronModel.isVisible()) {
                annumList.add(isochronModel.getDateInAnnum());
            }
        }

        Collections.sort(annumList);

        annumIsochrons = annumList.stream().mapToDouble(Double::doubleValue).toArray();

        if (((SampleDateModel) sampleDateModel).isAutomaticInitDelta234USelection()) {
            ((SampleDateModel) sampleDateModel).setAr48icntrs(IsochronModel.generateDefaultEvolutionAr48icntrs(((SampleDateModel) sampleDateModel).getAr48icntrs()));
        }

        double[] ar48icntrsBase = ((SampleDateModel) sampleDateModel).getAr48icntrs();
        List<Double> ar48icntrsList = new ArrayList<>();
        for (int i = 0; i < ar48icntrsBase.length; i++) {
            ar48icntrsList.add(ar48icntrsBase[i]);
        }

        Collections.sort(ar48icntrsList);

        ar48icntrs = ar48icntrsList.stream().mapToDouble(Double::doubleValue).toArray();
        ar48icntrsDsplayAsDeltaUnits = ((SampleDateModel) sampleDateModel).isAr48icntrsDsplayAsDeltaUnits();

        Matrix ar48limYaxis = new Matrix(new double[][]{{0.0, maxY * 1}});
        Matrix ar08limXaxis = new Matrix(new double[][]{{0.0, maxX * 1}});

        // % Calculations for isochron line parameters and endpoints
        int nisochrons = annumIsochrons.length;
        Matrix r48lim = ar48limYaxis.times(lambda238D / lambda234D);
        Matrix r08lim = ar08limXaxis.times(lambda238D / lambda230D);

        // Calculations for isochron slope/y-intercept, in isotope ratio coordinates (not activity ratios)
        Matrix abmat = new Matrix(2, nisochrons, 0.0);
        Matrix xminpoints = new Matrix(1, nisochrons, 0.0);
        Matrix yminpoints = new Matrix(1, nisochrons, 0.0);

        int it = -1;
        for (int i = 0; i < nisochrons; i++) {
            double t = annumIsochrons[i];
            it++;

            if (t >= 10e13) {
                abmat.set(1, it, lambda230D / lambda234D - 1.0); //% note: works, but not sure how to evaluate this limit
                abmat.set(0, it, lambda238D / (lambda230D - lambda238D)); // y-int with above slope through transient eqbm

                xminpoints.set(0, it, matrixQUTh().get(2, 0) / matrixQUTh().get(0, 0)); // limit is transient eqbm.  Lower starts all end up here after ~5 Myr
                yminpoints.set(0, it, matrixQUTh().get(1, 0) / matrixQUTh().get(0, 0));

            } else {// finite t
                Matrix mxpNegAt = matrixUTh(-t);
                abmat.set(1, it, -mxpNegAt.get(2, 2) / mxpNegAt.get(2, 1));// slope

                Matrix mxpAt = matrixUTh(t);
                double XX = -mxpAt.get(2, 0) / mxpAt.get(2, 1);
                abmat.set(0, it, matrixUTh4(t).times((new Matrix(new double[][]{{1.0, XX, 0.0}})).transpose()).get(0, 0));   // y-int
                Matrix mxpAtmin = mxpAt.times((new Matrix(new double[][]{{1.0, 0.0, 0.0}})).transpose());

                xminpoints.set(0, it, mxpAtmin.get(2, 0) / mxpAtmin.get(0, 0));
                yminpoints.set(0, it, mxpAtmin.get(1, 0) / mxpAtmin.get(0, 0));
            }
        }

        // y-coord of intersections with left boundary of box
        Matrix leftBorder = abmat.getMatrix(0, 0, 0, nisochrons - 1).plus(abmat.getMatrix(1, 1, 0, nisochrons - 1).times(r08lim.get(0, 0)));
        // y-coord of intersections with right boundary of box
        Matrix rightBorder = abmat.getMatrix(0, 0, 0, nisochrons - 1).plus(abmat.getMatrix(1, 1, 0, nisochrons - 1).times(r08lim.get(0, 1)));
        // x-coord of intersections with bottom boundary of box
        Matrix bottomBorder = (new Matrix(1, nisochrons, r48lim.get(0, 0))).minus(abmat.getMatrix(0, 0, 0, nisochrons - 1)).arrayRightDivide(abmat.getMatrix(1, 1, 0, nisochrons - 1));
        // x-coord of intersections with top boundary of box
        Matrix topBorder = (new Matrix(1, nisochrons, r48lim.get(0, 1))).minus(abmat.getMatrix(0, 0, 0, nisochrons - 1)).arrayRightDivide(abmat.getMatrix(1, 1, 0, nisochrons - 1));

        xEndPointsD = new double[2][nisochrons];
        yEndPointsD = new double[2][nisochrons];
        for (int col = 0; col < nisochrons; col++) {
            xEndPointsD[0][col] = leftBorder.get(0, col) > r48lim.get(0, 0) ? r08lim.get(0, 0) : 0.0;
            xEndPointsD[0][col] += (leftBorder.get(0, col) <= r48lim.get(0, 0) ? bottomBorder.get(0, col) : 0.0);
            xEndPointsD[0][col] = Math.max(xEndPointsD[0][col], xminpoints.get(0, col));
            xEndPointsD[0][col] *= lambda230D / lambda238D;

            xEndPointsD[1][col] = rightBorder.get(0, col) < r48lim.get(0, 1) ? r08lim.get(0, 1) : 0.0;
            xEndPointsD[1][col] += (rightBorder.get(0, col) >= r48lim.get(0, 1) ? topBorder.get(0, col) : 0.0);
            xEndPointsD[1][col] *= lambda230D / lambda238D;

            yEndPointsD[0][col] = leftBorder.get(0, col) > r48lim.get(0, 0) ? leftBorder.get(0, col) : 0.0;
            yEndPointsD[0][col] += (leftBorder.get(0, col) <= r48lim.get(0, 0) ? r48lim.get(0, 0) : 0.0);
            yEndPointsD[0][col] = Math.max(yEndPointsD[0][col], yminpoints.get(0, col));
            yEndPointsD[0][col] *= lambda234D / lambda238D;

            yEndPointsD[1][col] = rightBorder.get(0, col) < r48lim.get(0, 1) ? rightBorder.get(0, col) : 0.0;
            yEndPointsD[1][col] += (rightBorder.get(0, col) >= r48lim.get(0, 1) ? r48lim.get(0, 1) : 0.0);
            yEndPointsD[1][col] *= lambda234D / lambda238D;
        }

        // calculate ar48i contours
        // new technique - use both evenly spaced and isochrons so we can get intersections for sea water
        List<Double> arList = DoubleStream.of(annumIsochrons).boxed().collect(Collectors.toList());
        for (int i = 0; i < 10; i++) {
            double age = (double) (i * 1.0e5);
            if (!arList.contains(age) && age < 10e10) {
                arList.add(age);
            }
        }
        arList.add(2e6);

        Collections.sort(arList);

        int nts = arList.size();
        // build array of vectors of evenly spaced values with last value = 2e6
        tv = new double[ar48icntrs.length][nts];
        for (int i = 0; i < (nts - 0); i++) {
            double colVal = arList.get(i);//  annumIsochrons[i];//          (double) (i * 1.0e5);// / (double) (nts - 2));
            for (double[] tv1 : tv) {
                tv1[i] = colVal;
            }
        }

        xy = new double[ar48icntrs.length][2][nts];
        dardt = new double[ar48icntrs.length][2][nts];

        int iar48i = -1;

        for (double ar48i : ar48icntrs) {
            iar48i++;
            it = -1;

            for (double t : tv[iar48i]) {
                it++;
                Matrix n0 = new Matrix(new double[][]{{1, ar48i * lambda238D / lambda234D, 0}}).transpose();

                Matrix nt = matrixUTh(t).times(n0);

                xy[iar48i][0][it] = nt.get(2, 0) / nt.get(0, 0) * lambda230D / lambda238D;
                xy[iar48i][1][it] = nt.get(1, 0) / nt.get(0, 0) * lambda234D / lambda238D;

                double dar48dnt1 = -nt.get(1, 0) / nt.get(0, 0) / nt.get(0, 0) * lambda234D / lambda238D;
                double dar48dnt2 = 1.0 / nt.get(0, 0) * lambda234D / lambda238D;
                double dar48dnt3 = 0;
                double dar08dnt1 = -nt.get(2, 0) / nt.get(0, 0) / nt.get(0, 0) * lambda230D / lambda238D;
                double dar08dnt2 = 0;
                double dar08dnt3 = 1.0 / nt.get(0, 0) * lambda230D / lambda238D;

                Matrix dardnt = new Matrix(new double[][]{{dar08dnt1, dar08dnt2, dar08dnt3}, {dar48dnt1, dar48dnt2, dar48dnt3}});
                Matrix dntdt = matrixA().times(matrixUTh(t)).times(n0);

                dardt[iar48i][0][it] = dardnt.times(dntdt).get(0, 0);
                dardt[iar48i][1][it] = dardnt.times(dntdt).get(1, 0);
            }
        }

        // repeat for labels
        nts = 200;//10; // number of segments - need 200 to position label well
        // build array of vectors of evenly spaced values with last value = 2e6
        tvLabels = new double[ar48icntrs.length][nts];
        for (int i = 0; i < (nts - 1); i++) {
            double colVal = (double) (i * 1.0e6 / (double) (nts - 2));
            for (double[] tv1 : tvLabels) {
                tv1[i] = colVal;
            }
        }
        for (double[] tv1 : tvLabels) {
            tv1[nts - 1] = 2e6;
        }

        xyLabels = new double[ar48icntrs.length][2][nts];

        iar48i = -1;

        for (double ar48i : ar48icntrs) {
            iar48i++;
            it = -1;

            for (double t : tvLabels[iar48i]) {
                it++;
                Matrix n0 = new Matrix(new double[][]{{1, ar48i * lambda238D / lambda234D, 0}}).transpose();

                Matrix nt = matrixUTh(t).times(n0);

                xyLabels[iar48i][0][it] = nt.get(2, 0) / nt.get(0, 0) * lambda230D / lambda238D;
                xyLabels[iar48i][1][it] = nt.get(1, 0) / nt.get(0, 0) * lambda234D / lambda238D;
            }
        }
    }

    /**
     *
     * @param seaWaterInitialDelta234UTableModel
     * @param limit limit negative = lower envelope, 0 = seawater, >0 = upper
     * envelope
     */
    private void buildSeawaterModelPlot(SeaWaterInitialDelta234UTableModel seaWaterInitialDelta234UTableModel, int limit) {
        double[] dates = seaWaterInitialDelta234UTableModel.getArrayOfDates();

        int countOfPoints = 100;
        double step = (dates[dates.length - 1] - dates[0]) / countOfPoints;
        tvsw = new double[1][countOfPoints];
        double[] ar48isw = new double[countOfPoints];

        for (int i = 0; i < countOfPoints; i++) {
            tvsw[0][i] = dates[0] + i * step;
            ar48isw[i] = seaWaterInitialDelta234UTableModel.calculateAr234U_238Uisw(tvsw[0][i])
                    + Math.signum(limit) * seaWaterInitialDelta234UTableModel.calculateAr234U_238UiswUnct(tvsw[0][i]);
        }

        xysw = new double[1][2][ar48isw.length];
        dardtsw = new double[1][2][ar48isw.length];
        int it = -1;
        for (double t : tvsw[0]) {
            it++;
            Matrix n0 = new Matrix(new double[][]{{1, ar48isw[it] * lambda238D / lambda234D, 0}}).transpose();

            Matrix nt = matrixUTh(t).times(n0);

            xysw[0][0][it] = nt.get(2, 0) / nt.get(0, 0) * lambda230D / lambda238D;
            xysw[0][1][it] = nt.get(1, 0) / nt.get(0, 0) * lambda234D / lambda238D;

            double dar48dnt1 = -nt.get(1, 0) / nt.get(0, 0) / nt.get(0, 0) * lambda234D / lambda238D;
            double dar48dnt2 = 1.0 / nt.get(0, 0) * lambda234D / lambda238D;
            double dar48dnt3 = 0;
            double dar08dnt1 = -nt.get(2, 0) / nt.get(0, 0) / nt.get(0, 0) * lambda230D / lambda238D;
            double dar08dnt2 = 0;
            double dar08dnt3 = 1.0 / nt.get(0, 0) * lambda230D / lambda238D;

            Matrix dardnt = new Matrix(new double[][]{{dar08dnt1, dar08dnt2, dar08dnt3}, {dar48dnt1, dar48dnt2, dar48dnt3}});
            Matrix dntdt = matrixA().times(matrixUTh(t)).times(n0);

            dardtsw[0][0][it] = dardnt.times(dntdt).get(0, 0);
            dardtsw[0][1][it] = dardnt.times(dntdt).get(1, 0);
        }
    }

    private double[][] diag(double zeroZero, double oneOne, double twoTwo) {
        double[][] diag = new double[3][3];
        diag[0][0] = zeroZero;
        diag[1][1] = oneOne;
        diag[2][2] = twoTwo;

        return diag;
    }

    private Matrix matrixA() {
        double[][] matrixAvals = new double[][]//
        {{-lambda238D, 0.0, 0.0},
        {lambda238D, -lambda234D, 0.0},
        {0.0, lambda234D, -lambda230D}};
        return new Matrix(matrixAvals);
    }

    private Matrix matrixQUTh() {
        double[][] matrixQUThvals = new double[][]//
        {{((lambda230D - lambda238D) * (lambda234D - lambda238D)) / (lambda234D * lambda238D), 0.0, 0.0},
        {(lambda230D - lambda238D) / lambda234D, (lambda230D - lambda234D) / lambda234D, 0.0},
        {1.0, 1.0, 1.0}};
        return new Matrix(matrixQUThvals);
    }

    private Matrix matrixGUTh(double t) {
        return new Matrix(diag(Math.exp(-lambda238D * t), Math.exp(-lambda234D * t), Math.exp(-lambda230D * t)));
    }

    private Matrix matrixQinvUTh() {
        double[][] matrixQinvUThvals = new double[][]//
        {{(lambda234D * lambda238D) / ((lambda230D - lambda238D) * (lambda234D - lambda238D)), 0.0, 0.0},
        {-(lambda234D * lambda238D) / ((lambda230D - lambda234D) * (lambda234D - lambda238D)), lambda234D / (lambda230D - lambda234D), 0.0},
        {(lambda234D * lambda238D) / ((lambda230D - lambda234D) * (lambda230D - lambda238D)), -lambda234D / (lambda230D - lambda234D), 1.0}};
        return new Matrix(matrixQinvUThvals);
    }

    private Matrix matrixUTh(double t) {
        return matrixQUTh().times(matrixGUTh(t)).times(matrixQinvUTh());
    }

    private Matrix matrixUTh0(double t) {
        return matrixQUTh().getMatrix(2, 2, 0, 2).times(matrixGUTh(t)).times(matrixQinvUTh()); //For the 230 concentration only (to solve for root)
    }

    private Matrix matrixUTh4(double t) {
        return matrixQUTh().getMatrix(1, 1, 0, 2).times(matrixGUTh(t)).times(matrixQinvUTh()); //For the 234 concentration only (to solve for root)
    }

    // per Noah email June 2019
    private Point2D.Double calculateOpenSystemIsochronEndPoint(double age, double ar234U_238Uisw, double rValue, double pctLoss) {
        /*
        New variables used in calculations appear as outlined text below when they first appear.
        Inputs:

        In addition to the sample's physical constant model, which is already user-selected (lambda238, lambda234, lambda230),
        there are three user inputs needed to draw an open system isochron.

        "Coral or source % loss" – entered with units of %.  pctLoss
        Seawater initial del234Ui – a chooser for the seawater model.  (PS – why is the W capitalized in SeaWater in Redux?
        It looks like SeaWorld!  Seawater is a real word.)  This dropdown list chooser should be linked with the graphical displayed seawater model,
        so that you're not plotting a seawater curve with one seawater model and an open system isochron with another model.
        Isochron age – this can look just like the column of check-boxes for the 'isochron chooser' which includes the ability to add/subtract isochrons.
        Following the rest of Redux, ages in input/output in ka and saved off and used in computations in units of years.  t

        Calculations:

        Each point on the open system isochron line has an 'R' value (this is what it's called in Andrea's spreadsheet,
        though I can't find it in the original paper).  If you have two R values, you have two points, and can plot the line between them,
        or extend the line out in either direction.  The R values used in Andrea's spreadsheet range from 0 to 0.14.

        Calculate the initial seawater 234U/238U activity ratio ar234U_238Uisw for the input age t using the user-input seawater model.
        This is an activity ratio, so a typical number would be 1.145.
        Calculate f234 =  1 – pctLoss / 100
        Calculate f230 = ((f234 - 1) * (4.754 * 234 / 4.184 / 230) + 1 + f234)/2
        Calculate ar234U_238U = (1 + R * (1 – f234)) * (1 – EXP(–lambda234 * t)) + ar234U_238Uisw *EXP(–lambda234 * t)
        Calculate ar230Th_238U = (1 + R * (1 – f234 * f230)) * (1 – lambda230/( lambda230- lambda234) * EXP(–lambda234 * t) + lambda234/( lambda230 - lambda234) * EXP(–lambda230 * t))+(1 + R * (1 - f230)) * (lambda230 / (lambda230 - lambda234) * ar234U_238Uisw * (EXP(–lambda234* t) - EXP(–lambda230 * t)))

        You now have the ar234U_238U and ar230Th_238U, which are the y and x values, respectively, for a point on the open system isochron line.
         */

        double ar234U_238U;
        double ar230Th_238U;

        double f234 = 1.0 - (pctLoss / 100.0);
        double f230 = ((f234 - 1.0) * (4.754 * 234.0 / 4.184 / 230.0) + 1.0 + f234) / 2;

        ar234U_238U = (1.0 + rValue * (1.0 - f234)) * (1.0 - Math.exp(-lambda234D * age)) + ar234U_238Uisw * Math.exp(-lambda234D * age);
        ar230Th_238U
                = (1.0 + rValue * (1.0 - f234 * f230))
                * (1.0 - lambda230D / (lambda230D - lambda234D) * Math.exp(-lambda234D * age)
                + lambda234D / (lambda230D - lambda234D) * Math.exp(-lambda230D * age))
                + (1.0 + rValue * (1.0 - f230)) * (lambda230D / (lambda230D - lambda234D)
                * ar234U_238Uisw * (Math.exp(-lambda234D * age) - Math.exp(-lambda230D * age)));

        return new Point2D.Double(ar230Th_238U, ar234U_238U);
    }

    /**
     * @param annumIsochrons the annumIsochrons to set
     */
    public void setAnnumIsochrons(double[] annumIsochrons) {
        this.annumIsochrons = annumIsochrons;
    }

    /**
     * @param xAxisMax the xAxisMax to set
     */
    public void setxAxisMax(double xAxisMax) {
        this.xAxisMax = xAxisMax;
    }

    /**
     * @param yAxisMax the yAxisMax to set
     */
    public void setyAxisMax(double yAxisMax) {
        this.yAxisMax = yAxisMax;
    }

    @Override
    public void mousePressed(MouseEvent evt) {
        super.mousePressed(evt);
        if ((evt.getX() >= leftMargin)
                && (evt.getX() <= graphWidth + leftMargin)
                && (evt.getY() >= topMargin)
                && (evt.getY() <= graphHeight + topMargin)) {

            if (evt.isPopupTrigger() || evt.getButton() == MouseEvent.BUTTON3) {

                putInImageModePan();

                //Create the popup menu.
                JPopupMenu popup = new JPopupMenu();

                // Jan 2011 show coordinates fyi
                double x = convertMouseXToValue(evt.getX());
                double y = convertMouseYToValue(evt.getY());

                JMenuItem menuItem = new JMenuItem("Toggle Y-axis units");
                menuItem.addActionListener(new ActionListener() {

                    public void actionPerformed(ActionEvent arg0) {
                        yAxisDisplayAsDeltaUnits = !yAxisDisplayAsDeltaUnits;
                        repaint();
                    }
                });
                popup.add(menuItem);

                popup.show(evt.getComponent(), evt.getX(), evt.getY());
            }
        }
    }

    /**
     *
     * @param evt
     */
    @Override
    public void mouseMoved(MouseEvent evt) {
        int myX = evt.getX();
        int myY = evt.getY();

        eastResizing = isEastResize(myX);
        southResizing = isSouthResize(myY);

        setCursor(Cursor.getDefaultCursor());
        if (eastResizing ^ southResizing) {
            if (eastResizing) {
                setCursor(Cursor.getPredefinedCursor(Cursor.E_RESIZE_CURSOR));
            } else {
                setCursor(Cursor.getPredefinedCursor(Cursor.S_RESIZE_CURSOR));
            }
        }

        if (eastResizing && southResizing) {
            setCursor(Cursor.getPredefinedCursor(Cursor.SE_RESIZE_CURSOR));
        }
    }

    private boolean isEastResize(int myX) {
        return ((myX >= (graphWidth + leftMargin - 2)) && (myX <= (graphWidth + leftMargin + 2)));
    }

    private boolean isSouthResize(int myY) {
        return ((myY >= (graphHeight + leftMargin - 2)) && (myY <= (graphHeight + leftMargin + 2)));
    }

    @Override
    public void mouseWheelMoved(MouseWheelEvent e) {
        if (mouseInHouse(e)) {

            zoomMaxX = e.getX();
            zoomMaxY = e.getY();

            // https://java.com/en/download/faq/release_changes.xml
            double notches = e.getPreciseWheelRotation();
            if (true) {//(notches == Math.rint(notches)) {
                if (notches < 0) {// zoom in
                    minX += getRangeX_Display() / ZOOM_FACTOR;
                    maxX -= getRangeX_Display() / ZOOM_FACTOR;
                    minY += getRangeY_Display() / ZOOM_FACTOR;
                    maxY -= getRangeY_Display() / ZOOM_FACTOR;

                    zoomCount++;

                } else {// zoom out
                    minX -= getRangeX_Display() / ZOOM_FACTOR;
                    minX = Math.max(minX, 0.0);

                    minY -= getRangeY_Display() / ZOOM_FACTOR;
                    minY = Math.max(minY, 0.0);

                    zoomCount--;
                    // stop zoom out
                    if (minX * minY > 0.0) {
                        maxX += getRangeX_Display() / ZOOM_FACTOR;
                        maxY += getRangeY_Display() / ZOOM_FACTOR;

                    } else {
                        minX = 0.0;
                        maxX = xAxisMax;
                        minY = 0.0;
                        maxY = yAxisMax;
                        zoomCount = 0;
                    }
                }

                if (minX <= 0.0) {
                    minX = 0.0;
                    displayOffsetX = 0.0;
                }
                if (minY <= 0.0) {
                    minY = 0.0;
                    displayOffsetY = 0.0;
                }

                zoomMinX = zoomMaxX;
                zoomMinY = zoomMaxY;

                buildIsochronsAndInitDelta234UContours();
                generateCustomTics();
                repaint();
            }
        }
    }

    private void generateCustomTics() {
        ticsYaxis = TicGeneratorForAxes.generateTics(getMinY_Display(), getMaxY_Display(), 10);
        ticsXaxis = TicGeneratorForAxes.generateTics(getMinX_Display(), getMaxX_Display(), 10);
    }

    /**
     *
     * @param file
     */
    public void outputToSVG(File file) {

        // Get a DOMImplementation.
        DOMImplementation domImpl
                = GenericDOMImplementation.getDOMImplementation();

        // Create an instance of org.w3c.dom.Document.
        String svgNS = "http://www.w3.org/2000/svg";
        Document document = domImpl.createDocument(svgNS, "svg", null);

        // Create an instance of the SVG Generator.
        SVGGraphics2D svgGenerator = new SVGGraphics2D(document);

        // Ask the test to render into the SVG Graphics2D implementation.
        paint(svgGenerator, false);

        // Finally, stream out SVG to the standard output using
        // UTF-8 encoding.
        boolean useCSS = true; // we want to use CSS style attributes

        Writer out = null;
        try {
            out = new OutputStreamWriter(new FileOutputStream(file), "UTF-8");
        } catch (FileNotFoundException | UnsupportedEncodingException fileNotFoundException) {
        }
        try {
            svgGenerator.stream(out, useCSS);
        } catch (SVGGraphics2DIOException sVGGraphics2DIOException) {
        }
    }

    /**
     *
     * @param file
     */
    public void outputToPDF(File file) {
        SVGConverter myConv = new SVGConverter();
        myConv.setDestinationType(org.apache.batik.apps.rasterizer.DestinationType.PDF);
        try {
            myConv.setSources(new String[]{file.getCanonicalPath()});

        } catch (IOException iOException) {
        }
        myConv.setWidth((float) getWidth() + 2);
        myConv.setHeight((float) getHeight() + 2);

        try {
            myConv.execute();

        } catch (SVGConverterException sVGConverterException) {
            System.out.println("Error in pdf conversion: " + sVGConverterException.getMessage());
        }

    }

    @Override
    public void preparePanel(boolean doReScale, boolean inLiveMode) {
        throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
    }

    @Override
    public void refreshPanel(boolean doReScale, boolean inLiveMode) {
        throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
    }

    @Override
    public void resetPanel(boolean doReScale, boolean inLiveMode) {
        refreshPanel(doReScale);
    }

    @Override
    public void setShowTightToEdges(boolean showTightToEdges) {
        throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
    }

    @Override
    public void performZoom(double factor) {
        throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
    }

    @Override
    public PlotAxesSetupInterface getCurrentPlotAxesSetup() {
        throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
    }

    /**
     * @param openSystemIsochronModelsList the openSystemIsochronModelsList to
     * set
     */
    public void setOpenSystemIsochronModelsList(List<OpenSystemIsochronTableModel> openSystemIsochronModelsList) {
        this.openSystemIsochronModelsList = openSystemIsochronModelsList;
    }
}


By Fred Gardner Many of us who get interested in cannabis as medicine get very interested and want to learn more about how it works. One of the first facts you pick up is that the chemical structure of THC was worked out and published in 1964 by Israeli pharmacologists Raphael Mechoulam and Yechiel Gaoni.
Klein, 46, is one of those people who get very interested in cannabis. His 2011 documentary Prescribed Grass told the story of Tikun Olam, Israel's pioneering medical cannabis collective (a group Klein helped organize).
In The Scientist Klein plays the curious Everyman who questions Mechoulam about cannabis and how it works in the body. (Klein's face is handsomer and more expressive than Everyman's.) The interviews are conducted in the pleasant Jerusalem apartment where Raphe and Dahlia Mechoulam have lived since 1966, and in Mechoulam's lab at Hebrew University, and in his car as the scientist drives to and from work, and at a meeting of the International Canabinoid Research Society (a group Mechoulam helped organize).
Klein occasionally carries a potted cannabis plant —a signature prop, like Charlie Chaplin's cane.
Although Mechoulam's manner is gentle and undemanding, he is making a strong plea in The Scientist: cannabis-based medicines should be made available to patients. He does not point an angry finger at any government or agency that has impeded progress —he shrugs in disappointment.
Klein asks why, at the start of his career, Mechoulam chose to study the active compound(s) in cannabis.
About a year later, Mechoulam got a phone call from a high-ranking NIH pharmacolgist who was interested in cannabis.
"So the pharmacologist came over and asked if I was still working on it and I said yes, we had just discovered the active compound and we had a large amount —about 10 grams of THC.
"So he said, 'Please give us the 10 grams and we'll do a lot of pharmacology in the U.S.'" Mechoulam complied. "So he got the world's supply of THC, took it to the US —actually, he probably smuggled it because I don't think he had a license to take it to the U.S. But then of course nobody was looking for THC, it was not a known compound. So he took it to NIH and for the next couple of years most of the research on THC in the U.S. was done with materials supplied by us —those grams that they took.
The hashish from which Mechoulam isolated THC and CBD in the early '60s had been obtained from the police in Jerusalem. Bringing it back to his lab on a bus, Mechoulam drew inquisitive looks and remarks from fellow passengers puzzled by "this very unusual smell." His reminiscence is brought to life in The Scientist by the formidable Swiss-based cartoonist Ivan Art.
Mechoulam shows Klein (and us) a glass column like the one he and Gaoni used all those years ago to separate out "10 or 12 compounds" from their hashish. Of those compounds, only one was found to be active. (Activity was defined as having a sedating effect on monkeys).
With basic safety having been established in the medical literature going back centuries and confirmed at the monkey colony, the logical next step was an experiment with humans.
"We had a few of our friends take 10 milligrams of pure THC on a piece of cake my wife prepared," Mechoulam recalls. "And five took only the cake without the THC, and we compared the effects.
"Another one said 'Nothing happens' —but he didn't stop talking all the time. A third one said, "Well, nothing's happened. But every 15, 20 seconds he would burst out laughing.
One of the participants experienced anxiety. Mechoulam says. "She felt, I believe, that her psychological guards… are breaking down and all of a sudden she was open to everybody. So she really got into an anxiety state.
Note Mechoulam's use of "maybe" and "I believe." He abjures strong assertions and tends towards understatement, as if his knowledge is provisional.
Ideas also come from a respectful reading of centuries-old texts.
Mechoulam recalls his role in advancing a Brazilian study of CBD as a treatment for epilepsy, telling Klein (and us) of "an Arab story from the 15th century and it says that one of the Arab leaders had epilepsy. A physician came over and gave him cannabis and it cured him. But he had to take it for his entire life.
In other words, from Mechoulam's POV, it was not his original insight that cannabinoids would have anti-seizure effects, it was a logical conclusion from reading one's scientific ancestors. What a modest way to describe his role! And how revealing about insight itself!
When anti-Jewish laws were enacted, Mechoulam says, the family moved to a series of small villages where a doctor was needed and respected. "But at some point somebody decided that my father should be taken to a concentration camp," Mechoulam says. Dr. Mechoulam was released, apparently in appreciation for his heroic usefulness after a fire destroyed the camp.
With a twinkling eye, Raphael Mechoulam tells Klein how his uncle saved the Jews of Bulgaria from the Nazis' extermination camps. We won't spoil it. You've got to watch this movie for yourself.
After doing post-doctoral research at the Rockefeller Institute in Manhattan, Mechoulam took a position at the Weizmann Institute in Rehovot, which is where he and Gaoni isolated the compounds in hashish. Mechoulam joined the Hebrew University faculty in 1966.
The next challenge for scientists was to find the body's own endogenous cannabinoids, "In my lab there were three collaborators who contributed a lot in this research," Mechoulam tells Klein, as he enters a room where two of those collaborators —Lumír Hanuš and Aviva Breuer— are still at the bench.
Hanuš explains that he came from Czechoslavakia 23 years ago "just for one year, and got a little bit overextended." Already working with Mechoulam as of 1991 was Bill Devane, who played a key role in Allyn Howlett's lab when the receptor was identified.
"We initially worked on brains of pigs," Mechoulam says of the search for the endogenous cannabinoid. "It is generally accepted that the organs of pigs and the organs of humans are somewhat closely related. And probably pigs and humans are also somehow closely related. Well, I'm not sure that the pigs will be very happy to be related to humans, but that's something else.
"So we wanted to work on pig brains and pig brains are not so easy to get in Jerusalem." A butcher was found in Tel Aviv who supplied the brains readily at first, but began charging as he realized that his new customers had an ongoing need for the material.
But when Hanuš's year came to an end, the endogenous cannabinoid had still not been isolated. "So we asked Professor Mechoulam to extend," Hanuš tells Klein.
Other scientists were seeking to identify the endogenous cannabinoid, and Devane says that Mechoulam "thought we might be scooped by some other lab." But he kept Devane and Hanuš on the project and in 1992 they isolated a small amount of compound they identified arachidonoyl ethanolamide.
"It was only like a few droplets in the end of a little test tube," Devane remembers.
The task of confirming that the newly discovered compound had the properties that define a cannabinoid was carried out by University of Aberdeen pharmacologist Roger Pertwee.
Because the compound was an ethanol amide, and amide fit nicely behind the Sanskrit root, the endogenous cannabinoid was dubbed "anandamide" —a name that says something about its effect and its chemical structure.
It was Mechoulam who inspired Ethan Russo and Vincenzo DiMarzo to think in terms of entourage effects —compounds acting in concert— instead of single molecules. It was Mechoulam who urged Itai Bab to explore the role of endogenous cannabinoids in bone, and Ester Fride to study their role in the birthing process and breastfeeding.
Mechoulam arranged for a clinical trial led by pediatric oncologist Ava Abramov. "Obviously children cannot smoke. We had children that were not even one year old. She dropped THC in olive oil under the tongue two or three times a day, small doses, during the anti-cancer treatment.
"There was a complete separation. Those that didn't get it continued to vomit. So she went ahead doing an open study. She gave THC —pure THC— under the tongue about 400 times [during the course of a child's treatment]. And at the end we had complete —complete— block of vomiting, a complete block of nausea by a small amount of THC. We did not cause any psychoactivity, nothing.
Mechoulam has no misgivings. "Well I believe it's an excllent idea because we help those children that suffer. But I have no influence on oncologists." He shrugs and smiles ruefully.
Klein asks, "Can cannabis cure cancer?" Mechoulam answers: "We know that THC lowers the [nausea] effects of cancer treatment. But what you're asking is 'is it an anti-cancer drug?' And the answer is, 'I don't know.' And the reason for that is silly.
Klein asked Mechoulam, "Do you have a dream?" The answer was earthbound and poignant: "I have one dream that comes on and off in very different ways. I'm in a city that I don't know. and I don't know how to go back to the hotel I'm staying and I don't remember the name of the hotel and I get into an anxiety and I wake up. And this has happened many times. I think it has to do with whatever happened in the Second World War when my parents told me 'Remember these names and these addresses.' Because if we disappear, you should go there. Which is, well, not very pleasant, which is quite a shock, probably, to a child. And of course we were very afraid that we'll be separated, my parents and I. I was afraid.
Mechoulam describes a study in which cannabis "seems to be helping the symptoms of Alzheimer… Alzheimer at the moment is a huge, huge problem and there is very little that can be done for Alzheimer's patients. So maybe if it is well researched in the future, we should know how to help these patients… We are lucky that cannabis is not toxic.
The Scientist ends with a clip from Mechoulam's 2012 talk to the International Cannabinoid Research Society.
Mechoulam elaborates to Klein: "One way of explaining it is there are several hundred endocannabinoid-like compounds —they are like anandamide in their chemical structure— present in the brain.


text:
Q: What is the equivalent to $stateProvider from angularJS in angular 12? I'm migrating code from AngularJS to Angular 12, what's equivalent to $stateProvider in angular 12?
I see that $stateProvider related to ui-router, can I use something from AppRoutingModule that gives the same functionality?

A: To manage state in an modern version of Angular you have some different options. You can work with services and observables in order store your state and subscribe to it everytime you need it. You could also use per example libraries like https://ngrx.io/.

redpajama_set_name: RedPajamaStackExchange


text:
Where Stories are Celebrated
I have been blessed with visiting places where stories have been celebrated for centuries. And here are photos and drawings of two of these in Oregon. At both sites, there is a stone bench near the rock writings where a storyteller sits and shares stories. There's room around each bench where folks sit and listen, and each site has the acoustics of a natural stone amphitheater. I've sat on the benches a few times over the past three decades and spun stories. As they worked their magic, I felt that I was part of something both ancient and currently vibrant. Here's some words I wrote years ago that describe the energy and presence of these sacred places for stories....
In Oregon, there are places where the voices of Mother Landscape have been heard and her stories painted and carved on cliffs. A few of these pictures show the storyteller as she abandons her role as narrator to join her story as a dramatic participant. In firelight, in the depths of a winter evening, characters come alive and speak directly to each other and to those in the audience. This is the most ancient spark of performance.
The storyteller's words sizzle with depth. Layers of truth emerge as her story swells beyond sound to include a visual canvas of gestures and movements. Like the story itself, shadows cast on walls by firelight loom larger than the event. What is real transcends itself into what is possible. Not only is the storyteller transformed, so are her listeners.
In the pictures they are often portrayed as myth characters. Perhaps those who were most deeply touched by the stories were the artists who were inspired to create the pictures. If one looks long enough at the images, it isn't hard to imagine that there is a time in each story when listeners become so engaged in the narrative that they leap up and join in a telling that soon becomes a dance drama.
When we visit the cliffs and view these pictures we are reminded to remember.
View Larger Photo (PDF)

redpajama_set_name: RedPajamaCommonCrawl


When processing an app to your corporation and receive it legally registered, you become qualified with respect to bank loans. Small enterprises generally own very limited methods and give a restricted range of products and alternatives. You can't commence a business mainly because you imagine that you simply suitable of doing this. Adequate proving an enterprise in the business then getting diligent even though completing the paperwork will not only offer you a feeling of results nevertheless as well make certain your business's safe and sound future. Businesses may use the organized data to lower costs and improve profits. Today, employing venture software suppliers are getting more widespread. These kinds of providers are usually restricted to the particular small enterprise area.
The templates are a slight wind to work with combined with free to down load. They happen to be easy to use and are packed with many features that allow you to revise these people to satisfy your specific requirements. That they can be without difficulty downloaded on the web. They will are very reasonably listed. Additionally, they incorporate pre loaded products to help you whenever you get caught up.
Pretty much all the data utilized by simply the industry user is also applied to the exploration. Non-technical people who include to offer with crucial data just like they had been advisors can easily easily employ Kohezion. Working together with a DRONE application makes it a whole lot easier for your business to sort unstructured info into even more intelligent and meaningful accounts that could be applied to various methods. Since there is certainly nowadays consequently much info readily readily available, business intelligence applications have changed into a vital portion of just a little firm's toolbox of tactical equipment.
In the area of organization, applications can be found to display or classify an individual or business entity. Enterprise applications are manufactured to become deployed across various corporate networks, intranets or the the net and also meet strict requirements for reliability and software administration. On the other hand, the applications should become good enough to support the task that should be carried out. When a organization software falters a single really wants to appropriate this company program problem anytime possible so the business users can return to their function. Business applications are designed reliant on the requirements from your company users. Business Applications prepares learners to come to be successful at work. An on-line program, in some cases usually a wealthy internet software, is definitely typically an interactive software that can be gathered through a web browser.
Organization computer software is a kind of business computer software that's created to serve a specific kind of organization. Organization software is expected for huge businesses that require software which may scale while using requirements of your company. Equipment like MailChimp make this simple to roll-out promotions from a cellular gadget. Different equipment make it possible for builders to produce one of a kind types of internet applications. The Best net Survey Tools make this possible meant for one to set up and have part in study by your mobile or portable device.


text:
EnglishBengaliHindi
English Bengali Hindi
Mushfiqur Rahim to auction his maiden double century bat for COVID patients
Sports Info 9 months ago
Mushfiqur Rahim, the Bangladesh batsman, is set to auction the bat with which he scored his maiden double century in Test cricket. It's because the 32-year-old has decided to come forward for the ones affected in the massive coronavirus pandemic. Mushfiqur was the first Tigers' batter to get a Test double when he accomplished the feat against Sri Lanka at Galle back in 2013.
On the back of the knock in the first match of the series, Bangladesh eked out a drew after fetching a first-innings lead. The bat has a special place in his heart, but he understands the need to lend his helping hand in the COVID fight and make the sacrifices.
I had special liking for this bat: Mushfiqur Rahim
"Definitely, the bat is very special to me because it is attached to history. Not everyone can become the first double centurion for his country. I had special liking for this bat. But there is nothing more important than human life and so I have decided to put it into the auction," Mushfiqur was quoted as saying to the reporters on Sunday, April 19.
"If through this sacrifice I can help one or two people than that will be my biggest achievement. If I find a good response in the auction for the bat than I have got few more things that I will put up in the auction. I don't think there is nothing important than helping out people during their time of distress," the Bogra-born added.
Mushfiqur is the only Bangladesh batsman with as many as three double centuries. In 2018 and 2020 versus Zimbabwe, he got the other two 200 plus scores. He also has the highest individual Test score of 219* for his country. Of later, Mushfiqur toppled Tamim Iqbal as the all-time leading run-scorer for Bangladesh in Test when he scored 203* against Zimbabwe in Dhaka.
Moreover, Mushfiqur donated half of his cricket salary during the critical situation. In Bangladesh, the coronavirus cases have gone up to 2,456 with the death tolls up to 91. Like most other nations, even the Asian country is going though a lockdown period as a precautionary measure.
Sports Info
SportsInfo offers cricket, soccer, kabaddi, tennis, badminton, racing, basketball and other sports news, articles, videos, live coverage & live scores, player rankings & team rankings. Also, offers minute details of any match along with live commentary.
Readlist
Bangabandhu T20 Cup: Mushfiqur Rahim had gestured to hit Nasum Ahmed twice in the same match
Mushfiqur Rahim fined for his rude behaviour towards his teammate in Bangabandhu T20 Cup
'It was not acceptable at all' – Mushfiqur Rahim apologizes to his fans and teammate Nasum Ahmed after losing his cool in Bangabandhu T20 Cup
Bangabandhu T20 Cup: Mushfiqur Rahim loses his cool at teammate Nasum Ahmed for interfering while catching
I feel there is no chance of leading the national side: Mushfiqur Rahim
Bangabandhu T20 Cup: Mushfiqur Rahim had gestured ...
Mushfiqur Rahim fined for his rude behaviour towar...
'It was not acceptable at all' – Mushfiqur Rahim a...
Bangabandhu T20 Cup: Mushfiqur Rahim loses his coo...
I feel there is no chance of leading the national ...
MS Dhoni is my idol, I'm fond of his captaincy: Mu...
Bangladesh call up uncapped Nasum Ahmed for Zimbab...
Family is important for everybody, but the country...
Stats: Milestones galore for Mushfiqur Rahim durin...
Mushfiqur Rahim reveals the exact reason behind hi...
©2021 Sports Info. All Rights Reserved.
Flash Score
Ooops! No live commentaries available at the moment.
New version of SportsInfo is available.
Hi! We use cookies on this website to help operate our site and for analytics purposes. For more on how we use cookies, Visit Terms & Conditions.
By continuing to use our services, you are giving us your consent to use cookies.
Ooops ! SportsInfo needs access to Javascript to render better experiences. Enable JS


text:
Royal Philharmonic Orchestra (RPO) Tour Dates
Founded in 1946 by Sir Thomas Beecham and described by the Daily Telegraph as 'a true premier league orchestra'. Acknowledged as one of the UK's most prestigious orchestras, the RPO enjoys an international reputation for first-class performances.
Official website rpo.co.uk
Feb 09 Sun
Royal Philharmonic Orchestra (RPO)
Northampton, Royal & Derngate Theatre
Coventry, Warwick Arts Centre
Rufus Wainwright Royal Philharmonic Orchestra (RPO)
Hastings, The White Rock Theatre
On sale Fri 20th Nov 10am
John Williams Gala Royal Philharmonic Orchestra (RPO)
Sunderland Empire
Royal Philharmonic Orchestra (RPO) Tasmin Little, Thierry Fischer
Nottingham, Theatre Royal and Royal Concert Hall
Cardiff, St David's Hall
Messiah On Good Friday The Royal Choral Society, Royal Philharmonic Orchestra (RPO)
London, Royal Albert Hall
Beethoven, Mendelssohn And Saint-Saëns Royal Philharmonic Orchestra (RPO), Moritz Gnann
The Four Seasons Royal Philharmonic Orchestra (RPO)
Scunthorpe, Baths Hall
May 09 Sat
Film Music Gala Royal Philharmonic Orchestra (RPO)
Let's Face The Music Royal Philharmonic Orchestra (RPO)
Sep 17 Thu
Last Night Of The Proms Royal Philharmonic Orchestra (RPO)
Rescheduled
Sep 19 Sat
Beethoven's Ninth London Philharmonic Choir, Royal Philharmonic Orchestra (RPO)
The Planets Royal Philharmonic Orchestra (RPO), City Of London Choir, Hilary Davan Wetton, Danny Driver
Carmina Burana English Concert Chorus, Goldsmiths Choral Union, Southend Boys Choir, Andrew Greenwood, Helena Dix…
Nov 07 Sat
Film Gala Royal Philharmonic Orchestra (RPO)
Fans who like Royal Philharmonic Orchestra (RPO) also like:
City Of Birmingham Symphony Orchestra (CBSO)
Royal Philharmonic Concert Orchestra
The Hallé Orchestra
The Royal Liverpool Philharmonic Orchestra (RLPO)
The BBC Concert Orchestra
The London Mozart Players


text:
This site may not function properly in your current browser. Update Now
Four Corners Region
Developed in association with
Trip Plans
Colorado Welcome Center at Alamosa
Visitor or Interpretive Center
Colorado Welcome Center Alamosa Train Depot
Colorado has 10 Welcome Centers, located in key entrance points across the state. The Welcome Centers, which are staffed by an outstanding group of volunteers, serve as a great source of information for visitors coming to Colorado. The Alamosa Welcome Center is particularly unique as it is located in the historic Alamosa Train Depot. Alamosa was founded in part, due to the railroad. The first Denver & Rio Grande train arrived in Alamosa in 1870. By 1880, it was the center of narrow gauge railroading in America. The Alamosa Train Depot was built in 1908-1909. The town quickly sprung up from the railroad and Sixth Street became the heart of activity and commerce. After the decline of railroad transportation, the building was used as various government offices over the years.
In 2009, the interior renovations were made for the Colorado Welcome Center to move into their ideal home. Listed on the National Historic Register, the Depot features the architecture and memorabilia reminiscent of a bygone era. Partnering with the Rio Grande Scenic Railroad, this center offers visitors a place to stop and stretch their legs, or pick up their train tickets for a ride on the Railroad. Visitors can also get maps, statewide information, road conditions, personalized travel itineraries, information on lodging and activities, free cup of coffee, and access the internet.
Pet Friendly Notes
Very Pet Friendly! There is plenty of room for a nice walk outside, but don't forget to bring Fido in to say hello!
Summer 8 am-6pm Winter 8am - 5pm
Seasons Open
Explore All Places
Add Places to the Map Guide!
Privacy Policy Terms of Use Log In


text:
Kino és un grup britànic de rock neo-progressiu format per membres d'altres grups (John Mitchell d'Arena i The Urbane; Pete Trewavas de Marillion, Transatlantic i  Edison's Children; John Beck d'It Bites; Bob Dalton d'It Bites; Chris Maitland de Porcupine Tree).

La formació va treure el seu àlbum de debut, Picture al febrer del 2005.

Enter el període del 2006 al 2018 va estar inactiva degut a que Mitchell es va reunir amb Beck i Dalton als reformats It Bites, reemplaçant al guitarra i cantant original, Francis Dunnery, fent una gira el 2006 i realitzant dos àlbums. A part, la banda ha deixat d'aparèixer a la web del seu segell, InsideOut.

Al Gener del 2018, Mitchell va anunciar que reformava la banda amb Trewavas, Beck i Craig Blundell reemplaçant a Chris Maitland a la bateria. Al Març del mateix any editen un nou disc en estudi, 'Radio Voltaire'.

Formació
 John Mitchell: veu solista, guitarres (2004–2006, 2017–present)
 Pete Trewavas: baix, bass pedals, cors (2004–2006, 2017–present)
 John Beck: sintetitzadors, cors (2004–2006, 2017–present)
 Chris Maitland (Gravació a l'estudi de Picture): bateria i percussions, cors (2005)
 Bob Dalton: bateria i percussions, cors (2006)
 Craig Blundell: bateria i percussions (2018–present)

Discografia
 Picture - àlbum en estudi, Febrer 2005
 Cutting Room Floor - recopilació, Desembre 2005
 Radio Voltaire - àlbum en estudi, Març 2018)

Referències

Enllaços externs
 Kino Myspace
 Web d'It Bites
 Inside Out

Grups de rock anglesos
Supergrups

redpajama_set_name: RedPajamaWikipedia


text:
Ad will collapse in seconds…
fashion yearbook January 13, 2012
See Kirsten Dunst, Elle Fanning, George Clooney, Stacy Kiebler, and More from the Critics' Choice Awards Red Carpet
Photo: Jason Merritt/Getty Images
The People's Choice Awards were a mostly forgettable melange of black and shiny dresses worn by a group of people that was painfully hard to mentally place from their career achievements alone (if a testament to the power of things you might suppose people don't care about anymore, like High School Musical or Dancing With the Stars). Last night, one after the People's Choice Awards, a mostly different crowd of much more recognizable names turned up for the Critics' Choice Awards. Again, the attending actors wore a lot of black dresses, which is seldom a great color for the red carpet because it can easily wash people out and, the detail often never fully realized in photos of these outfits, makes people look like floating heads and arms behind an old-fashioned printer ink splotch.
Hopefully, this is a a realization the stars will come to on their own before the Golden Globes on Sunday. Remember how unexpected and fun it was when so many people wore emerald green to those awards last year? We can't expect 99 percent of these people to wear anything that's truly cool, lest they alienate the vast majority of potential fans that doesn't pay attention to or care about runway fashion, but if they're going to dress from a place of fear, may they at least feel the rainbow on their sinewy, juice-fasted bodies. In the slideshow, see what Kirsten Dunst, Elle Fanning, Elizabeth Olsen, and more wore to the Critics' Choice Awards last night.
1 / 19 Photos
more-arrow
Expand Photo
Diablo Cody Her Sharon Osbourne-esque look of late makes me miss the old her, which may not have been perfect from a fashion perspective (though ...
Diablo Cody Her Sharon Osbourne-esque look of late makes me miss the old her, which may not have been perfect from a fashion perspective (though she was wearing leopard print long before the rest of the trend-hungry), but was more interesting than a designer bedding display at Macy's. Photo: Jason Merritt/2012 Getty Images
Maya Rudolph See what happens with the black? You know this must be more interesting than it looks, and thanks to the bit of structure on the wai...
Maya Rudolph See what happens with the black? You know this must be more interesting than it looks, and thanks to the bit of structure on the waist detailing you can see that it is, but especially on a drab, gray, Sears-portrait quality step-and-repeat (what the hell, Critics' Choice?), it's a dismal, funereal even, effect. Photo: Jason Merritt/2012 Getty Images
Tilda Swinton For a 51-year-old, a look like this makes sense for a psuedo-serious award show. The coloring may be a little Hostess Cupcake/Oreo ...
Tilda Swinton For a 51-year-old, a look like this makes sense for a psuedo-serious award show. The coloring may be a little Hostess Cupcake/Oreo cookie/whatever but it's an example of breaking up black to make it more palatable in a red carpet photo. Photo: Jason Merritt/2012 Getty Images
Brad Pitt Brad is walking with a cane because, ever the valiant patriarch, he injured his Achilles tendon while carrying his daughter. But, like ...
Brad Pitt Brad is walking with a cane because, ever the valiant patriarch, he injured his Achilles tendon while carrying his daughter. But, like when Andre Leon Talley has one, it really is slick. Photo: Jason Merritt/2012 Getty Images
Evan Rachel Wood The sad thing about this outfit is that the shoes, the most interesting part, don't even get any air time unless the red carpet ...
Evan Rachel Wood The sad thing about this outfit is that the shoes, the most interesting part, don't even get any air time unless the red carpet photographers ask her to hike up her dress and show them off. Photo: Jason Merritt/2012 Getty Images
Charlize Theron This Azzedine Alaia dress and side braid business is an unusual choice for the red carpet, and works on Charlize, though any othe...
Charlize Theron This Azzedine Alaia dress and side braid business is an unusual choice for the red carpet, and works on Charlize, though any other less-blessed woman who tried to wear a fishtail gown with tumor-y protrusions from the hips down might just look like a stack of spare tires. Photo: Jason Merritt/2012 Getty Images
Chloe Moretz Is that a Ouiga board on her collar bones? Something to do in case she gets bored inside? Photo: Jason Merritt/2012 Getty Images
Elizabeth Olsen For the record, this dress is Pucci, not a game of Parcheesi. Photo: Jason Merritt/2012 Getty Images
Stacy Keibler and George Clooney In yesterday's People's Choice slideshow we played a little game where we explained who everyone was, because so...
Stacy Keibler and George Clooney In yesterday's People's Choice slideshow we played a little game where we explained who everyone was, because so many people who walk red carpets are impossible to place with their myriad of reality dance telvision and High School Musical associations that brought them there. So, how much do you know about Stacy Keibler? She is "best known for her work with World Championship Wrestling(WCW) and World Wrestling Entertainment (WWE)," Wikipedia tells us. "She began her professional wrestling career as a part of the Nitro Girls in WCW.[1][5] She quickly moved on to a more prominent role in the company as the manager, Miss Hancock (sometimes "Handcock")," the article continues. "Despite wearing business suits, her character was known to climb on top of the announcers' table and dance sensually.[6] It was also during this period that she began using what would become her trademark ring entrance: slowly putting her forty-two inch legs through the second tier of ropes, pausing to let the crowd momentarily see her panties." Also, she was on Dancing With the Stars. So far, from a red carpet style standpoint, she's been poised and inoffensively dressed as George Clooney's arm candy, the color of her panties consistently and happily a mystery. She's undergoing a perfectly decent sartorial evolution. Photo: Jason Merritt/2012 Getty Images
Elle Fanning This little infusion of springtime relief is Rodarte. Photo: Jason Merritt/2012 Getty Images
Busy Phillips Busy wearing primary colors, apparently. Photo: Jason Merritt/2012 Getty Images
Kirsten Dunst This is an example of a black dress that has enough texture and stuff going on to photograph well. But still, don't you kind of wis...
Kirsten Dunst This is an example of a black dress that has enough texture and stuff going on to photograph well. But still, don't you kind of wish it was a color? Like NEON ORANGE? Just for the sake of us having one clearly scary dress in this bunch? Photo: Jason Merritt/2012 Getty Images
Diane Kruger "Uterus" is probably not the word you want people to think when they look at you wearing a dress. Photo: Jason Merritt/2...
Diane Kruger "Uterus" is probably not the word you want people to think when they look at you wearing a dress. Photo: Jason Merritt/2012 Getty Images
Emma Stone Even if you don't like Emma Stone's clothes, she looks fantastic pretty much all the time because she looks sincerely happy when she g...
Emma Stone Even if you don't like Emma Stone's clothes, she looks fantastic pretty much all the time because she looks sincerely happy when she goes to these things. I don't much care for these keyhole things here but I predict a good outfit from her on Sunday. Photo: Jason Merritt/2012 Getty Images
Melissa McCarthy Beyonce would most definitely approve of the dense sequining of this dress. Photo: Jason Merritt/2012 Getty Images
Shailene Woodley I don't dislike how minimal this is, but I wish there was just one more element to the look. A lipstick, a ring, a bracelet, an ...
Shailene Woodley I don't dislike how minimal this is, but I wish there was just one more element to the look. A lipstick, a ring, a bracelet, an empty handbag, a rhinestone tattoo (remember those?). Just one visual punch. Photo: Jason Merritt/2012 Getty Images
Carrie Keagan I went from not knowing who this was until yesterday to rapidly falling in love with Carrie Keagan as a red carpet person...
Carrie Keagan I went from not knowing who this was until yesterday to rapidly falling in love with Carrie Keagan as a red carpet person. "MEEE!" her photos say, in moment after moment of touching honesty. Photo: Jason Merritt/2012 Getty Images
Jessica Chastain I like this color but it also calls to mind a big set of human gums. Photo: Jason Merritt/2012 Getty Images
Michelle Williams Michelle reliably wears more unusual things that tend to suit her, which I love, but I'm mixed on this color-blocking. What say...
Michelle Williams Michelle reliably wears more unusual things that tend to suit her, which I love, but I'm mixed on this color-blocking. What say you? And while you're down there, do feel free to share your hopes/dreams/disinterest in the Golden Globes red carpet happening Sunday in the comments. Photo: Jason Merritt/2012 Getty Images
stacy kiebler
critics choice awards
fashion yearbook
parties! 7/15/2019 at 5:42 p.m.
Gucci's Popping Up in Montauk This Summer With help from vintage shop Melet Mercantile.
the wedding files 7/12/2019 at 11:12 a.m.
The Bride Who Designs Wedding Flowers for a Living A New York wedding full of roses and sea oats.
By Kaitlin Menza
the wedding files 7/5/2019 at 9:00 a.m.
A Tropical Wedding Oasis in Joshua Tree The couple served Pakistani food and wore garlands.
A Wildflower Wedding in Texas Hill Country Spicy margaritas and BBQ brisket were served.
6/24/2019 at 11:57 a.m.
The Best Looks From the BET Awards Red Carpet From Lil Nas X to Lizzo.
By Sarah Spellings
6/21/2019 at 9:00 a.m.
A Rooftop Farm Wedding Among the Sunflowers Laura Linney read a poem to the grooms.
obituaries 6/17/2019 at 12:52 p.m.
Socialite, Artist, and Style Icon Gloria Vanderbilt Has Died at 95 Her son, Anderson Cooper, delivered an obituary on CNN this morning.
the wedding files 6/14/2019 at 9:00 a.m.
A Rock Opera Wedding in Tuscany The party kicked off with a water ballet and ended with skinny-dipping.
6/10/2019 at 2:09 p.m.
Dyke Day L.A. Was a Sunny Celebration of Love Twenty-four photos from Saturday's event.
By Paola de Varona
the wedding files 6/7/2019 at 12:35 p.m.
A Wedding Among the Redwoods The brides served three kinds of boba tea.
The Bride Who Carried an Owl Down the Aisle Brooke Wall and Jason Cannon got married at a former fly-fishing lodge in the Catskills.
the wedding files 5/24/2019 at 2:02 p.m.
A Gowanus Wedding With Pizza and Doughnuts The bridesmaids wore white, while the bride wore florals.
red carpet derby 5/24/2019 at 1:17 p.m.
The Cannes Red Carpet Is Having a Very Good Year The festival is known for an extravagant red carpet and has not disappointed.
game of thrones 5/20/2019 at 11:15 a.m.
Jon Snow's Hottest Moments on Game of Thrones His pouts, his hairdos — a retrospective of smoldering.
A Brewery Wedding During a Congressional Campaign The groom now represents the 11th district of New York.
A Look Inside Dior's Lavish Masquerade Ball Tilda Swinton and Karlie Kloss partied in a Venice palazzo.
By Andrew Nguyen
talent scout 5/13/2019 at 5:54 p.m.
See Looks From the 2019 Pratt Institute Fashion Show Pyer Moss's Kerby Jean-Raymond was the honorary guest of the evening.
A Sikh-Jewish Wedding That Ended in Fireworks On a horse farm upstate.
5/9/2019 at 4:00 p.m.
The Best Street Style From the Contemporary African Art Fair From traditional textiles to of-the-moment jumpsuits.
People-Watching at the Frieze Art Fair Where else could you wear a sequined face mask and a blazer?
By Lee Musho


Treat someone special to an extra special treat with a Crerar Hotels gift voucher. Whether it's a spot of afternoon tea, dinner from an award-winning restaurant or a hot stone massage, our breaks, food and spa vouchers are a great way to spoil a friend, family member or loved one.
We offer a fantastic selection of experience vouchers ranging from spa pamper days to one night stays with everything included. We also have a selection of monetary vouchers that can be redeemed across all our hotels in Scotland.
Click the link below to see all our vouchers on offer and have them delivered straight to your doorstep.


It was a rainy afternoon on February 8th at the University of Waterloo, but that did not stop the University of Waterloo Alternative Fuels Team (UWAFT) from engaging the student body in a discussion surrounding the automotive industry and sustainability in the region. Leading the discussion was a panel of community leaders including local MPP Catherine Fife, directing manager of the Waterloo Centre for Automotive Research (WatCAR) Ross McKenzie, Powertrain Engineer for Green and Intelligent Automotive (GAIA) Stef Bruinsma, and of course UWAFT project manager Daniel Van Lanen. Each panel member brought their own perspective to a variety of topics such as sustainability in Kitchener/Waterloo, autonomous vehicles, diversity in STEM sectors (Science, Technology, Engineering, and Math Education), and the impact of low gas prices on environmentally friendly vehicles. More details regarding this event are shared amongst the photos below.
UWAFT System Safety Officer John Catton assists with setting up zap banners prior to the event. We were proud to have such a strong attendance from both the student population and team members.
Upon arriving in the Student Design Centre for the panel discussion, guests were invited to pick up some branded UWAFT swag. At the table UWAFT members greeted the guests and provided them with more information on our team. Guests were also asked to participate in a short survey to learn more about their conceptions regarding environmentally friendly vehicles.
Catherine Fife brought some great perspective to the discussion with her insights on how the Ontario government works alongside the automotive industry to promote sustainability. Fife made a point to mention that the province is a leader in clean energy and there is no reason why Ontario cannot become a leader for manufacturing the next generation of environmentally friendly vehicles. There is a role for the government to reward consumers for making sustainable decisions, and spark a culture shift towards green products.
In addition to Catherine Fife's contributions to the discussion, other panel members brought insights of their own to further the discussion. On the topic of diversity in STEM, all were in agreement that more needs to be done to promote women and minorities in these industries. Van Lanen made note that diversity is an important part of creating new ideas and furthering innovation in the sector. As a female in a male dominated industry, Bruinsma mentioned that she had to deal with gender based expectations and earn the respect of her colleagues. Finally, McKenzie advocated that outreach initiatives are very important to increase exposure to the industry.
Also on hand for the event were members of General Motors recruitment team. Students in attendance were eager to talk to the recruiters regarding possible career opportunities, and to learn more about jobs at General Motors.
Those in attendance gained not only the insights of community leaders but also their advice on what needs to be done to foster success within the next generation of the automotive industry.


Shepherd's Delight is nestled under a hedge overlooking open countryside with wonderful views across the Aylesbury Vale. It has its own eco loo inside and an outside shower just beside the hut. There is a flushing loo and a shower at the farm if guests prefer.
Peacefully off the beaten track Hill View Farm is a small working family farm. Depending on the farming year/calendar our fields rotate between corn and grass. In the summer months we harvest the corn or make hay or silage from the grass and graze our cattle. The hut has a gate/wooden fence surrounding it to ensure that any inquisitive cattle can't get too close when grazing in the surrounding fields.
Hill View Farm is not far from the Cotswold and Chiltern hills should you wish to venture further afield. If you fancy leaving the car behind you can either walk or use our bikes to cycle around the area taking in the countryside. There are a number of local pubs serving food (see "places of interest" page).
In nearby Twyford there is a well stocked village shop run by the locals and at Stratton Audley there is a gelato ice cream parlour, cafe and gift shop. There will be a welcome hamper to greet you when you first arrive, also a supply of basics such as coffee, tea and sugar in the hut.
If you prefer to prepare your own meals either on the BBQ or the little stove, you can top up your supplies in the nearby village of Launton which boasts an excellent traditional butcher and deli.
£83.34 + vat (£100) per night, minimum booking 2 nights.
Unlike times gone by, the hut has luxuries that no shepherd would have enjoyed. Inside there is a king size bed, eco loo, running water, 2 ring hob, a fridge and a wood burner. The hut even has its own solar panel providing lighting and 2 x 12V sockets. Though you may never need us, Hill View Farm Bed & Breakfast is just a brief five minute walk away if you do.


Bi Fold Doors (also known as bifolding doors, or folding doors) are the latest must-have home improvement for UK homeowners. They are a modern, contemporary alternative to traditional sliding patio doors, but provide much wider clear openings than patio doors.
Bifold Doors are similar to French doors, but can cover a far greater space – high quality Bifold Doors can easily handle open spaces of 7 metres or more.
Aluminium, plastic (uPVC) and timber are the most common materials used to manufacture Bifold doors – and each material has its pros and cons with regards to sightlines, colour, durability, reliability, maximum size and expansion in hot weather.
If you would like to add a wow factor to a newly built home extension, or open up a Juliet balcony on a loft conversion, these bi fold doors are a must have addition.
Many systems support both double glazing and triple glazing for optimal thermal performance, and internal integrated blinds are a popular and convenient option.
External Bi Fold doors really can bring the outdoors indoors – giving you a beautiful unobstructed view of your garden from within. Internal bi fold doors are a stylish, contemporary way of opening up indoor spaces to give all the benefits of an open plan living area to any home.
* prices subject to pre constructed opening, If you require opening in wall please refer to our steel beam installation service.
We have published reports and case studies on the relevant subject area to help you better understand the products of services you may wish to procure.


Everyone who works with SketchUp, sooner or later, will face the need to share a presentation of his models with other people, but frequently without sharing the original file. There are some solutions available to perform this task, but recently, I found a new project - Kubity - and it looks very handy. Kubity transforms easily, any Sketchup file in a "visitable" model, directly in your browser, without any need of plugins. All one have to do, is drag the file to the Kubity site and after the upload ends, configure the scene, using the available options for sky, terrain, water and "smart objects" such as trees, particles (fire, fountains) or links to external pages. An important issue to refer is that the configuration process is very fast and also very easy to learn.
Kubity is a recent project, so it's in constant evolution and new features are being introduced regularly. For now, it works well in Windows 8 with Firefox or Chrome and it may be used in mobile platforms.
Currently I'm using Kubity in my work, everytime I have to show my Sketchup models to clients or colleagues, (I find it far more interesting and flexible than Sketchfab, for instance), so why don't give it a try?
Nice work with the baggage handling system and the roman villa!
Kubity is indeed a handy WebGL renderer and provides several navigation modes and other useful features and scene enhancements.