Trinity Source

I was concerned that the source code that I used for my article about converting FXML to Kotlin would someday become out of date, or removed from GitHub, so I thought I would preserve a copy for permanent reference on this website.

The FXML File

<?xml version="1.0" encoding="UTF-8"?>

<?import javafx.geometry.Insets?>
<?import javafx.scene.control.*?>
<?import javafx.scene.layout.*?>

<AnchorPane fx:id="root" style="-fx-background-color: #00000000;" xmlns="http://javafx.com/javafx" xmlns:fx="http://javafx.com/fxml"
            fx:controller="edu.jhuapl.trinity.javafx.controllers.ManifoldControlController">
    <children>
        <TabPane fx:id="tabPane" tabClosingPolicy="UNAVAILABLE">
            <tabs>
                <Tab closable="false" text="UMAP">
                    <content>
                        <BorderPane fx:id="majorPane" minHeight="200.0" minWidth="400.0">
                            <children>
                            </children>
                            <top>
                            </top>
                            <center>
                                <GridPane hgap="10.0" vgap="5.0" BorderPane.alignment="CENTER">
                                    <columnConstraints>
                                        <ColumnConstraints hgrow="SOMETIMES" maxWidth="288.0" minWidth="10.0" prefWidth="206.0"/>
                                        <ColumnConstraints hgrow="SOMETIMES" maxWidth="380.0" minWidth="10.0" prefWidth="380.0"/>
                                    </columnConstraints>
                                    <rowConstraints>
                                        <RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="NEVER"/>
                                        <RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="NEVER"/>
                                        <RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="NEVER"/>
                                        <RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="NEVER"/>
                                        <RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="NEVER"/>
                                        <RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="NEVER"/>
                                        <RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="NEVER"/>
                                        <RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="NEVER"/>
                                        <RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="NEVER"/>
                                        <RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="NEVER"/>
                                        <RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="NEVER"/>
                                        <RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="NEVER"/>
                                        <RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="NEVER"/>
                                        <RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="NEVER"/>
                                    </rowConstraints>
                                    <children>
                                        <Label text="Number of Components"/>
                                        <Spinner fx:id="numComponentsSpinner" editable="true" prefWidth="100.0" GridPane.rowIndex="1"/>
                                        <Label text="Number of Epochs" GridPane.rowIndex="2"/>
                                        <Spinner fx:id="numEpochsSpinner" editable="true" prefWidth="100.0" GridPane.rowIndex="3"/>
                                        <Label text="Nearest Neighbors" GridPane.rowIndex="4"/>
                                        <Label text="Negative Sample Rate" GridPane.rowIndex="6"/>
                                        <Label text="Local Connectivity" GridPane.rowIndex="8"/>
                                        <Spinner fx:id="nearestNeighborsSpinner" editable="true" prefWidth="100.0" GridPane.rowIndex="5"/>
                                        <Spinner fx:id="negativeSampleRateSpinner" editable="true" prefWidth="100.0" GridPane.rowIndex="7"/>
                                        <Spinner fx:id="localConnectivitySpinner" editable="true" prefWidth="100.0" GridPane.rowIndex="9"/>
                                        <HBox spacing="10.0" GridPane.columnIndex="1" GridPane.rowIndex="10" GridPane.rowSpan="2">
                                            <children>
                                                <VBox alignment="CENTER_LEFT" spacing="10.0">
                                                    <children>
                                                        <Label text="Distance Metric"/>
                                                        <ChoiceBox fx:id="metricChoiceBox" prefWidth="200.0"/>
                                                    </children>
                                                </VBox>
                                                <VBox alignment="CENTER_LEFT" layoutX="10.0" layoutY="10.0" spacing="10.0">
                                                    <children>
                                                        <Label text="Threshold (if applicable)"/>
                                                        <Spinner fx:id="thresholdSpinner" prefWidth="150.0">
                                                            <editable>true</editable>
                                                            <valueFactory>
                                                                <SpinnerValueFactory.DoubleSpinnerValueFactory min="0.01" max="1.0" initialValue="0.1"
                                                                                                               amountToStepBy="0.01"/>
                                                            </valueFactory>
                                                        </Spinner>
                                                    </children>
                                                </VBox>
                                            </children>
                                            <padding>
                                                <Insets top="5.0"/>
                                            </padding>
                                        </HBox>
                                        <Label text="Repulsion Strength" GridPane.columnIndex="1"/>
                                        <Label text="Minimum Distance" GridPane.columnIndex="1" GridPane.rowIndex="2"/>
                                        <Label text="Spread" GridPane.columnIndex="1" GridPane.rowIndex="4"/>
                                        <Label text="Op Mix Ratio" GridPane.columnIndex="1" GridPane.rowIndex="6"/>
                                        <Slider fx:id="repulsionSlider" blockIncrement="0.1" majorTickUnit="0.1" max="2.0" showTickLabels="true"
                                                showTickMarks="true" snapToTicks="true" value="1.0" GridPane.columnIndex="1" GridPane.rowIndex="1"/>
                                        <Slider fx:id="minDistanceSlider" blockIncrement="0.1" majorTickUnit="0.1" max="0.6" showTickLabels="true"
                                                showTickMarks="true" snapToTicks="true" value="0.1" GridPane.columnIndex="1" GridPane.rowIndex="3"/>
                                        <Slider fx:id="spreadSlider" blockIncrement="0.1" majorTickUnit="0.1" max="1.5" min="0.5" showTickLabels="true"
                                                showTickMarks="true" snapToTicks="true" value="1.0" GridPane.columnIndex="1" GridPane.rowIndex="5"/>
                                        <Slider fx:id="opMixSlider" blockIncrement="0.1" majorTickUnit="0.1" max="1.0" showTickLabels="true"
                                                showTickMarks="true" snapToTicks="true" value="0.5" GridPane.columnIndex="1" GridPane.rowIndex="7"/>
                                        <HBox alignment="CENTER" spacing="15.0" GridPane.columnSpan="2147483647" GridPane.halignment="CENTER"
                                              GridPane.rowIndex="12" GridPane.rowSpan="2" GridPane.valignment="CENTER">
                                            <children>
                                                <VBox alignment="CENTER" spacing="10.0">
                                                    <children>
                                                        <Button mnemonicParsing="false" onAction="#loadUmapConfig" prefWidth="200.0" text="Load New Config"/>
                                                        <Button mnemonicParsing="false" onAction="#saveUmapConfig" prefWidth="200.0"
                                                                text="Save Current Config"/>
                                                    </children>
                                                </VBox>
                                                <VBox alignment="CENTER_LEFT" spacing="10.0">
                                                    <children>
                                                        <RadioButton fx:id="useHypersurfaceButton" mnemonicParsing="false" text="Use Hypersurface"/>
                                                        <RadioButton fx:id="useHyperspaceButton" mnemonicParsing="false" selected="true" text="Use Hyperspace"/>
                                                        <CheckBox fx:id="verboseCheckBox" mnemonicParsing="false" selected="true" text="Progress Output"/>
                                                    </children>
                                                    <padding>
                                                        <Insets bottom="5.0" left="5.0" right="5.0" top="5.0"/>
                                                    </padding>
                                                </VBox>
                                                <VBox alignment="CENTER" spacing="10.0">
                                                    <children>
                                                        <Button defaultButton="true" mnemonicParsing="false" onAction="#project" prefWidth="200.0"
                                                                text="Run UMAP"/>
                                                        <Button mnemonicParsing="false" onAction="#exportMatrix" prefWidth="200.0" text="Export TMatrix"/>
                                                        <Button mnemonicParsing="false" onAction="#saveProjections" prefWidth="200.0"
                                                                text="Export Projections"/>
                                                    </children>
                                                </VBox>
                                            </children>
                                            <padding>
                                                <Insets bottom="2.0" left="2.0" right="2.0" top="2.0"/>
                                            </padding>
                                        </HBox>
                                        <Label text="Target Weight" GridPane.columnIndex="1" GridPane.rowIndex="8"/>
                                        <Slider fx:id="targetWeightSlider" blockIncrement="0.1" majorTickUnit="0.1" max="1.0" showTickLabels="true"
                                                showTickMarks="true" snapToTicks="true" value="0.5" GridPane.columnIndex="1" GridPane.rowIndex="9"/>
                                    </children>
                                    <padding>
                                        <Insets bottom="25.0" left="25.0" right="25.0" top="25.0"/>
                                    </padding>
                                </GridPane>
                            </center>
                        </BorderPane>
                    </content>
                </Tab>
                <Tab closable="false" text="PCA">
                    <content>
                        <BorderPane fx:id="majorPane" minHeight="200.0" minWidth="400.0">
                            <children>
                            </children>
                            <top>
                            </top>
                            <center>
                                <GridPane hgap="10.0" vgap="5.0" BorderPane.alignment="CENTER">
                                    <columnConstraints>
                                        <ColumnConstraints hgrow="SOMETIMES" maxWidth="288.0" minWidth="10.0" prefWidth="200.0"/>
                                        <ColumnConstraints hgrow="SOMETIMES" maxWidth="380.0" minWidth="10.0" prefWidth="200.0"/>
                                    </columnConstraints>
                                    <rowConstraints>
                                        <RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="NEVER"/>
                                        <RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="NEVER"/>
                                        <RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="NEVER"/>
                                        <RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="NEVER"/>
                                        <RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="NEVER"/>
                                        <RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="NEVER"/>
                                        <RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="NEVER"/>
                                        <RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="NEVER"/>
                                        <RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="NEVER"/>
                                        <RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="NEVER"/>
                                    </rowConstraints>
                                    <children>
                                        <Label text="Number of Components"/>
                                        <Spinner fx:id="numPcaComponentsSpinner" editable="true" prefWidth="100.0" GridPane.rowIndex="1"/>
                                        <HBox spacing="20.0" GridPane.rowIndex="3" GridPane.rowSpan="2">
                                            <children>
                                                <VBox spacing="15.0">
                                                    <children>
                                                        <Label text="Fit Start Index"/>
                                                        <Spinner fx:id="fitStartIndexSpinner" editable="true" prefWidth="100.0"/>
                                                    </children>
                                                </VBox>
                                                <VBox spacing="15.0">
                                                    <children>
                                                        <Label text="Fit End Index"/>
                                                        <Spinner fx:id="fitEndIndexSpinner" editable="true" prefWidth="100.0"/>
                                                    </children>
                                                </VBox>
                                            </children>
                                        </HBox>
                                        <RadioButton fx:id="pcaRadioButton" mnemonicParsing="false" selected="true" text="PCA (EigenValue)"
                                                     GridPane.columnIndex="1" GridPane.rowIndex="1"/>
                                        <Label text="Component Analysis Type" GridPane.columnIndex="1"/>
                                        <RadioButton fx:id="svdRadioButton" mnemonicParsing="false" text="Singular Value Decomposition" GridPane.columnIndex="1"
                                                     GridPane.rowIndex="2"/>
                                        <RadioButton fx:id="pcaUseHypersurfaceButton" mnemonicParsing="false" text="Use Hypersurface" GridPane.columnIndex="1"
                                                     GridPane.rowIndex="4"/>
                                        <RadioButton fx:id="pcaUseHyperspaceButton" mnemonicParsing="false" selected="true" text="Use Hyperspace"
                                                     GridPane.columnIndex="1" GridPane.rowIndex="5"/>
                                        <Label text="Output Scaling Factor" GridPane.rowIndex="5"/>
                                        <Spinner fx:id="pcaScalingSpinner" editable="true" prefWidth="100.0" GridPane.rowIndex="6"/>
                                        <HBox alignment="CENTER" spacing="10.0" GridPane.columnSpan="2147483647" GridPane.rowIndex="8">
                                            <children>
                                                <Button defaultButton="true" mnemonicParsing="false" onAction="#runPCA" prefWidth="175.0" text="Project Data"/>
                                                <Button mnemonicParsing="false" onAction="#saveProjections" prefWidth="175.0" text="Export Projections"/>
                                            </children>
                                            <padding>
                                                <Insets bottom="5.0" left="5.0" right="5.0" top="5.0"/>
                                            </padding>
                                        </HBox>
                                        <Label text="Input Data Source" GridPane.columnIndex="1" GridPane.rowIndex="3"/>
                                        <CheckBox fx:id="rangedFittingCheckBox" mnemonicParsing="false" text="Enabled Ranged Fitting (Experimental)"
                                                  GridPane.rowIndex="2"/>
                                    </children>
                                    <padding>
                                        <Insets bottom="15.0" left="15.0" right="15.0" top="15.0"/>
                                    </padding>
                                </GridPane>
                            </center>
                        </BorderPane>
                    </content>
                </Tab>
                <Tab closable="false" text="Distances">
                    <content>
                        <BorderPane fx:id="majorPane" minHeight="200.0" minWidth="400.0">
                            <children>
                            </children>
                            <top>
                            </top>
                            <center>
                                <GridPane hgap="10.0" vgap="5.0" BorderPane.alignment="CENTER">
                                    <columnConstraints>
                                        <ColumnConstraints hgrow="SOMETIMES" maxWidth="288.0" minWidth="10.0" prefWidth="206.0"/>
                                        <ColumnConstraints fillWidth="false" hgrow="NEVER"/>
                                        <ColumnConstraints hgrow="SOMETIMES" maxWidth="380.0" minWidth="10.0" prefWidth="380.0"/>
                                    </columnConstraints>
                                    <rowConstraints>
                                        <RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="NEVER"/>
                                        <RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="NEVER"/>
                                        <RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="NEVER"/>
                                        <RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="NEVER"/>
                                        <RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="NEVER"/>
                                        <RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="NEVER"/>
                                        <RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="NEVER"/>
                                        <RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="NEVER"/>
                                        <RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="NEVER"/>
                                        <RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="NEVER"/>
                                        <RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="NEVER"/>
                                    </rowConstraints>
                                    <children>
                                        <Label text="Connector Thickness" GridPane.rowIndex="5"/>
                                        <VBox alignment="CENTER_LEFT" spacing="5.0" GridPane.rowIndex="7" GridPane.rowSpan="2">
                                            <children>
                                                <Label text="Connector Color"/>
                                                <ColorPicker fx:id="connectorColorPicker" editable="true" minHeight="40.0" prefWidth="200.0"
                                                             promptText="Change the color of the 3D connector"/>
                                            </children>
                                            <padding>
                                                <Insets bottom="5.0" left="5.0" right="5.0" top="5.0"/>
                                            </padding>
                                        </VBox>
                                        <Spinner fx:id="connectorThicknessSpinner" editable="true" prefWidth="100.0" GridPane.rowIndex="6"/>
                                        <HBox alignment="CENTER" spacing="20.0" GridPane.columnIndex="2">
                                            <children>
                                                <Label text="Collected Distances"/>
                                                <Button mnemonicParsing="false" onAction="#clearAllDistances" prefWidth="150.0" text="Clear All"/>
                                            </children>
                                        </HBox>
                                        <VBox spacing="5.0" GridPane.rowSpan="2">
                                            <children>
                                                <Label text="Distance Metric"/>
                                                <TextField fx:id="distanceMetricTextField" minHeight="40.0" promptText="Select Distance From ListView"/>
                                            </children>
                                            <padding>
                                                <Insets bottom="5.0" left="5.0" right="5.0" top="5.0"/>
                                            </padding>
                                        </VBox>
                                        <ScrollPane fitToHeight="true" fitToWidth="true" pannable="true" GridPane.columnIndex="2" GridPane.rowIndex="1"
                                                    GridPane.rowSpan="2147483647">
                                            <content>
                                                <ListView fx:id="distancesListView" prefHeight="200.0" prefWidth="200.0">
                                                    <padding>
                                                        <Insets bottom="5.0" left="5.0" right="5.0" top="5.0"/>
                                                    </padding>
                                                </ListView>
                                            </content>
                                        </ScrollPane>
                                        <Separator orientation="VERTICAL" prefHeight="200.0" GridPane.columnIndex="1" GridPane.rowSpan="2147483647"/>
                                        <RadioButton fx:id="pointToGroupRadioButton" disable="true" mnemonicParsing="false" text="Point to Group"
                                                     GridPane.rowIndex="3"/>
                                        <RadioButton fx:id="pointToPointRadioButton" mnemonicParsing="false" selected="true" text="Point to Point"
                                                     GridPane.rowIndex="2"/>
                                    </children>
                                    <padding>
                                        <Insets bottom="10.0" left="10.0" right="10.0" top="10.0"/>
                                    </padding>
                                </GridPane>
                            </center>
                        </BorderPane>
                    </content>
                </Tab>
                <Tab closable="false" text="Hull Geometry">
                    <content>
                        <BorderPane>
                            <center>
                                <VBox spacing="5.0" BorderPane.alignment="CENTER">
                                    <children>
                                        <HBox alignment="CENTER_LEFT" spacing="20.0">
                                            <children>
                                                <Label text="Generated Manifolds"/>
                                            </children>
                                        </HBox>
                                        <HBox alignment="CENTER" layoutX="15.0" layoutY="15.0" spacing="20.0">
                                            <children>
                                                <Button mnemonicParsing="false" onAction="#clearAll" prefWidth="125.0" text="Clear All"/>
                                                <Button layoutX="100.0" layoutY="10.0" mnemonicParsing="false" onAction="#exportAll" prefWidth="125.0"
                                                        text="Export All"/>
                                            </children>
                                        </HBox>
                                        <ScrollPane fitToHeight="true" fitToWidth="true" pannable="true">
                                            <content>
                                                <ListView fx:id="manifoldsListView">
                                                    <padding>
                                                        <Insets bottom="5.0" left="5.0" right="5.0" top="5.0"/>
                                                    </padding>
                                                </ListView>
                                            </content>
                                        </ScrollPane>
                                    </children>
                                    <padding>
                                        <Insets bottom="5.0" left="5.0" right="5.0" top="5.0"/>
                                    </padding>
                                </VBox>
                            </center>
                            <top>
                                <HBox alignment="CENTER" BorderPane.alignment="CENTER">
                                    <children>
                                        <GridPane maxHeight="1.7976931348623157E308" maxWidth="1.7976931348623157E308">
                                            <columnConstraints>
                                                <ColumnConstraints halignment="CENTER" hgrow="ALWAYS" maxWidth="-Infinity" minWidth="10.0" prefWidth="150.0"/>
                                                <ColumnConstraints halignment="CENTER" hgrow="ALWAYS" maxWidth="216.0" minWidth="10.0" prefWidth="214.0"/>
                                                <ColumnConstraints halignment="CENTER" hgrow="ALWAYS" maxWidth="145.0" minWidth="10.0" prefWidth="118.0"/>
                                                <ColumnConstraints halignment="CENTER" hgrow="ALWAYS" maxWidth="145.0" minWidth="10.0" prefWidth="118.0"/>
                                            </columnConstraints>
                                            <rowConstraints>
                                                <RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="ALWAYS"/>
                                                <RowConstraints minHeight="10.0" prefHeight="40.0" vgrow="ALWAYS"/>
                                                <RowConstraints minHeight="10.0" prefHeight="40.0" vgrow="ALWAYS"/>
                                                <RowConstraints minHeight="10.0" vgrow="ALWAYS"/>
                                            </rowConstraints>
                                            <children>
                                                <Label layoutX="15.0" layoutY="62.0" text="Point Set"/>
                                                <HBox alignment="CENTER" GridPane.columnIndex="1" GridPane.valignment="CENTER">
                                                    <children>
                                                        <RadioButton fx:id="useVisibleRadioButton" mnemonicParsing="false" prefWidth="75.0" selected="true"
                                                                     text="Visible"/>
                                                        <RadioButton fx:id="useAllRadioButton" mnemonicParsing="false" prefWidth="75.0" text="All"/>
                                                    </children>
                                                </HBox>
                                                <Label text="Distance Tolerance" textAlignment="CENTER" GridPane.rowIndex="1"/>
                                                <HBox alignment="CENTER" spacing="10.0" GridPane.columnIndex="1" GridPane.rowIndex="1">
                                                    <children>
                                                        <CheckBox fx:id="automaticCheckBox" mnemonicParsing="false" selected="true" text="Auto"/>
                                                        <Spinner fx:id="manualSpinner" editable="true" prefWidth="75.0"/>
                                                    </children>
                                                </HBox>
                                                <Label text="Find by Label" GridPane.rowIndex="2"/>
                                                <ChoiceBox fx:id="labelChoiceBox" maxWidth="200.0" prefWidth="150.0" GridPane.columnIndex="1"
                                                           GridPane.rowIndex="2"/>
                                                <Separator prefWidth="200.0" GridPane.columnSpan="2147483647" GridPane.rowIndex="3"/>
                                                <VBox alignment="CENTER" spacing="20.0" GridPane.columnIndex="2" GridPane.columnSpan="2"
                                                      GridPane.halignment="CENTER" GridPane.rowSpan="3" GridPane.valignment="CENTER">
                                                    <children>
                                                        <Button mnemonicParsing="false" onAction="#generate" prefWidth="175.0" text="Generate"/>
                                                        <Button mnemonicParsing="false" onAction="#clusterBuilder" prefWidth="175.0" text="Cluster Tools"/>
                                                    </children>
                                                    <padding>
                                                        <Insets bottom="10.0" left="10.0" right="10.0" top="10.0"/>
                                                    </padding>
                                                </VBox>
                                            </children>
                                        </GridPane>
                                    </children>
                                </HBox>
                            </top>
                            <left>
                                <VBox spacing="10.0" BorderPane.alignment="CENTER">
                                    <children>
                                        <Label text="Selected Manifold Properties"/>
                                        <TitledPane collapsible="false" text="Material" VBox.vgrow="ALWAYS">
                                            <content>
                                                <VBox spacing="5.0">
                                                    <children>
                                                        <HBox alignment="CENTER_LEFT" spacing="10.0">
                                                            <children>
                                                                <Label prefWidth="125.0" text="Diffuse Color"/>
                                                                <ColorPicker fx:id="manifoldDiffuseColorPicker" editable="true" prefHeight="50.0"
                                                                             prefWidth="150.0"/>
                                                            </children>
                                                        </HBox>
                                                        <HBox alignment="CENTER_LEFT" spacing="10.0">
                                                            <children>
                                                                <Label prefWidth="125.0" text="Wire Mesh Color"/>
                                                                <ColorPicker fx:id="manifoldWireMeshColorPicker" editable="true" prefHeight="50.0"
                                                                             prefWidth="150.0"/>
                                                            </children>
                                                        </HBox>
                                                        <HBox alignment="CENTER_LEFT" spacing="10.0">
                                                            <children>
                                                                <Label prefWidth="125.0" text="Specular Color"/>
                                                                <ColorPicker fx:id="manifoldSpecularColorPicker" editable="true" prefHeight="50.0"
                                                                             prefWidth="150.0"/>
                                                            </children>
                                                        </HBox>
                                                    </children>
                                                </VBox>
                                            </content>
                                        </TitledPane>
                                        <TitledPane collapsible="false" layoutX="10.0" layoutY="396.0" text="MeshView" VBox.vgrow="ALWAYS">
                                            <content>
                                                <GridPane>
                                                    <columnConstraints>
                                                        <ColumnConstraints hgrow="SOMETIMES" maxWidth="-Infinity" minWidth="10.0" prefWidth="300.0"/>
                                                    </columnConstraints>
                                                    <rowConstraints>
                                                        <RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES"/>
                                                        <RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES"/>
                                                        <RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES"/>
                                                    </rowConstraints>
                                                    <children>
                                                        <HBox alignment="CENTER_LEFT" spacing="15.0" GridPane.halignment="CENTER" GridPane.valignment="CENTER">
                                                            <children>
                                                                <Label prefWidth="75.0" text="Cull Face"/>
                                                                <RadioButton fx:id="frontCullFaceRadioButton" mnemonicParsing="false" prefWidth="70.0"
                                                                             selected="true" text="Front"/>
                                                                <RadioButton fx:id="backCullFaceRadioButton" mnemonicParsing="false" text="Back"/>
                                                                <RadioButton fx:id="noneCullFaceRadioButton" mnemonicParsing="false" text="None"/>
                                                            </children>
                                                        </HBox>
                                                        <HBox alignment="CENTER_LEFT" spacing="15.0" GridPane.halignment="CENTER" GridPane.rowIndex="1"
                                                              GridPane.valignment="CENTER">
                                                            <children>
                                                                <Label prefWidth="75.0" text="Draw Mode"/>
                                                                <RadioButton fx:id="fillDrawModeRadioButton" mnemonicParsing="false" prefWidth="70.0"
                                                                             selected="true" text="Fill"/>
                                                                <RadioButton fx:id="linesDrawModeRadioButton" mnemonicParsing="false" text="Lines"/>
                                                            </children>
                                                        </HBox>
                                                        <HBox alignment="CENTER" spacing="10.0" GridPane.rowIndex="2">
                                                            <children>
                                                                <CheckBox fx:id="showWireframeCheckBox" mnemonicParsing="false" selected="true"
                                                                          text="Show Wire Frame"/>
                                                                <CheckBox fx:id="showControlPointsCheckBox" mnemonicParsing="false" selected="true"
                                                                          text="Show Control Points"/>
                                                            </children>
                                                        </HBox>
                                                    </children>
                                                </GridPane>
                                            </content>
                                        </TitledPane>
                                    </children>
                                    <padding>
                                        <Insets bottom="5.0" left="5.0" right="5.0" top="5.0"/>
                                    </padding>
                                </VBox>
                            </left>
                        </BorderPane>
                    </content>
                </Tab>
            </tabs>
        </TabPane>

    </children>
