ch.unibas.fittingwizard.presentation.fitting.FittingParameterPage.java Source code

Java tutorial

Introduction

Here is the source code for ch.unibas.fittingwizard.presentation.fitting.FittingParameterPage.java

Source

/*
 * Copyright (c) 2015, Florent Hedin, Markus Meuwly, and the University of Basel
 * All rights reserved.
 *
 * The 3-clause BSD license is applied to this software.
 * see LICENSE.txt
 *
 */
package ch.unibas.fittingwizard.presentation.fitting;

import ch.unibas.fittingwizard.application.fitting.ChargeValue;
import ch.unibas.fittingwizard.application.fitting.FitRepository;
import ch.unibas.fittingwizard.application.molecule.*;
import ch.unibas.fittingwizard.application.scripts.fitmtp.FitMtpInput;
import ch.unibas.fittingwizard.application.tools.charges.ChargesFileGenerator;
import ch.unibas.fittingwizard.presentation.MoleculeListPage;
import ch.unibas.fittingwizard.presentation.base.ButtonFactory;
import ch.unibas.fittingwizard.presentation.base.DefaultValues;
import ch.unibas.fittingwizard.presentation.base.WizardPage;
import ch.unibas.fittingwizard.presentation.base.dialog.OverlayDialog;
import java.io.File;
import java.util.*;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.fxml.FXML;
import javafx.scene.control.Button;
import javafx.scene.control.CheckBox;
import javafx.scene.control.ComboBox;
import javafx.scene.control.TextField;
import org.apache.commons.lang.NotImplementedException;

/**
 * User: mhelmer
 * Date: 29.11.13
 * Time: 17:14
 */
public class FittingParameterPage extends WizardPage {

    private final File sessionDir;
    private final EditAtomTypeChargesDialog editAtomTypeChargesDialog;
    private final FitRepository fitRepository;
    private final MoleculeRepository moleculeRepository;

    @FXML
    private CheckBox chkIgnoreHydrogen;
    @FXML
    private TextField txtConvergence;
    @FXML
    private ComboBox<RankItem> cmbRank;

    public FittingParameterPage(FitRepository fitRepository, MoleculeRepository moleculeRepository,
            DefaultValues defaultValues, File sessionDir, EditAtomTypeChargesDialog editAtomTypeChargesDialog,
            FitMtpInput fitMtpInput) {
        super("Fitting parameters");
        this.fitRepository = fitRepository;
        this.moleculeRepository = moleculeRepository;
        this.sessionDir = sessionDir;
        this.editAtomTypeChargesDialog = editAtomTypeChargesDialog;

        setupComboBox();
        if (fitMtpInput != null) {
            setupInitialValues(fitMtpInput.getRank(), fitMtpInput.getConvergence(), fitMtpInput.isIgnoreHydrogen());
        } else {
            setupInitialValues(defaultValues.getRank(), defaultValues.getMonopoleConvergence(),
                    defaultValues.getIgnoreHydrogen());
        }
    }

    private void setupComboBox() {
        // TODO improve http://stackoverflow.com/questions/13368572/rendering-a-pojo-with-javafx-2s-combo-box-without-overriding-the-tostring-met
        cmbRank.getItems().clear();
        cmbRank.getItems().add(new RankItem("Point charges", 0));
        cmbRank.getItems().add(new RankItem("Point charges and dipoles", 1));
        cmbRank.getItems().add(new RankItem("Point charges, dipoles and quadrupoles", 2));
        cmbRank.autosize();
    }

    private void setupInitialValues(int rank, double convergence, boolean hydrogen) {
        RankItem itemToSelect = null;
        for (RankItem rankItem : cmbRank.getItems()) {
            if (rankItem.getRankValue() == rank) {
                itemToSelect = rankItem;
                break;
            }
        }
        cmbRank.getSelectionModel().select(itemToSelect);

        txtConvergence.setText(String.valueOf(convergence));
        chkIgnoreHydrogen.setSelected(hydrogen);
    }