</AnchorPane>

The FXML Controller File

/* Copyright (C) 2021 - 2023 The Johns Hopkins University Applied Physics Laboratory LLC */

/**
 * FXML Controller class
 *
 * @author Sean Phillips
 */
public class ManifoldControlController implements Initializable {
    private static final Logger LOG = LoggerFactory.getLogger(ManifoldControlController.class);

    @FXML
    private Node root;

    //Geometry Tab
    @FXML
    private ListView<ManifoldListItem> manifoldsListView;
    private Manifold3D activeManifold3D = null;
    @FXML
    private RadioButton useVisibleRadioButton;
    @FXML
    private RadioButton useAllRadioButton;
    ToggleGroup pointsToggleGroup;
    @FXML
    private ChoiceBox labelChoiceBox;
    @FXML
    private CheckBox automaticCheckBox;
    @FXML
    private Spinner manualSpinner;
    @FXML
    private ColorPicker manifoldDiffuseColorPicker;
    @FXML
    private ColorPicker manifoldSpecularColorPicker;
    @FXML
    private ColorPicker manifoldWireMeshColorPicker;
    @FXML
    private RadioButton frontCullFaceRadioButton;
    @FXML
    private RadioButton backCullFaceRadioButton;
    @FXML
    private RadioButton noneCullFaceRadioButton;
    ToggleGroup cullfaceToggleGroup;
    @FXML
    private RadioButton fillDrawModeRadioButton;
    @FXML
    private RadioButton linesDrawModeRadioButton;
    ToggleGroup drawModeToggleGroup;
    @FXML
    private CheckBox showWireframeCheckBox;
    @FXML
    private CheckBox showControlPointsCheckBox;

    //PCA Tab
    @FXML
    private RadioButton pcaRadioButton;
    @FXML
    private RadioButton svdRadioButton;
    ToggleGroup componentAnalysisToggleGroup;
    @FXML
    private Spinner numPcaComponentsSpinner;
    @FXML
    private Spinner fitStartIndexSpinner;
    @FXML
    private Spinner fitEndIndexSpinner;
    @FXML
    private CheckBox rangedFittingCheckBox;

    @FXML
    private Spinner pcaScalingSpinner;

    @FXML
    private RadioButton pcaUseHyperspaceButton;
    @FXML
    private RadioButton pcaUseHypersurfaceButton;
    ToggleGroup pcahyperSourceGroup;

    //UMAP tab
    @FXML
    private Slider targetWeightSlider;
    @FXML
    private Slider repulsionSlider;
    @FXML
    private Slider minDistanceSlider;
    @FXML
    private Slider spreadSlider;
    @FXML
    private Slider opMixSlider;
    @FXML
    private Spinner numComponentsSpinner;
    @FXML
    private Spinner numEpochsSpinner;
    @FXML
    private Spinner nearestNeighborsSpinner;
    @FXML
    private Spinner negativeSampleRateSpinner;
    @FXML
    private Spinner localConnectivitySpinner;
    @FXML
    private Spinner<Double> thresholdSpinner;
    @FXML
    private ChoiceBox metricChoiceBox;
    @FXML
    private CheckBox verboseCheckBox;
    @FXML
    private RadioButton useHyperspaceButton;
    @FXML
    private RadioButton useHypersurfaceButton;
    ToggleGroup hyperSourceGroup;