    @Override
    protected void fillButtonBar() {
        Button backButton = ButtonFactory.createButtonBarButton("Go back to molecule list",
                new EventHandler<ActionEvent>() {
                    @Override
                    public void handle(ActionEvent actionEvent) {
                        logger.info("Going back to molecule list.");
                        navigateTo(MoleculeListPage.class);
                    }
                });
        addButtonToButtonBar(backButton);

        Button startButton = ButtonFactory.createButtonBarButton("Start fitting", new EventHandler<ActionEvent>() {
            @Override
            public void handle(ActionEvent actionEvent) {
                logger.info("Starting fit.");

                MoleculeQueryService queryService = moleculeRepository.getQueryServiceForAllMolecules();
                File initalCharges = getInitalCharges(queryService);
                if (initalCharges != null) {
                    navigateTo(RunningFitPage.class,
                            createFittingParameter(initalCharges, queryService.getMoleculeIds()));
                }
            }
        });
        addButtonToButtonBar(startButton);
    }

    private File getInitalCharges(MoleculeQueryService queryService) {
        LinkedHashSet<ChargeValue> userCharges = new LinkedHashSet<>();
        LinkedHashSet<AtomTypeId> atomTypesRequiringUserInput = new LinkedHashSet<>();

        List<Molecule> moleculesWithMissingUserCharges = queryService.findMoleculesWithMissingUserCharges();
        atomTypesRequiringUserInput.addAll(getAllAtomTypeIds(moleculesWithMissingUserCharges));

        boolean multipleMoleculesDefined = queryService.getNumberOfMolecules() > 1;
        if (multipleMoleculesDefined) {
            List<AtomTypeId> duplicates = queryService.findUnequalAndDuplicateAtomTypes();
            atomTypesRequiringUserInput.addAll(duplicates);
        }

        if (atomTypesRequiringUserInput.size() > 0) {
            LinkedHashSet<ChargeValue> editedValues = editAtomTypeChargesDialog
                    .editAtomTypes(atomTypesRequiringUserInput);
            if (editedValues == null) {
                // TODO ... no nested return
                return null;
            }
            userCharges.addAll(editedValues);
        }

        // fill up with all other values in order to generate a correct charges file.
        // due to the set, the already edited values will not be replaced.
        LinkedHashSet<ChargeValue> allCharges = queryService.getUserChargesFromMoleculesWithCharges();
        for (ChargeValue charge : allCharges) {
            if (!userCharges.contains(charge)) {
                userCharges.add(charge);
            }
        }

        File initalChargesFile = generateInitialChargesFileFromUserCharges(userCharges);
        return initalChargesFile;
    }

    private LinkedHashSet<AtomTypeId> getAllAtomTypeIds(List<Molecule> molecules) {
        LinkedHashSet<AtomTypeId> allIds = new LinkedHashSet<>();
        for (Molecule molecule : molecules) {
            allIds.addAll(molecule.getAllAtomTypeIds());
        }
        return allIds;
    }

    private File generateInitialChargesFileFromUserCharges(LinkedHashSet<ChargeValue> chargeValues) {
        File chargesFile = new File(sessionDir, "output");
        File generatedFile = new ChargesFileGenerator().generate(chargesFile, "generated_charges.txt",
                chargeValues);
        return generatedFile;
    }

    private File generateInitalValuesFromScript() {
        // TODO generate inital values by script
        OverlayDialog.showError("Not implemented yet.", "This functionality is not yet implemented yet.");
        throw new NotImplementedException();
        //        File chargesFile = new File(sessionDir, "output");
        //        chargesFile = new File(chargesFile, "co2_t_charges.txt");
        //
        //        return chargesFile;
    }

    @Override
    public void initializeData() {
    }

    private FitMtpInput createFittingParameter(File initalChargesFile, List<MoleculeId> moleculesForFit) {
        try {
            double convergence = Double.parseDouble(txtConvergence.getText());
            int rank = cmbRank.getSelectionModel().getSelectedItem().getRankValue();
            boolean ignoreHydrongen = chkIgnoreHydrogen.isSelected();
            int id = fitRepository.getNextFitId();

            return new FitMtpInput(id, convergence, rank, ignoreHydrongen, initalChargesFile, moleculesForFit);
        } catch (Exception e) {
            OverlayDialog.showError("Invalid parameters", "The provided parameters are invalid.");
            throw e;
        }
    }

    private class RankItem {
        private final String title;
        private final int value;

        public RankItem(String title, int value) {
            this.title = title;
            this.value = value;
        }

        private String getTitle() {
            return title;
        }

        private int getRankValue() {
            return value;
        }

        @Override
        public String toString() {
            return title;
        }
    }
}