    //Distances Tab
    @FXML
    private ListView<DistanceListItem> distancesListView;
    @FXML
    private RadioButton pointToPointRadioButton;
    @FXML
    private RadioButton pointToGroupRadioButton;
    ToggleGroup pointModeToggleGroup;
    @FXML
    private TextField distanceMetricTextField;
    @FXML
    private ColorPicker connectorColorPicker;
    @FXML
    private Spinner connectorThicknessSpinner;

    Scene scene;
    private final String ALL = "ALL";
    boolean reactive = true;
    Umap latestUmapObject = null;
    File latestDir = new File(".");

    /**
     * Initializes the controller class.
     *
     * @param url
     * @param rb
     */
    @Override
    public void initialize(URL url, ResourceBundle rb) {
        scene = App.getAppScene();
        setupPcaControls();
        setupHullControls();
        setupUmapControls();
        setupDistanceControls();
        if (null != root) {
            root.addEventHandler(DragEvent.DRAG_OVER, event -> {
                event.acceptTransferModes(TransferMode.COPY);
            });
            root.addEventHandler(DragEvent.DRAG_DROPPED, e -> {
                Dragboard db = e.getDragboard();
                if (db.hasFiles()) {
                    File file = db.getFiles().get(0);
                    try {

                        if (UmapConfig.isUmapConfig(Files.readString(file.toPath()))) {
                            ObjectMapper mapper = new ObjectMapper();
                            UmapConfig uc = mapper.readValue(file, UmapConfig.class);
                            setUmapConfig(uc);
                            sendUmapConfig();
                        }
                    } catch (IOException ex) {
                        LOG.error(null, ex);
                    }
                }
            });
            scene.addEventHandler(ManifoldEvent.NEW_UMAP_CONFIG, event -> {
                UmapConfig config = (UmapConfig) event.object1;
                setUmapConfig(config);
            });
        }
    }

    private void setupDistanceControls() {
        distanceMetricTextField.setText("Select Distance Object");
        distanceMetricTextField.setEditable(false);
        connectorThicknessSpinner.setValueFactory(
            new SpinnerValueFactory.IntegerSpinnerValueFactory(1, 50, 5, 1));
        connectorThicknessSpinner.setEditable(true);
        connectorThicknessSpinner.valueProperty().addListener(e -> {
            DistanceListItem item = distancesListView.getSelectionModel().getSelectedItem();
            if (null != item) {
                Integer width = (Integer) connectorThicknessSpinner.getValue();
                item.getDistance().setWidth(width);
                scene.getRoot().fireEvent(
                    new ManifoldEvent(ManifoldEvent.DISTANCE_CONNECTOR_WIDTH, item.getDistance()));
            }
        });
        connectorThicknessSpinner.setInitialDelay(Duration.millis(500));
        connectorThicknessSpinner.setRepeatDelay(Duration.millis(500));

        connectorColorPicker.valueProperty().addListener(cl -> {
            DistanceListItem item = distancesListView.getSelectionModel().getSelectedItem();
            if (null != item) {
                item.getDistance().setColor(connectorColorPicker.getValue());
                scene.getRoot().fireEvent(
                    new ManifoldEvent(ManifoldEvent.DISTANCE_CONNECTOR_COLOR, item.getDistance()));
            }
        });
        //Get a reference to any Distances already collected
        List<DistanceListItem> existingItems = new ArrayList<>();
        for (Distance d : Distance.getDistances()) {
            DistanceListItem item = new DistanceListItem(d);
            existingItems.add(item);
        }
        //add them all in one shot
        distancesListView.getItems().addAll(existingItems);
        ImageView iv = ResourceUtils.loadIcon("metric", 200);
        VBox placeholder = new VBox(10, iv, new Label("No Distances Acquired"));
        placeholder.setAlignment(Pos.CENTER);
        distancesListView.setPlaceholder(placeholder);

        //Bind disable properties so that controls only active when item is selected
        distanceMetricTextField.disableProperty().bind(
            distancesListView.getSelectionModel().selectedIndexProperty().lessThan(0));
        connectorThicknessSpinner.disableProperty().bind(
            distancesListView.getSelectionModel().selectedIndexProperty().lessThan(0));
        connectorColorPicker.disableProperty().bind(
            distancesListView.getSelectionModel().selectedIndexProperty().lessThan(0));

        pointModeToggleGroup = new ToggleGroup();
        pointToPointRadioButton.setToggleGroup(pointModeToggleGroup);
        pointToGroupRadioButton.setToggleGroup(pointModeToggleGroup);
        scene.addEventHandler(ManifoldEvent.DISTANCE_CONNECTOR_SELECTED, e -> {
            Distance distance = (Distance) e.object1;
            for (DistanceListItem item : distancesListView.getItems()) {
                if (item.getDistance() == distance) {
                    distancesListView.getSelectionModel().select(item);
                    distanceMetricTextField.setText(distance.getMetric());
                    connectorColorPicker.setValue(distance.getColor());
                    connectorThicknessSpinner.getValueFactory().setValue(distance.getWidth());
                    return; //break out early
                }
            }
            //if we get here its because that Distance object wasn't in the list
            scene.getRoot().fireEvent(new CommandTerminalEvent(
                "Distance object not found!", new Font("Consolas", 20), Color.YELLOW));
        });
        scene.addEventHandler(ManifoldEvent.DISTANCE_OBJECT_SELECTED, e -> {
            Distance distance = (Distance) e.object1;
            distanceMetricTextField.setText(distance.getMetric());
            connectorColorPicker.setValue(distance.getColor());
            connectorThicknessSpinner.getValueFactory().setValue(distance.getWidth());
        });
        scene.addEventHandler(ManifoldEvent.CREATE_NEW_DISTANCE, e -> {
            Distance distance = (Distance) e.object1;
            DistanceListItem distanceListItem = new DistanceListItem(distance);
            Distance.addDistance(distance);
            distancesListView.getItems().add(distanceListItem);
        });
    }

    private void getCurrentLabels() {
        labelChoiceBox.getItems().clear();
        labelChoiceBox.getItems().add(ALL);
        labelChoiceBox.getItems().addAll(
            FactorLabel.getFactorLabels().stream()
                .map(f -> f.getLabel()).sorted().toList());
    }

    private void setupPcaControls() {
        numPcaComponentsSpinner.setValueFactory(
            new SpinnerValueFactory.IntegerSpinnerValueFactory(2, 100, 3, 1));
        fitStartIndexSpinner.setValueFactory(
            new SpinnerValueFactory.IntegerSpinnerValueFactory(0, 500, 0, 5));
        fitEndIndexSpinner.setValueFactory(
            new SpinnerValueFactory.IntegerSpinnerValueFactory(5, 2000, 50, 5));
        //"min","max","initialValue","amountToStepBy"
        fitStartIndexSpinner.disableProperty().bind(rangedFittingCheckBox.selectedProperty().not());
        fitEndIndexSpinner.disableProperty().bind(rangedFittingCheckBox.selectedProperty().not());

        pcaScalingSpinner.setValueFactory(
            new SpinnerValueFactory.DoubleSpinnerValueFactory(1, 1000, 100, 10));

        componentAnalysisToggleGroup = new ToggleGroup();
        pcaRadioButton.setToggleGroup(componentAnalysisToggleGroup);
        svdRadioButton.setToggleGroup(componentAnalysisToggleGroup);

        pcahyperSourceGroup = new ToggleGroup();
        pcaUseHyperspaceButton.setToggleGroup(pcahyperSourceGroup);
        pcaUseHypersurfaceButton.setToggleGroup(pcahyperSourceGroup);
    }

    private void setupUmapControls() {
        hyperSourceGroup = new ToggleGroup();
        useHyperspaceButton.setToggleGroup(hyperSourceGroup);
        useHypersurfaceButton.setToggleGroup(hyperSourceGroup);

        metricChoiceBox.getItems().addAll(Metric.getMetricNames());
        metricChoiceBox.getSelectionModel().selectFirst();

        numComponentsSpinner.setValueFactory(
            new SpinnerValueFactory.IntegerSpinnerValueFactory(2, 50, 3, 1));
        numEpochsSpinner.setValueFactory(
            new SpinnerValueFactory.IntegerSpinnerValueFactory(25, 500, 200, 25));
        nearestNeighborsSpinner.setValueFactory(
            new SpinnerValueFactory.IntegerSpinnerValueFactory(5, 500, 15, 5));
        negativeSampleRateSpinner.setValueFactory(
            new SpinnerValueFactory.IntegerSpinnerValueFactory(1, 250, 5, 1));
        localConnectivitySpinner.setValueFactory(
            new SpinnerValueFactory.IntegerSpinnerValueFactory(1, 250, 1, 1));
//        thresholdSpinner.setValueFactory(
//            new SpinnerValueFactory.DoubleSpinnerValueFactory(0.001, 1.0, 0.001, 0.001));
//        thresholdSpinner.setEditable(true);

        hyperSourceGroup = new ToggleGroup();
        useHyperspaceButton.setToggleGroup(hyperSourceGroup);
        useHypersurfaceButton.setToggleGroup(hyperSourceGroup);
    }

    private void setupHullControls() {
        //Get a reference to any Distances already collected
        List<ManifoldListItem> existingItems = new ArrayList<>();
        for (Manifold m : Manifold.getManifolds()) {
            ManifoldListItem item = new ManifoldListItem(m);
            existingItems.add(item);
        }
        //add them all in one shot
        manifoldsListView.getItems().addAll(existingItems);
        ImageView iv = ResourceUtils.loadIcon("manifold", 200);
        VBox placeholder = new VBox(10, iv, new Label("No Manifolds Acquired"));
        placeholder.setAlignment(Pos.CENTER);
        manifoldsListView.setPlaceholder(placeholder);

        getCurrentLabels();
        labelChoiceBox.getSelectionModel().selectFirst();
        labelChoiceBox.setOnShown(e -> getCurrentLabels());
        manualSpinner.setValueFactory(
            new SpinnerValueFactory.DoubleSpinnerValueFactory(0.1, 1, 0.5, 0.1));
        manualSpinner.setEditable(true);
        //whenever the spinner value is changed...
        manualSpinner.valueProperty().addListener(e -> {
            scene.getRoot().fireEvent(
                new ManifoldEvent(ManifoldEvent.SET_DISTANCE_TOLERANCE,
                    (Double) manualSpinner.getValue()));
        });
        manualSpinner.disableProperty().bind(automaticCheckBox.selectedProperty());

        manifoldDiffuseColorPicker.setValue(Color.CYAN);
        manifoldDiffuseColorPicker.valueProperty().addListener(cl -> {
            if (!reactive) return;
            ManifoldListItem item = manifoldsListView.getSelectionModel().getSelectedItem();
            if (null != item) {
                Manifold m = item.getManifold();
                if (null != m) {
                    m.setColor(manifoldDiffuseColorPicker.getValue());
                    scene.getRoot().fireEvent(new ManifoldEvent(
                        ManifoldEvent.MANIFOLD_DIFFUSE_COLOR,
                        manifoldDiffuseColorPicker.getValue(), m));
                }
            }
        });
        manifoldSpecularColorPicker.setValue(Color.RED);
        manifoldSpecularColorPicker.valueProperty().addListener(cl -> {
            if (!reactive) return;
            ManifoldListItem item = manifoldsListView.getSelectionModel().getSelectedItem();
            if (null != item) {
                Manifold m = item.getManifold();
                if (null != m)
                    scene.getRoot().fireEvent(new ManifoldEvent(
                        ManifoldEvent.MANIFOLD_SPECULAR_COLOR,
                        manifoldSpecularColorPicker.getValue(), m));
            }
        });
        manifoldWireMeshColorPicker.setValue(Color.BLUE);
        manifoldWireMeshColorPicker.valueProperty().addListener(cl -> {
            if (!reactive) return;
            ManifoldListItem item = manifoldsListView.getSelectionModel().getSelectedItem();
            if (null != item) {
                Manifold m = item.getManifold();
                if (null != m)
                    scene.getRoot().fireEvent(new ManifoldEvent(
                        ManifoldEvent.MANIFOLD_WIREFRAME_COLOR,
                        manifoldWireMeshColorPicker.getValue(), m));
            }
        });

        pointsToggleGroup = new ToggleGroup();
        useVisibleRadioButton.setToggleGroup(pointsToggleGroup);
        useAllRadioButton.setToggleGroup(pointsToggleGroup);
        pointsToggleGroup.selectedToggleProperty().addListener(cl -> {
            if (useVisibleRadioButton.isSelected())
                scene.getRoot().fireEvent(new ManifoldEvent(
                    ManifoldEvent.USE_VISIBLE_POINTS, true));
            else
                scene.getRoot().fireEvent(new ManifoldEvent(
                    ManifoldEvent.USE_ALL_POINTS, true));
        });

        cullfaceToggleGroup = new ToggleGroup();
        frontCullFaceRadioButton.setToggleGroup(cullfaceToggleGroup);
        backCullFaceRadioButton.setToggleGroup(cullfaceToggleGroup);
        noneCullFaceRadioButton.setToggleGroup(cullfaceToggleGroup);
        cullfaceToggleGroup.selectedToggleProperty().addListener(cl -> {
            Manifold m = manifoldsListView.getSelectionModel().getSelectedItem().getManifold();
            if (null != m)
                if (frontCullFaceRadioButton.isSelected())
                    scene.getRoot().fireEvent(new ManifoldEvent(
                        ManifoldEvent.MANIFOLD_FRONT_CULLFACE, true, m));
                else if (backCullFaceRadioButton.isSelected())
                    scene.getRoot().fireEvent(new ManifoldEvent(
                        ManifoldEvent.MANIFOLD_BACK_CULLFACE, true, m));
                else
                    scene.getRoot().fireEvent(new ManifoldEvent(
                        ManifoldEvent.MANIFOLD_NONE_CULLFACE, true, m));
        });
        drawModeToggleGroup = new ToggleGroup();
        fillDrawModeRadioButton.setToggleGroup(drawModeToggleGroup);
        linesDrawModeRadioButton.setToggleGroup(drawModeToggleGroup);
        drawModeToggleGroup.selectedToggleProperty().addListener(cl -> {
            Manifold m = manifoldsListView.getSelectionModel().getSelectedItem().getManifold();
            if (null != m)
                if (fillDrawModeRadioButton.isSelected())
                    scene.getRoot().fireEvent(new ManifoldEvent(
                        ManifoldEvent.MANIFOLD_FILL_DRAWMODE, true, m));
                else
                    scene.getRoot().fireEvent(new ManifoldEvent(
                        ManifoldEvent.MANIFOLD_LINE_DRAWMODE, true, m));
        });

        showWireframeCheckBox.selectedProperty().addListener(cl -> {
            Manifold m = manifoldsListView.getSelectionModel().getSelectedItem().getManifold();
            if (null != m)
                scene.getRoot().fireEvent(new ManifoldEvent(
                    ManifoldEvent.MANIFOLD_SHOW_WIREFRAME,
                    showWireframeCheckBox.isSelected(), m));
        });
        showControlPointsCheckBox.selectedProperty().addListener(cl -> {
            Manifold m = manifoldsListView.getSelectionModel().getSelectedItem().getManifold();
            if (null != m)
                scene.getRoot().fireEvent(new ManifoldEvent(
                    ManifoldEvent.MANIFOLD_SHOW_CONTROL,
                    showControlPointsCheckBox.isSelected(), m));
        });

        scene.addEventHandler(ManifoldEvent.MANIFOLD_3D_SELECTED, e -> {
            Manifold manifold = (Manifold) e.object1;
            for (ManifoldListItem item : manifoldsListView.getItems()) {
                if (item.getManifold() == manifold) {
                    manifoldsListView.getSelectionModel().select(item);
                    Manifold3D manifold3D = Manifold.globalManifoldToManifold3DMap.get(manifold);
                    updateActiveManifold3D(manifold3D);
                    return; //break out early
                }
            }
            //if we get here its because that Distance object wasn't in the list
            scene.getRoot().fireEvent(new CommandTerminalEvent(
                "Manifold object not found!", new Font("Consolas", 20), Color.YELLOW));
        });
        scene.addEventHandler(ManifoldEvent.MANIFOLD_OBJECT_SELECTED, e -> {
            Manifold manifold = (Manifold) e.object1;
            Manifold3D manifold3D = Manifold.globalManifoldToManifold3DMap.get(manifold);
            updateActiveManifold3D(manifold3D);
        });
        scene.addEventHandler(ManifoldEvent.MANIFOLD3D_OBJECT_GENERATED, e -> {
            Manifold manifold = (Manifold) e.object1;
            updateActiveManifold3D((Manifold3D) e.object2);
            ManifoldListItem manifoldListItem = new ManifoldListItem(manifold);
            manifoldsListView.getItems().add(manifoldListItem);
            manifoldsListView.getSelectionModel().selectLast();
        });
    }

    private void updateActiveManifold3D(Manifold3D manifold3D) {
        reactive = false;
        activeManifold3D = manifold3D;
        if (null != manifold3D) {
            PhongMaterial phong = (PhongMaterial) manifold3D.quickhullMeshView.getMaterial();
            manifoldDiffuseColorPicker.setValue(phong.getDiffuseColor());
            manifoldSpecularColorPicker.setValue(phong.getSpecularColor());
            manifoldWireMeshColorPicker.setValue(((PhongMaterial)
                manifold3D.quickhullLinesMeshView.getMaterial()).getDiffuseColor());
        }
        reactive = true;
    }

    @FXML
    public void exportMatrix() {
        if (null != latestUmapObject) {
            if (null != latestUmapObject.getmEmbedding()) {
                LOG.info("latestUmapObject: {}", latestUmapObject.getmEmbedding().toStringNumpy());
            } else {
                LOG.info("UMAP Embeddings not generated yet.");
            }
        } else {
            LOG.info("UMAP object not yet established.");
        }
    }

    @FXML
    public void loadUmapConfig() {
        FileChooser fc = new FileChooser();
        fc.setTitle("Choose UMAP Config to load...");
        if (!latestDir.isDirectory())
            latestDir = new File(".");
        fc.setInitialDirectory(latestDir);
        File file = fc.showOpenDialog(scene.getWindow());
        if (null != file) {
            if (file.getParentFile().isDirectory())
                latestDir = file;
            ObjectMapper mapper = new ObjectMapper();
            UmapConfig uc;
            try {
                uc = mapper.readValue(file, UmapConfig.class);
                setUmapConfig(uc);
            } catch (IOException ex) {
                LOG.error(null, ex);
            }
        }
    }

    public void setUmapConfig(UmapConfig uc) {
        if (null != uc.getTargetWeight())
            targetWeightSlider.setValue(uc.getTargetWeight());
        repulsionSlider.setValue(uc.getRepulsionStrength());
        minDistanceSlider.setValue(uc.getMinDist());
        spreadSlider.setValue(uc.getSpread());
        opMixSlider.setValue(uc.getOpMixRatio());
        numComponentsSpinner.getValueFactory().setValue(uc.getNumberComponents());
        numEpochsSpinner.getValueFactory().setValue(uc.getNumberEpochs());
        nearestNeighborsSpinner.getValueFactory().setValue(uc.getNumberNearestNeighbours());
        negativeSampleRateSpinner.getValueFactory().setValue(uc.getNegativeSampleRate());
        localConnectivitySpinner.getValueFactory().setValue(uc.getLocalConnectivity());
        if (null != uc.getThreshold())
            thresholdSpinner.getValueFactory().setValue(uc.getThreshold());
        metricChoiceBox.getSelectionModel().select(uc.getMetric());
        verboseCheckBox.setSelected(uc.getVerbose());

    }

    @FXML
    public void saveUmapConfig() {
        FileChooser fc = new FileChooser();
        fc.setTitle("Choose UMAP Config file output...");
        fc.setInitialFileName(UmapConfig.configToFilename(getCurrentUmapConfig()).concat(".json"));
        if (!latestDir.isDirectory())
            latestDir = new File(".");
        fc.setInitialDirectory(latestDir);
        File file = fc.showSaveDialog(scene.getWindow());
        if (null != file) {
            if (file.getParentFile().isDirectory())
                latestDir = file;
            writeConfigFile(file);
        }
    }

    public UmapConfig getCurrentUmapConfig() {
        UmapConfig uc = new UmapConfig();
        uc.setTargetWeight((float) targetWeightSlider.getValue());
        uc.setRepulsionStrength((float) repulsionSlider.getValue());
        uc.setMinDist((float) minDistanceSlider.getValue());
        uc.setSpread((float) spreadSlider.getValue());
        uc.setOpMixRatio((float) opMixSlider.getValue());
        uc.setNumberComponents((int) numComponentsSpinner.getValue());
        uc.setNumberEpochs((int) numEpochsSpinner.getValue());
        uc.setNumberNearestNeighbours((int) nearestNeighborsSpinner.getValue());
        uc.setNegativeSampleRate((int) negativeSampleRateSpinner.getValue());
        uc.setLocalConnectivity((int) localConnectivitySpinner.getValue());
        uc.setThreshold((double) thresholdSpinner.getValue());
        uc.setMetric((String) metricChoiceBox.getValue());
        uc.setVerbose(verboseCheckBox.isSelected());
        return uc;
    }

    private void writeConfigFile(File file) {
        UmapConfig uc = getCurrentUmapConfig();
        ObjectMapper mapper = new ObjectMapper();
        try {
            mapper.writeValue(file, uc);
        } catch (IOException ex) {
            LOG.error(null, ex);
        }
    }
//    private String configToFilename(){
//        NumberFormat format = new DecimalFormat("0.00");
//        StringBuilder sb = new StringBuilder("UmapConfig-");
////        sb.append(targetWeightSlider.getValue()).append("-");
//        sb.append((String) metricChoiceBox.getValue()).append("-");
//        sb.append("R").append(format.format(repulsionSlider.getValue())).append("-");
//        sb.append("MD").append(format.format(minDistanceSlider.getValue())).append("-");
//        sb.append("S").append(format.format(spreadSlider.getValue())).append("-");
//        sb.append("OPM").append(format.format(opMixSlider.getValue())).append("-");
////        uc.setNumberComponents((int) numComponentsSpinner.getValue());
////        uc.setNumberEpochs((int) numEpochsSpinner.getValue());
//        sb.append("NN").append(nearestNeighborsSpinner.getValue()).append("-");
//        sb.append("NSR").append(negativeSampleRateSpinner.getValue()).append("-");
//        sb.append("LC").append(localConnectivitySpinner.getValue());

    /// /        uc.setThreshold((double) thresholdSpinner.getValue());
    /// /        uc.setVerbose(verboseCheckBox.isSelected());
//        return sb.toString();
//    }
    private void sendUmapConfig() {
        String name = latestDir.getAbsolutePath() + File.separator
            + UmapConfig.configToFilename(getCurrentUmapConfig()).concat(".json");
        scene.getRoot().fireEvent(new ManifoldEvent(
            ManifoldEvent.NEW_UMAP_CONFIG, getCurrentUmapConfig(), name));


    }

    @FXML
    public void exportScene() {
        FileChooser fc = new FileChooser();
        fc.setTitle("Choose Location file output...");
        fc.setInitialFileName(UmapConfig.configToFilename(getCurrentUmapConfig()).concat(".json"));
        if (!latestDir.isDirectory())
            latestDir = new File(".");
        fc.setInitialDirectory(latestDir);
        File file = fc.showSaveDialog(scene.getWindow());
        if (null != file) {
            if (file.getParentFile().isDirectory())
                latestDir = file.getParentFile();
            writeConfigFile(file);
            scene.getRoot().fireEvent(new ManifoldEvent(
                ManifoldEvent.EXPORT_PROJECTION_SCENE, file));
        }
    }

    @FXML
    public void saveProjections() {
        FileChooser fc = new FileChooser();
        fc.setTitle("Choose Projection file output...");
        fc.setInitialFileName("ProjectionData.json");
        if (!latestDir.isDirectory())
            latestDir = new File(".");
        fc.setInitialDirectory(latestDir);
        File file = fc.showSaveDialog(scene.getWindow());
        if (null != file) {
            if (file.getParentFile().isDirectory())
                latestDir = file;
            scene.getRoot().fireEvent(new ManifoldEvent(
                ManifoldEvent.SAVE_PROJECTION_DATA, file));
        }
    }

    @FXML
    public void runPCA() {
        AnalysisUtils.SOURCE source = useHypersurfaceButton.isSelected() ?
            AnalysisUtils.SOURCE.HYPERSURFACE : AnalysisUtils.SOURCE.HYPERSPACE;
        AnalysisUtils.ANALYSIS_METHOD method = svdRadioButton.isSelected() ?
            AnalysisUtils.ANALYSIS_METHOD.SVD : AnalysisUtils.ANALYSIS_METHOD.PCA;

        int startIndex = 0;
        int endIndex = -1; //use max indicator
        if (rangedFittingCheckBox.isSelected()) {
            startIndex = (int) fitStartIndexSpinner.getValue();
            endIndex = (int) fitEndIndexSpinner.getValue();
            if (endIndex <= startIndex)
                endIndex = -1;
        }

        PCAConfig config = new PCAConfig(source, method,
            (int) numPcaComponentsSpinner.getValue(), (double) pcaScalingSpinner.getValue(),
            startIndex, endIndex);
        ManifoldEvent.POINT_SOURCE pointSource = useHypersurfaceButton.isSelected() ?
            ManifoldEvent.POINT_SOURCE.HYPERSURFACE : ManifoldEvent.POINT_SOURCE.HYPERSPACE;
        scene.getRoot().fireEvent(new ManifoldEvent(
            ManifoldEvent.GENERATE_NEW_PCA, config, pointSource));
    }

    @FXML
    public void project() {
        Umap umap = new Umap();
        umap.setTargetWeight((float) targetWeightSlider.getValue());
        umap.setRepulsionStrength((float) repulsionSlider.getValue());
        umap.setMinDist((float) minDistanceSlider.getValue());
        umap.setSpread((float) spreadSlider.getValue());
        umap.setSetOpMixRatio((float) opMixSlider.getValue());
        umap.setNumberComponents((int) numComponentsSpinner.getValue());
        umap.setNumberEpochs((int) numEpochsSpinner.getValue());
        umap.setNumberNearestNeighbours((int) nearestNeighborsSpinner.getValue());
        umap.setNegativeSampleRate((int) negativeSampleRateSpinner.getValue());
        umap.setLocalConnectivity((int) localConnectivitySpinner.getValue());
        umap.setThreshold((double) thresholdSpinner.getValue());
        umap.setMetric((String) metricChoiceBox.getValue());
        umap.setVerbose(verboseCheckBox.isSelected());
        ManifoldEvent.POINT_SOURCE pointSource = useHypersurfaceButton.isSelected() ?
            ManifoldEvent.POINT_SOURCE.HYPERSURFACE : ManifoldEvent.POINT_SOURCE.HYPERSPACE;
        latestUmapObject = umap;
        scene.getRoot().fireEvent(new ManifoldEvent(
            ManifoldEvent.GENERATE_NEW_UMAP, umap, pointSource));
    }

    @FXML
    public void generate() {
        Double tolerance = null;
        if (!automaticCheckBox.isSelected())
            tolerance = (Double) manualSpinner.getValue();
        scene.getRoot().fireEvent(new ManifoldEvent(
            ManifoldEvent.GENERATE_PROJECTION_MANIFOLD,
            useVisibleRadioButton.isSelected(),
            (String) labelChoiceBox.getValue(), tolerance
        ));
    }

    @FXML
    public void clearAll() {
        scene.getRoot().fireEvent(new ManifoldEvent(
            ManifoldEvent.CLEAR_ALL_MANIFOLDS));
        //add them all in one shot
        manifoldsListView.getItems().clear();
    }

    @FXML
    public void exportAll() {
        DirectoryChooser fc = new DirectoryChooser();
        fc.setTitle("Choose Directory to export ManifoldData files...");
        if (!latestDir.isDirectory())
            latestDir = new File(".");
        fc.setInitialDirectory(latestDir);
        File file = fc.showDialog(scene.getWindow());
        if (null != file) {
            if (file.getParentFile().isDirectory()) {
                latestDir = file;
                int sequence = 0;
                for (ManifoldListItem m : manifoldsListView.getItems()) {
                    Manifold3D m3D = Manifold.globalManifoldToManifold3DMap.get(m.getManifold());
                    if (null != m3D) {
                        String fileName = "ManifoldData_" + sequence + "_" + m.getManifold().getLabel() + ".json";
                        File exportFile = new File(latestDir.getPath() + fileName);
                        scene.getRoot().fireEvent(new ManifoldEvent(
                            ManifoldEvent.EXPORT_MANIFOLD_DATA, exportFile, m3D));
                    }
                    sequence++;
                }
            }
        }
    }

    @FXML
    public void clusterBuilder() {
        //fire event to put projection view into cluster selection mode
        scene.getRoot().fireEvent(new ApplicationEvent(
            ApplicationEvent.SHOW_SHAPE3D_CONTROLS));
    }

    @FXML
    public void startConnector() {
        //fire event to put projection view into connector mode
        //@TODO SMP Hardcoded for now to Euclidean
        if (pointToGroupRadioButton.isSelected())
            scene.getRoot().fireEvent(new ManifoldEvent(
                ManifoldEvent.DISTANCE_MODE_POINTGROUP, pointToGroupRadioButton.isSelected(), "euclidean"));
        else
            scene.getRoot().fireEvent(new ManifoldEvent(
                ManifoldEvent.DISTANCE_MODE_POINTPOINT, pointToPointRadioButton.isSelected(), "euclidean"));
    }

    @FXML
    public void clearAllDistances() {
        distancesListView.getItems().clear();
        Distance.removeAllDistances(); //will fire event notifying scene
        scene.getRoot().fireEvent(
            new ManifoldEvent(ManifoldEvent.CLEAR_DISTANCE_CONNECTORS));
    }
}

Secondary Files

There are a number of other files that you’ll need to look at to understand the code in the FXML Controller. Here they are:

ManifoldListItem

/* Copyright (C) 2021 - 2024 Sean Phillips */

package edu.jhuapl.trinity.javafx.components.listviews;


import edu.jhuapl.trinity.data.Manifold;
import edu.jhuapl.trinity.javafx.events.ManifoldEvent;
import edu.jhuapl.trinity.javafx.javafx3d.Manifold3D;
import edu.jhuapl.trinity.utils.ResourceUtils;
import javafx.scene.control.CheckBox;
import javafx.scene.control.TextField;
import javafx.scene.image.ImageView;
import javafx.scene.input.MouseEvent;
import javafx.scene.layout.HBox;
import javafx.scene.layout.VBox;

import static edu.jhuapl.trinity.data.Manifold.globalManifoldToManifold3DMap;

/**
 * @author Sean Phillips
 */
public class ManifoldListItem extends VBox {

    private String labelString;
    private CheckBox visibleCheckBox;
    private TextField manifoldLabelTextField;
    private Manifold manifold;
    public boolean reactive = true;

    public ManifoldListItem(Manifold manifold) {
        this.manifold = manifold;
        labelString = manifold.getLabel();
        manifoldLabelTextField = new TextField(labelString);
        manifoldLabelTextField.setPrefWidth(200);
        visibleCheckBox = new CheckBox("Show");
        visibleCheckBox.setSelected(true);

        ImageView manifoldIcon = ResourceUtils.loadIcon("manifold", 32);

        HBox topHBox = new HBox(5, manifoldIcon, visibleCheckBox, manifoldLabelTextField);

        getChildren().addAll(topHBox);//, bottomHBox);
        setSpacing(2);
        visibleCheckBox.selectedProperty().addListener(cl -> {
            if (null != visibleCheckBox.getScene()) {
                this.manifold.setVisible(visibleCheckBox.isSelected());
                if (reactive) {
                    Manifold.updateManifold(this.manifold.getLabel(), this.manifold);
                    Manifold3D m3D = globalManifoldToManifold3DMap.get(this.manifold);
                    m3D.setVisible(manifold.getVisible());
                    getScene().getRoot().fireEvent(new ManifoldEvent(
                        ManifoldEvent.MANIFOLD_3D_VISIBLE, manifold.getVisible()));
                }
            }
        });
        manifoldIcon.addEventHandler(MouseEvent.MOUSE_CLICKED, e -> {
            if (e.getClickCount() > 1) {
                //Let application know this distance object has been selected
                getScene().getRoot().fireEvent(new ManifoldEvent(
                    ManifoldEvent.MANIFOLD_OBJECT_SELECTED, this.manifold));
                getScene().getRoot().fireEvent(
                    new ManifoldEvent(ManifoldEvent.MANIFOLD_3D_SELECTED, this.manifold));
            }
        });
        setOnMouseClicked(e -> {
            //Let application know this distance object has been selected
            getScene().getRoot().fireEvent(new ManifoldEvent(
                ManifoldEvent.MANIFOLD_OBJECT_SELECTED, this.getManifold()));
        });
        manifoldLabelTextField.textProperty().addListener(e -> {
            labelString = manifoldLabelTextField.getText();
            this.manifold.setLabel(labelString);
        });
    }

    public boolean getDataVisible() {
        return visibleCheckBox.isSelected();
    }

    public void setDataVisible(boolean visible) {
        visibleCheckBox.setSelected(visible);
    }

    /**
     * @return the manifold
     */
    public Manifold getManifold() {
        return manifold;
    }

    /**
     * @param manifold the manifold to set
     */
    public void setManifold(Manifold manifold) {
        this.manifold = manifold;
    }

}

Manifold

/* Copyright (C) 2021 - 2024 Sean Phillips */

package edu.jhuapl.trinity.data;

import edu.jhuapl.trinity.javafx.javafx3d.Manifold3D;
import javafx.beans.property.SimpleBooleanProperty;
import javafx.geometry.Point3D;
import javafx.scene.paint.Color;

import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;

/**
 * @author Sean Phillips
 */
public class Manifold {
    private ArrayList<Point3D> points;
    private String label; //common data label of manifold (from input data)
    private Color color; //color of representative object
    public SimpleBooleanProperty visible;

    public Manifold(ArrayList<Point3D> points, String label, String name, Color color) {
        this.points = new ArrayList<>(points.size());
        this.points.addAll(points);
        this.label = label;
        this.color = color;
        visible = new SimpleBooleanProperty(true);
    }

    /**
     * Provides lookup mechanism to find any object model that is currently
     * anchored in the system.
     */
    private static HashMap<String, Manifold> globalManifoldMap = new HashMap<>();
    public static HashMap<Manifold, Manifold3D> globalManifoldToManifold3DMap = new HashMap<>();

    public static Collection<Manifold> getManifolds() {
        return globalManifoldMap.values();
    }

    public static Manifold getManifold(String label) {
        return globalManifoldMap.get(label);
    }

    public static void addManifold(Manifold manifold) {
        globalManifoldMap.put(manifold.getLabel(), manifold);
    }

    public static void addAllManifolds(List<Manifold> manifolds) {
        manifolds.forEach(d -> {
            globalManifoldMap.put(d.getLabel(), d);
        });
    }

    public static void removeAllManifolds() {
        globalManifoldMap.clear();
        globalManifoldToManifold3DMap.clear();
    }

    public static Manifold removeManifold(String label) {
        Manifold removed = globalManifoldMap.remove(label);
        return removed;
    }

    public static void updateManifold(String label, Manifold manifold) {
        globalManifoldMap.put(label, manifold);
    }

    public static Color getColorByLabel(String label) {
        Manifold fl = Manifold.getManifold(label);
        if (null == fl)
            return Color.ALICEBLUE;
        return fl.getColor();
    }

    public static boolean visibilityByLabel(String label) {
        Manifold fl = Manifold.getManifold(label);
        if (null == fl)
            return true;
        return fl.getVisible();
    }

    public static void setAllVisible(boolean visible) {
        globalManifoldMap.forEach((s, fl) -> {
            fl.setVisible(visible);
        });
    }

    /**
     * @return the label
     */
    public String getLabel() {
        return label;
    }

    /**
     * @param label the label to set
     */
    public void setLabel(String label) {
        this.label = label;
    }

    /**
     * @return the color
     */
    public Color getColor() {
        return color;
    }

    /**
     * @param color the color to set
     */
    public void setColor(Color color) {
        this.color = color;
    }

    public SimpleBooleanProperty visibleProperty() {
        return this.visible;
    }

    public java.lang.Boolean getVisible() {
        return this.visibleProperty().get();
    }

    public void setVisible(final java.lang.Boolean visible) {
        this.visibleProperty().set(visible);
    }

    /**
     * @return the points
     */
    public ArrayList<Point3D> getPoints() {
        return points;
    }

    /**
     * @param points the points to set
     */
    public void setPoints(ArrayList<Point3D> points) {
        this.points = points;
    }
}

DistanceListItem

/* Copyright (C) 2021 - 2024 Sean Phillips */

package edu.jhuapl.trinity.javafx.components.listviews;

import edu.jhuapl.trinity.data.Distance;
import edu.jhuapl.trinity.javafx.events.ManifoldEvent;
import edu.jhuapl.trinity.utils.PrecisionConverter;
import javafx.scene.control.CheckBox;
import javafx.scene.control.Label;
import javafx.scene.layout.HBox;

/**
 * @author Sean Phillips
 */
public class DistanceListItem extends HBox {
    private String labelString;
    private CheckBox visibleCheckBox;
    private Label label;
    private Label distanceValueLabel;
    private Distance distance;
    public boolean reactive = true;

    public DistanceListItem(Distance distance) {
        this.distance = distance;
        this.labelString = distance.getLabel();
        visibleCheckBox = new CheckBox("Visible");
        visibleCheckBox.setSelected(true);
        label = new Label(labelString);
        PrecisionConverter pc = new PrecisionConverter(7);
        String distanceLabel = distance.getMetric() + ":" + pc.toString(distance.getValue());
        distanceValueLabel = new Label(distanceLabel);
        getChildren().addAll(visibleCheckBox, label, distanceValueLabel);
        setSpacing(5);
        visibleCheckBox.selectedProperty().addListener(cl -> {
            if (null != visibleCheckBox.getScene()) {
                distance.setVisible(visibleCheckBox.isSelected());
                if (reactive)
                    Distance.updateDistance(distance.getLabel(), distance);
            }
        });
        setOnMouseClicked(e -> {
            //Let application know this distance object has been selected
            getScene().getRoot().fireEvent(new ManifoldEvent(
                ManifoldEvent.DISTANCE_OBJECT_SELECTED, distance));
        });
    }

    public boolean getDataVisible() {
        return visibleCheckBox.isSelected();
    }

    public void setDataVisible(boolean visible) {
        visibleCheckBox.setSelected(visible);
    }

    /**
     * @return the distance
     */
    public Distance getDistance() {
        return distance;
    }

    /**
     * @param distance the distance to set
     */
    public void setDistance(Distance distance) {
        this.distance = distance;
    }
}

Distance

/* Copyright (C) 2021 - 2024 Sean Phillips */

package edu.jhuapl.trinity.data;

import javafx.beans.property.SimpleBooleanProperty;
import javafx.geometry.Point3D;
import javafx.scene.paint.Color;

import java.util.Collection;
import java.util.HashMap;
import java.util.List;

/**
 * @author Sean Phillips
 */
public class Distance {
    private String metric; //Used to lookup into Metric enum later
    private double value; //the computed value
    private int width; //width of the connector
    private Point3D point1;
    private Point3D point2;
    private String label;
    private Color color;
    public SimpleBooleanProperty visible;

    public Distance(String label, Color color, String metric, Integer width) {
        this.label = label;
        this.color = color;
        this.width = width;
        if (null == metric)
            metric = "euclidean";
        else
            this.metric = metric;
        visible = new SimpleBooleanProperty(true);
    }

    /**
     * Provides lookup mechanism to find any object model that is currently
     * anchored in the system.
     */
    private static HashMap<String, Distance> globalDistanceMap = new HashMap<>();

    public static Collection<Distance> getDistances() {
        return globalDistanceMap.values();
    }

    public static Distance getDistance(String label) {
        return globalDistanceMap.get(label);
    }

    public static void addDistance(Distance distance) {
        globalDistanceMap.put(distance.getLabel(), distance);
    }

    public static void addAllDistances(List<Distance> distances) {
        distances.forEach(d -> {
            globalDistanceMap.put(d.getLabel(), d);
        });
    }

    public static void removeAllDistances() {
        globalDistanceMap.clear();
    }

    public static Distance removeDistance(String label) {
        Distance removed = globalDistanceMap.remove(label);
        return removed;
    }

    public static void updateDistance(String label, Distance distance) {
        globalDistanceMap.put(label, distance);
    }

    public static Color getColorByLabel(String label) {
        Distance fl = Distance.getDistance(label);
        if (null == fl)
            return Color.ALICEBLUE;
        return fl.getColor();
    }

    public static boolean visibilityByLabel(String label) {
        Distance fl = Distance.getDistance(label);
        if (null == fl)
            return true;
        return fl.getVisible();
    }

    public static void setAllVisible(boolean visible) {
        globalDistanceMap.forEach((s, fl) -> {
            fl.setVisible(visible);
        });
    }

    /**
     * @return the value
     */
    public double getValue() {
        return value;
    }

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

    /**
     * @return the point1
     */
    public Point3D getPoint1() {
        return point1;
    }

    /**
     * @param point1 the point1 to set
     */
    public void setPoint1(Point3D point1) {
        this.point1 = point1;
    }

    /**
     * @return the point2
     */
    public Point3D getPoint2() {
        return point2;
    }

    /**
     * @param point2 the point2 to set
     */
    public void setPoint2(Point3D point2) {
        this.point2 = point2;
    }

    /**
     * @return the label
     */
    public String getLabel() {
        return label;
    }

    /**
     * @param label the label to set
     */
    public void setLabel(String label) {
        this.label = label;
    }

    /**
     * @return the color
     */
    public Color getColor() {
        return color;
    }

    /**
     * @param color the color to set
     */
    public void setColor(Color color) {
        this.color = color;
    }

    public SimpleBooleanProperty visibleProperty() {
        return this.visible;
    }

    public java.lang.Boolean getVisible() {
        return this.visibleProperty().get();
    }

    public void setVisible(final java.lang.Boolean visible) {
        this.visibleProperty().set(visible);
    }

    /**
     * @return the metric
     */
    public String getMetric() {
        return metric;
    }

    /**
     * @param metric the metric to set
     */
    public void setMetric(String metric) {
        this.metric = metric;
    }

    /**
     * @return the width
     */
    public int getWidth() {
        return width;
    }

    /**
     * @param width the width to set
     */
    public void setWidth(int width) {
        this.width = width;
    }
}