package edu.stanford.rsl.apps.gui;
import java.awt.Color;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.awt.LayoutManager;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.ButtonGroup;
import javax.swing.JCheckBox;
import javax.swing.JComboBox;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JRadioButton;
import javax.swing.JTabbedPane;
import javax.swing.JTextField;
import javax.swing.SwingUtilities;
import javax.swing.event.DocumentEvent;
import javax.swing.event.DocumentListener;
import edu.stanford.rsl.conrad.geometry.General;
import edu.stanford.rsl.conrad.geometry.Projection.CameraAxisDirection;
import edu.stanford.rsl.conrad.geometry.trajectories.CircularTrajectory;
import edu.stanford.rsl.conrad.geometry.trajectories.ConfigFileBasedTrajectory;
import edu.stanford.rsl.conrad.geometry.trajectories.MultiSweepTrajectory;
import edu.stanford.rsl.conrad.geometry.trajectories.Trajectory;
import edu.stanford.rsl.conrad.numerics.SimpleVector;
import edu.stanford.rsl.conrad.physics.detector.XRayDetector;
import edu.stanford.rsl.conrad.utils.CONRAD;
import edu.stanford.rsl.conrad.utils.Configuration;
import edu.stanford.rsl.conrad.utils.GUIUtil;
import edu.stanford.rsl.conrad.utils.UserUtil;
/**
* This code was edited or generated using CloudGarden's Jigloo
* SWT/Swing GUI Builder, which is free for non-commercial
* use. If Jigloo is being used commercially (ie, by a corporation,
* company or business for any purpose whatever) then you
* should purchase a license for each developer using Jigloo.
* Please visit www.cloudgarden.com for details.
* Use of Jigloo implies acceptance of these licensing terms.
* A COMMERCIAL LICENSE HAS NOT BEEN PURCHASED FOR
* THIS MACHINE, SO JIGLOO OR THIS CODE CANNOT BE USED
* LEGALLY FOR ANY CORPORATE OR COMMERCIAL PURPOSE.
*/
public class ConfigurationFrame extends JFrame implements ActionListener {
/**
*
*/
private static final long serialVersionUID = 979874928758716096L;
private JTabbedPane jTabbedPane;
private JButton jSaveButton;
private boolean exited = false;
Configuration config;
private UpdateableGUI parentFrame;
private RegistryEditor regEditor;
private TrajectoryEditor trajEdit;
JButton jCenterVolume = new JButton("Center volume");
JButton jDoubleVolumeResolution = new JButton("Resolution *= 2");
JButton jHalfVolumeResolution = new JButton("Resolution /= 2");
JButton jDoubleDetectorResolution = new JButton("Resolution *= 2");
JButton jHalfDetectorResolution = new JButton("Resolution /= 2");
public ConfigurationFrame(){
config = Configuration.getGlobalConfiguration();
regEditor = new RegistryEditor(config);
SwingUtilities.invokeLater(new Runnable() {
public void run(){
regEditor.initGUI();
};
});
initGUI();
updateValues();
}
public boolean isExited() {
return exited;
}
public void exit(){
exited = true;
setVisible(false);
if (parentFrame != null) parentFrame.updateGUI();
System.out.println("exiting config frame");
}
String [] camAxes = new String [] {
"points in the direction of detector motion",
"points against the direction of detector motion",
"points in rotation axis direction",
"points against rotation axis direction"};
private CameraAxisDirection getDirection(String str){
CameraAxisDirection dir = CameraAxisDirection.DETECTORMOTION_PLUS;
if (str != null){
if (str.equals("points in the direction of detector motion")){
dir = CameraAxisDirection.DETECTORMOTION_PLUS;
} else if (str.equals("points against the direction of detector motion")){
dir = CameraAxisDirection.DETECTORMOTION_MINUS;
} else if (str.equals("points in rotation axis direction")){
dir = CameraAxisDirection.ROTATIONAXIS_PLUS;
} else if (str.equals("points against rotation axis direction")){
dir = CameraAxisDirection.ROTATIONAXIS_MINUS;
}
}
return dir;
}
private int getDirectionIndex(CameraAxisDirection dir){
int index = -1;
if (dir == CameraAxisDirection.DETECTORMOTION_PLUS) {
index = 0;
} else if (dir == CameraAxisDirection.DETECTORMOTION_MINUS){
index = 1;
} else if (dir == CameraAxisDirection.ROTATIONAXIS_PLUS){
index = 2;
} else if (dir == CameraAxisDirection.ROTATIONAXIS_MINUS){
index = 3;
}
return index;
}
public void actionPerformed(ActionEvent e) {
if (e.getSource() != null){
if (e.getSource().equals(jSaveButton)) {
readValuesToConfig();
if (config.getImportFromDicomAutomatically()) {
try {
Trajectory load = Configuration.loadGeometrySource(config);
if (load != null){
config.setGeometry(load);
}
} catch (Exception e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
}
Configuration.setGlobalConfiguration(config);
Configuration.saveConfiguration();
exited = true;
setVisible(false);
if (parentFrame != null) parentFrame.updateGUI();
}
if (e.getSource().equals(trajectoryEditorButton)) {
startTrajectoryEditor();
}
if (e.getSource().equals(jParseGeometry)) {
JTextField field = this.projectionTableFileField;
Trajectory geom = ConfigFileBasedTrajectory.openAsGeometrySource(field.getText(), config.getGeometry());
if (geom != null){
Configuration config = Configuration.getGlobalConfiguration();
config.setProjectionTableFileName(field.getText());
config.setGeometry(geom);
}
updateValues();
}
if (e.getSource().equals(optionList)){
//System.out.println("Event" + e);
trajectoryPanel.remove(trajectoryFromParameters);
trajectoryPanel.remove(trajectoryFromFile);
if (optionList.getSelectedIndex() == 0){
trajectoryPanel.add(trajectoryFromFile, createConstraints(0, 2, 5, 1, GridBagConstraints.NORTHWEST, GridBagConstraints.HORIZONTAL, 0, 0, 0, 0));
} else {
trajectoryPanel.add(trajectoryFromParameters, createConstraints(0, 2, 5, 1, GridBagConstraints.NORTHWEST, GridBagConstraints.HORIZONTAL, 0, 0, 0, 0));
}
this.repaint();
}
if (e.getSource().equals(jGenerateDetector)) {
XRayDetector detector;
try {
detector = (XRayDetector) UserUtil.queryObject("Select Detector:", "Detector Selection", XRayDetector.class);
detector.configure();
Configuration.getGlobalConfiguration().setDetector(detector);
jDetectorLabel.setText("Current Detector: " + config.getDetector());
} catch (Exception e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
}
if (e.getSource().equals(jGenerateGeometry)) {
readValuesToConfig();
int numProjectionMatrices = config.getGeometry().getProjectionStackSize();
double sourceToAxisDistance = Double.parseDouble(sourceToPatientField.getText());
double averageAngularIncrement = config.getGeometry().getAverageAngularIncrement();
double detectorOffsetU = config.getGeometry().getDetectorOffsetU();
double detectorOffsetV = config.getGeometry().getDetectorOffsetV();
CameraAxisDirection uDirection = config.getGeometry().getDetectorUDirection();
CameraAxisDirection vDirection = config.getGeometry().getDetectorVDirection();
SimpleVector rotationAxis = config.getGeometry().getRotationAxis();
Trajectory geom = new CircularTrajectory(config.getGeometry());
geom.setSecondaryAngleArray(null);
((CircularTrajectory)geom).setTrajectory(numProjectionMatrices, sourceToAxisDistance, averageAngularIncrement, detectorOffsetU, detectorOffsetV, uDirection, vDirection, rotationAxis);
if (geom != null){
Configuration config = Configuration.getGlobalConfiguration();
if (config.getNumSweeps() > 1){
MultiSweepTrajectory multi = new MultiSweepTrajectory(geom);
multi.extrapolateProjectionGeometry();
geom = new Trajectory(multi);
}
config.setGeometry(geom);
}
}
if (e.getSource().equals(jCenterVolume)) {
centerVolume();
}
if (e.getSource().equals(jDoubleVolumeResolution)) {
changeVolumeResolution(2.0);
}
if (e.getSource().equals(jHalfVolumeResolution)) {
changeVolumeResolution(0.5);
}
if (e.getSource().equals(jDoubleDetectorResolution)) {
changeDetectorResolution(2.0);
}
if (e.getSource().equals(jHalfDetectorResolution)) {
changeDetectorResolution(0.5);
}
}
}
private void startTrajectoryEditor() {
if(trajEdit == null) {
trajEdit = new TrajectoryEditor();
trajEdit.setVisible(true);
trajEdit.setLocation(CONRAD.getWindowTopCorner());
}
}
/**
* creates a 5 x 4 GridBagLayout in ConfigurationFrame SubPanel-Style
* @return the sub panel layout
*/
static LayoutManager createSubPaneLayout(){
GridBagLayout thisLayout = new GridBagLayout();
thisLayout.rowWeights = new double[] {0.0, 0.1, 0.1, 0.0};
thisLayout.rowHeights = new int[] {15, 120, 120, 15};
thisLayout.columnWeights = new double[] {0.1, 0.1, 0.1, 0.1, 0.1};
thisLayout.columnWidths = new int[] {15, 225, 15, 225, 15};
return thisLayout;
}
private void positionNumericLabelTextFieldPair(JPanel panel, String labelText, JTextField field, int x, int y, int topOffset){
JLabel label = new JLabel(labelText);
panel.add(label, createConstraints(x, y, 1, 1, GridBagConstraints.NORTHWEST, GridBagConstraints.NONE, topOffset + 3, 0, 0, 0));
panel.add(field, createConstraints(x, y, 1, 1, GridBagConstraints.NORTHWEST, GridBagConstraints.HORIZONTAL, topOffset, 210, 0, 0));
field.setHorizontalAlignment(JTextField.RIGHT);
}
private void positionLabelTextFieldPair(JPanel panel, String labelText, JTextField field, int x, int y, int width, int topOffset){
JLabel label = new JLabel(labelText);
panel.add(label, createConstraints(x, y, width, 1, GridBagConstraints.NORTHWEST, GridBagConstraints.NONE, topOffset + 3, 0, 0, 0));
panel.add(field, createConstraints(x, y, width, 1, GridBagConstraints.NORTHWEST, GridBagConstraints.HORIZONTAL, topOffset, 210, 0, 0));
}
private void positionLabelTextFieldButton(JPanel panel, String labelText, JTextField field, int x, int y, int width, int topOffset, JButton button){
JLabel label = new JLabel(labelText);
panel.add(label, createConstraints(x, y, width, 1, GridBagConstraints.NORTHWEST, GridBagConstraints.NONE, topOffset + 3, 0, 0, 0));
panel.add(field, createConstraints(x, y, width, 1, GridBagConstraints.NORTHWEST, GridBagConstraints.HORIZONTAL, topOffset+30, 0, 0, 0));
panel.add(button, createConstraints(x+width-1, y, 1, 1, GridBagConstraints.NORTHEAST, GridBagConstraints.HORIZONTAL, topOffset+60, 100, 0, 0));
}
JTextField xDimensionField = new JTextField();
JTextField yDimensionField = new JTextField();
JTextField zDimensionField = new JTextField();
JTextField xOriginVoxel = new JTextField();
JTextField yOriginVoxel = new JTextField();
JTextField zOriginVoxel = new JTextField();
JTextField xOriginWorld = new JTextField();
JTextField yOriginWorld = new JTextField();
JTextField zOriginWorld = new JTextField();
JTextField xSpacingField = new JTextField();
JTextField ySpacingField = new JTextField();
JTextField zSpacingField = new JTextField();
JTextField maxVOIPathField = new JTextField();
private void updateValues(){
// volume
Trajectory geometry = config.getGeometry();
if (geometry != null) {
xDimensionField.setText("" + geometry.getReconDimensionX());
yDimensionField.setText("" + geometry.getReconDimensionY());
zDimensionField.setText("" + geometry.getReconDimensionZ());
xSpacingField.setText("" + geometry.getVoxelSpacingX());
ySpacingField.setText("" + geometry.getVoxelSpacingY());
zSpacingField.setText("" + geometry.getVoxelSpacingZ());
xOriginWorld.setText("" + geometry.getOriginX());
yOriginWorld.setText("" + geometry.getOriginY());
zOriginWorld.setText("" + geometry.getOriginZ());
xOriginVoxel.setText("" + geometry.getOriginInPixelsX());
yOriginVoxel.setText("" + geometry.getOriginInPixelsY());
zOriginVoxel.setText("" + geometry.getOriginInPixelsZ());
// geometry
detectorWidthField.setText("" + geometry.getDetectorWidth());
detectorHeightField.setText("" + geometry.getDetectorHeight());
pixelDimensionXField.setText("" + geometry.getPixelDimensionX());
pixelDimensionYField.setText("" + geometry.getPixelDimensionY());
sourceToDetectorField.setText("" + geometry.getSourceToDetectorDistance());
sourceToPatientField.setText("" + geometry.getSourceToAxisDistance());
projectionStackSizeField.setText("" + geometry.getProjectionStackSize());
// new parameters for trajectory definition
averageAngularIncrement.setText("" + geometry.getAverageAngularIncrement());
detectorOffsetU.setText("" + geometry.getDetectorOffsetU());
detectorOffsetV.setText("" + geometry.getDetectorOffsetV());
SimpleVector rotAxis = geometry.getRotationAxis();
if (rotAxis==null) rotAxis = new SimpleVector(0,0,1);
rotationAxis.setText("" + rotAxis.toString());
DetectorUDirection.setSelectedIndex(getDirectionIndex(geometry.getDetectorUDirection()));
DetectorVDirection.setSelectedIndex(getDirectionIndex(geometry.getDetectorVDirection()));
}
numSweepsField.setText("" + config.getNumSweeps());
maxVOIPathField.setText(config.getVolumeOfInterestFileName());
projectionTableFileField.setText(config.getProjectionTableFileName());
// other
recentFileOneField.setText(config.getRecentFileOne());
recentFileTwoField.setText(config.getRecentFileTwo());
importFromDicom.setSelected(config.getImportFromDicomAutomatically());
extrapolateGeometry.setSelected(config.getUseExtrapolatedGeometry());
houns.setSelected(config.getUseHounsfieldScaling());
if (config.getCitationFormat() == Configuration.BIBTEX_CITATION_FORMAT){
citationFormatGroup.setSelected(bibButton.getModel(), true);
} else {
citationFormatGroup.setSelected(medlineButton.getModel(), true);
}
}
private String getTextSave(JTextField textField){
String revan = null;
if (! textField.getText().equals("")) {
revan = textField.getText();
}
return revan;
}
public void setParentFrame(UpdateableGUI parentFrame) {
this.parentFrame = parentFrame;
}
public UpdateableGUI getParentFrame() {
return parentFrame;
}
private void readValuesToConfig() throws NumberFormatException {
// volume
config.getGeometry().setReconDimensionX((int) Double.parseDouble(xDimensionField.getText()));
config.getGeometry().setReconDimensionY((int) Double.parseDouble(yDimensionField.getText()));
config.getGeometry().setReconDimensionZ((int) Double.parseDouble(zDimensionField.getText()));
config.getGeometry().setVoxelSpacingX(Double.parseDouble(xSpacingField.getText()));
config.getGeometry().setVoxelSpacingY(Double.parseDouble(ySpacingField.getText()));
config.getGeometry().setVoxelSpacingZ(Double.parseDouble(zSpacingField.getText()));
config.getGeometry().setOriginInPixelsX(Double.parseDouble(xOriginVoxel.getText()));
config.getGeometry().setOriginInPixelsY(Double.parseDouble(yOriginVoxel.getText()));
config.getGeometry().setOriginInPixelsZ(Double.parseDouble(zOriginVoxel.getText()));
config.setVolumeOfInterestFileName(getTextSave(maxVOIPathField));
// geometry
config.getGeometry().setDetectorWidth((int)Math.floor(Double.parseDouble(detectorWidthField.getText())));
config.getGeometry().setDetectorHeight((int)Math.floor(Double.parseDouble(detectorHeightField.getText())));
config.getGeometry().setPixelDimensionX(Double.parseDouble(pixelDimensionXField.getText()));
config.getGeometry().setPixelDimensionY(Double.parseDouble(pixelDimensionYField.getText()));
config.getGeometry().setSourceToDetectorDistance(Double.parseDouble(sourceToDetectorField.getText()));
config.getGeometry().setSourceToAxisDistance(Double.parseDouble(sourceToPatientField.getText()));
config.getGeometry().setProjectionStackSize(Integer.parseInt(projectionStackSizeField.getText()));
config.setNumSweeps(Integer.parseInt(numSweepsField.getText()));
config.setProjectionTableFileName(getTextSave(projectionTableFileField));
// other
config.setRecentFileOne(getTextSave(recentFileOneField));
config.setRecentFileTwo(getTextSave(recentFileTwoField));
config.setImportFromDicomAutomatically(importFromDicom.isSelected());
config.setUseExtrapolatedGeometry(extrapolateGeometry.isSelected());
config.setUseHounsfieldScaling(houns.isSelected());
if (bibButton.isSelected()){
config.setCitationFormat(Configuration.BIBTEX_CITATION_FORMAT);
} else {
config.setCitationFormat(Configuration.MEDLINE_CITATION_FORMAT);
}
// new parameters for trajectory definition
config.getGeometry().setAverageAngularIncrement(Double.parseDouble(averageAngularIncrement.getText()));
config.getGeometry().setDetectorOffsetU(Double.parseDouble(detectorOffsetU.getText()));
config.getGeometry().setDetectorOffsetV(Double.parseDouble(detectorOffsetV.getText()));
SimpleVector rotAxis = new SimpleVector();
rotAxis.setVectorSerialization(rotationAxis.getText());
config.getGeometry().setRotationAxis(rotAxis);
config.getGeometry().setDetectorUDirection(getDirection((String)DetectorUDirection.getSelectedItem()));
config.getGeometry().setDetectorVDirection(getDirection((String)DetectorVDirection.getSelectedItem()));
regEditor.updateToConfiguration();
}
JLabel jDetectorLabel;
private JPanel detectorPane(){
JPanel volume = new JPanel();
volume.setBackground(Color.white);
volume.setLayout(createSubPaneLayout());
positionNumericLabelTextFieldPair(volume, "Detector size x [pixels]", detectorWidthField, 1, 1, 0);
positionNumericLabelTextFieldPair(volume, "Detector size y [pixels]", detectorHeightField, 1, 1, 30);
positionNumericLabelTextFieldPair(volume, "Pixel spacing x [mm]", pixelDimensionXField, 3, 1, 0);
positionNumericLabelTextFieldPair(volume, "Pixel spacing y [mm]", pixelDimensionYField, 3, 1, 30);
volume.add(jDoubleDetectorResolution, createConstraints(1, 1, 3, 1, GridBagConstraints.NORTH, GridBagConstraints.NONE, 200, -150, 0, 0));
jDoubleDetectorResolution.addActionListener(this);
volume.add(jHalfDetectorResolution, createConstraints(1, 1, 3, 1, GridBagConstraints.NORTH, GridBagConstraints.NONE, 200, 150, 0, 0));
jHalfDetectorResolution.addActionListener(this);
volume.add(jGenerateDetector, createConstraints(1, 1, 3, 1, GridBagConstraints.NORTH, GridBagConstraints.NONE, 90, 0, 0, 0));
jDetectorLabel = new JLabel("Current Detector: " + config.getDetector());
volume.add(jDetectorLabel, createConstraints(1, 1, 3, 1, GridBagConstraints.NORTH, GridBagConstraints.NONE, 60, 0, 0, 0));
jGenerateDetector.addActionListener(this);
return volume;
}
private void changeDetectorResolution(double scale){
testNumericFields(detectorWidthField, detectorHeightField, pixelDimensionXField, pixelDimensionYField);
updateNumericFieldValue(pixelDimensionXField, 1.0/scale);
updateNumericFieldValue(pixelDimensionYField, 1.0/scale);
updateNumericFieldValue(detectorWidthField, scale);
updateNumericFieldValue(detectorHeightField, scale);
}
private void updateNumericFieldValue(JTextField field, double scale){
updateNumericFieldValue(field, scale, false);
}
private void updateNumericFieldValue(JTextField field, double scale, boolean roundToInteger){
if (!roundToInteger)
field.setText(new Double(Double.parseDouble(field.getText()) * scale).toString());
else
field.setText(new Integer((int)Math.floor(Double.parseDouble(field.getText()) * scale)).toString());
}
/**
* Will throw a parsing exception, if the fields contain invalid numbers.
* @param fields
*/
private void testNumericFields(JTextField ... fields){
for (int i=0; i<fields.length; i++){
Double.parseDouble(fields[i].getText());
}
}
private void changeVolumeResolution(double scale){
testNumericFields(xSpacingField, ySpacingField, zSpacingField, xDimensionField, yDimensionField, zDimensionField);
updateNumericFieldValue(xSpacingField, 1.0/scale);
updateNumericFieldValue(ySpacingField, 1.0/scale);
updateNumericFieldValue(zSpacingField, 1.0/scale);
updateNumericFieldValue(xDimensionField, scale);
updateNumericFieldValue(yDimensionField, scale);
updateNumericFieldValue(zDimensionField, scale);
}
private JPanel volumePane(){
JPanel volume = new JPanel();
volume.setBackground(Color.white);
volume.setLayout(createSubPaneLayout());
positionNumericLabelTextFieldPair(volume, "Size x [voxels]", xDimensionField, 1, 1, 0);
positionNumericLabelTextFieldPair(volume, "Spacing x [mm]", xSpacingField, 3, 1, 0);
positionNumericLabelTextFieldPair(volume, "Size y [voxels]", yDimensionField, 1, 1, 30);
positionNumericLabelTextFieldPair(volume, "Spacing y [mm]", ySpacingField, 3, 1, 30);
positionNumericLabelTextFieldPair(volume, "Size z [voxels]", zDimensionField, 1, 1, 60);
positionNumericLabelTextFieldPair(volume, "Spacing z [mm]", zSpacingField, 3, 1, 60);
positionNumericLabelTextFieldPair(volume, "Index of (0mm/0mm/0mm) x [voxels]", xOriginVoxel, 1, 1, 90);
xOriginVoxel.setEnabled(false);
positionNumericLabelTextFieldPair(volume, "Index of (0mm/0mm/0mm) y [voxels]", yOriginVoxel, 1, 1, 120);
yOriginVoxel.setEnabled(false);
positionNumericLabelTextFieldPair(volume, "Index of (0mm/0mm/0mm) z [voxels]", zOriginVoxel, 1, 1, 150);
zOriginVoxel.setEnabled(false);
positionNumericLabelTextFieldPair(volume, "World coord. of vol. origin (0/0/0) x [mm]", xOriginWorld, 3, 1, 90);
positionNumericLabelTextFieldPair(volume, "World coord. of vol. origin (0/0/0) y [mm]", yOriginWorld, 3, 1, 120);
positionNumericLabelTextFieldPair(volume, "World coord. of vol. origin (0/0/0) z [mm]", zOriginWorld, 3, 1, 150);
xSpacingField.getDocument().addDocumentListener(new VoxelWorldFieldUpdater(xOriginWorld, xOriginVoxel, xSpacingField));
xOriginWorld.getDocument().addDocumentListener(new VoxelWorldFieldUpdater(xOriginWorld, xOriginVoxel, xSpacingField));
ySpacingField.getDocument().addDocumentListener(new VoxelWorldFieldUpdater(yOriginWorld, yOriginVoxel, ySpacingField));
yOriginWorld.getDocument().addDocumentListener(new VoxelWorldFieldUpdater(yOriginWorld, yOriginVoxel, ySpacingField));
zSpacingField.getDocument().addDocumentListener(new VoxelWorldFieldUpdater(zOriginWorld, zOriginVoxel, zSpacingField));
zOriginWorld.getDocument().addDocumentListener(new VoxelWorldFieldUpdater(zOriginWorld, zOriginVoxel, zSpacingField));
volume.add(jCenterVolume, createConstraints(1, 1, 3, 1, GridBagConstraints.NORTH, GridBagConstraints.NONE, 200, 0, 0, 0));
jCenterVolume.addActionListener(this);
volume.add(jDoubleVolumeResolution, createConstraints(1, 1, 3, 1, GridBagConstraints.NORTH, GridBagConstraints.NONE, 200, -300, 0, 0));
jDoubleVolumeResolution.addActionListener(this);
volume.add(jHalfVolumeResolution, createConstraints(1, 1, 3, 1, GridBagConstraints.NORTH, GridBagConstraints.NONE, 200, 300, 0, 0));
jHalfVolumeResolution.addActionListener(this);
positionLabelTextFieldPair(volume, "Maximum VOI file:", maxVOIPathField, 1, 2, 3, 0);
GUIUtil.enableDragAndDrop(maxVOIPathField);
return volume;
}
private void centerVolume() {
double dimX = Double.parseDouble(xDimensionField.getText());
double dimY = Double.parseDouble(yDimensionField.getText());
double dimZ = Double.parseDouble(zDimensionField.getText());
double spacingX = Double.parseDouble(xSpacingField.getText());
double spacingY = Double.parseDouble(ySpacingField.getText());
double spacingZ = Double.parseDouble(zSpacingField.getText());
xOriginWorld.setText(new Double(-(dimX-1.0)/2.0 * spacingX).toString());
yOriginWorld.setText(new Double(-(dimY-1.0)/2.0 * spacingY).toString());
zOriginWorld.setText(new Double(-(dimZ-1.0)/2.0 * spacingZ).toString());
}
JTextField detectorWidthField = new JTextField();
JTextField detectorHeightField = new JTextField();
JTextField pixelDimensionXField = new JTextField();
JTextField pixelDimensionYField = new JTextField();
JButton jGenerateDetector = new JButton("Configure absorption behavior");
JTextField projectionStackSizeField = new JTextField();
JTextField numSweepsField = new JTextField();
JTextField sourceToDetectorField = new JTextField();
JTextField sourceToPatientField = new JTextField();
JTextField projectionTableFileField = new JTextField();
JButton jParseGeometry = new JButton("Import");
JButton jGenerateGeometry = new JButton("Define a trajectory");
// new trajectory parameters
JTextField averageAngularIncrement = new JTextField();
JTextField detectorOffsetU = new JTextField();
JTextField detectorOffsetV = new JTextField();
JTextField rotationAxis = new JTextField();
JComboBox DetectorUDirection = new JComboBox(camAxes);
JComboBox DetectorVDirection = new JComboBox(camAxes);
JComboBox optionList;
JPanel trajectoryFromFile;
JPanel trajectoryFromParameters;
JPanel trajectoryPanel;
JButton trajectoryEditorButton;
/**
* Trajectory Tab
* @return
*/
private JPanel trajectoryPane(){
trajectoryPanel = new JPanel();
trajectoryPanel.setBackground(Color.white);
GridBagLayout thisLayout = new GridBagLayout();
thisLayout.rowWeights = new double[] {0.0, 0.1, 0.1, 0.0};
thisLayout.rowHeights = new int[] {15, 30, 120, 15};
thisLayout.columnWeights = new double[] {0.0, 0.1, 0.0, 0.1, 0.0};
thisLayout.columnWidths = new int[] {15, 225, 15, 225, 15};
trajectoryPanel.setLayout(thisLayout);
int x = 1;
int y = 1;
int topOffset = 0;
int width = 3;
String[] options = { "from file", "from parameters"};
trajectoryEditorButton = new JButton("Edit Trajetory");
trajectoryEditorButton.addActionListener(this);
optionList = new JComboBox(options);
optionList.addActionListener(this);
JLabel label = new JLabel("Define trajectory:");
trajectoryPanel.add(label, createConstraints(x, y, width, 1, GridBagConstraints.NORTHWEST, GridBagConstraints.NONE, topOffset + 3, 0, 0, 0));
trajectoryPanel.add(optionList, createConstraints(x, y, width, 1, GridBagConstraints.NORTHWEST, GridBagConstraints.HORIZONTAL, topOffset, 170, 0, 150));
trajectoryPanel.add(trajectoryEditorButton, createConstraints(x, y, width, 1, GridBagConstraints.NORTHWEST, GridBagConstraints.HORIZONTAL, topOffset-2, 470, 0, 30));
trajectoryFromFile = trajectoryFromFile();
trajectoryFromParameters = trajectoryFromParameters();
if (Configuration.getGlobalConfiguration().getProjectionTableFileName() != null){
optionList.setSelectedIndex(0);
trajectoryPanel.add(trajectoryFromFile, createConstraints(0, 2, 5, 1, GridBagConstraints.NORTHWEST, GridBagConstraints.HORIZONTAL, 0, 0, 0, 0));
} else {
optionList.setSelectedIndex(1);
trajectoryPanel.add(trajectoryFromParameters, createConstraints(0, 2, 5, 1, GridBagConstraints.NORTHWEST, GridBagConstraints.HORIZONTAL, 0, 0, 0, 0));
}
return trajectoryPanel;
}
private JPanel trajectoryFromParameters(){
JPanel volume = new JPanel();
volume.setBackground(Color.white);
volume.setLayout(createSubPaneLayout());
positionNumericLabelTextFieldPair(volume, "Source to detector distance [mm]", sourceToDetectorField, 1, 1, 00);
positionNumericLabelTextFieldPair(volume, "Source to patient distance [mm]", sourceToPatientField, 3, 1, 00);
positionNumericLabelTextFieldPair(volume, "Projection stack size", projectionStackSizeField, 1, 1, 30);
positionNumericLabelTextFieldPair(volume, "Number of sweeps", numSweepsField, 3, 1, 30);
positionNumericLabelTextFieldPair(volume, "Rotation axis", rotationAxis, 1, 1, 60);
positionNumericLabelTextFieldPair(volume, "Average angular increment [deg]", averageAngularIncrement, 3, 1, 60);
positionNumericLabelTextFieldPair(volume, "Detector offset u [px]", detectorOffsetU, 1, 1, 90);
positionNumericLabelTextFieldPair(volume, "Detector offset v [px]", detectorOffsetV, 3, 1, 90);
int x = 1;
int y = 1;
int topOffset = 120;
int width = 3;
JLabel label = new JLabel("Detector u direction:");
volume.add(label, createConstraints(x, y, width, 1, GridBagConstraints.NORTHWEST, GridBagConstraints.NONE, topOffset + 3, 0, 0, 0));
volume.add(DetectorUDirection, createConstraints(x, y, width, 1, GridBagConstraints.NORTHWEST, GridBagConstraints.HORIZONTAL, topOffset, 170, 0, 0));
topOffset = 150;
JLabel label2 = new JLabel("Detector v direction:");
volume.add(label2, createConstraints(x, y, width, 1, GridBagConstraints.NORTHWEST, GridBagConstraints.NONE, topOffset + 3, 0, 0, 0));
volume.add(DetectorVDirection, createConstraints(x, y, width, 1, GridBagConstraints.NORTHWEST, GridBagConstraints.HORIZONTAL, topOffset, 170, 0, 0));
volume.add(jGenerateGeometry, createConstraints(1, 1, 3, 1, GridBagConstraints.NORTH, GridBagConstraints.NONE, 200, 0, 0, 0));
jGenerateGeometry.addActionListener(this);
return volume;
}
private JPanel trajectoryFromFile(){
JPanel volume = new JPanel();
volume.setBackground(Color.white);
volume.setLayout(createSubPaneLayout());
positionLabelTextFieldButton(volume, "Projection geometry source file:", projectionTableFileField, 1, 1, 3, 0, jParseGeometry);
jParseGeometry.addActionListener(this);
GUIUtil.enableDragAndDrop(projectionTableFileField);
return volume;
}
JTextField recentFileOneField = new JTextField();
JTextField recentFileTwoField = new JTextField();
ButtonGroup citationFormatGroup = new ButtonGroup();
JRadioButton bibButton = new JRadioButton("BibTeX");
JRadioButton medlineButton = new JRadioButton("Medline");
JCheckBox importFromDicom = new JCheckBox("Import geometry automatically from DICOM header");
JCheckBox extrapolateGeometry = new JCheckBox("Extraploate geometry if less than short-scan");
JCheckBox houns = new JCheckBox("Apply Hounsfield scaling");
private JPanel otherPane(){
JPanel volume = new JPanel();
volume.setBackground(Color.white);
volume.setLayout(createSubPaneLayout());
medlineButton.setBackground(Color.WHITE);
bibButton.setBackground(Color.WHITE);
JLabel citationLabel = new JLabel("Citation format:");
volume.add(citationLabel, createConstraints(1, 1, 1, 1, GridBagConstraints.NORTHWEST, GridBagConstraints.NONE, 10, 0, 0, 0));
volume.add(bibButton, createConstraints(3, 1, 1, 1, GridBagConstraints.NORTHWEST, GridBagConstraints.NONE, 3, 0, 0, 0));
volume.add(medlineButton, createConstraints(3, 1, 1, 1, GridBagConstraints.NORTHWEST, GridBagConstraints.NONE, 3, 120, 0, 0));
volume.add(importFromDicom, createConstraints(1, 1, 3, 1, GridBagConstraints.NORTH, GridBagConstraints.NONE, 50, 0, 0, 0));
volume.add(extrapolateGeometry, createConstraints(1, 1, 3, 1, GridBagConstraints.NORTH, GridBagConstraints.NONE, 80, 0, 0, 0));
volume.add(houns, createConstraints(1, 1, 3, 1, GridBagConstraints.NORTH, GridBagConstraints.NONE, 110, 0, 0, 0));
importFromDicom.setBackground(Color.WHITE);
extrapolateGeometry.setBackground(Color.WHITE);
houns.setBackground(Color.WHITE);
citationFormatGroup.add(bibButton);
citationFormatGroup.add(medlineButton);
positionLabelTextFieldPair(volume, "File for most preferred use:", recentFileOneField, 1, 1, 3, 160);
GUIUtil.enableDragAndDrop(recentFileOneField);
positionLabelTextFieldPair(volume, "Reference Volume:", recentFileTwoField, 1, 1, 3, 180);
GUIUtil.enableDragAndDrop(recentFileTwoField);
return volume;
}
/**
* Creates GridBagConstraints
* @param x location x
* @param y location y
* @param width width of the element
* @param height height of the element
* @param anchor anchor type
* @param fill fill type
* @param top top inset
* @param left left inset
* @param bottom bottom inset
* @param right right inset
* @return the GridBagConstraints
*/
static GridBagConstraints createConstraints(int x, int y, int width, int height, int anchor, int fill, int top, int left, int bottom, int right){
return new GridBagConstraints(x, y, width, height, 0.0, 0.0, anchor, fill, new Insets(top, left, bottom, right), 0, 0);
}
private void initGUI() {
try {
GridBagLayout thisLayout = new GridBagLayout();
thisLayout.rowWeights = new double[] {0.0, 0.1, 0.1, 0.0};
thisLayout.rowHeights = new int[] {15, 150, 150, 15};
thisLayout.columnWeights = new double[] {0.1, 0.1, 0.1, 0.1};
thisLayout.columnWidths = new int[] {15, 300, 300, 15};
setTitle("Configuration");
getContentPane().setLayout(thisLayout);
getContentPane().setBackground(Color.WHITE);
{
jTabbedPane = new JTabbedPane();
getContentPane().add(jTabbedPane, new GridBagConstraints(1, 1, 2, 2, 0.0, 0.0, GridBagConstraints.CENTER, GridBagConstraints.BOTH, new Insets(0, 0, 0, 0), 0, 0));
}
{
jSaveButton = new JButton();
getContentPane().add(jSaveButton, new GridBagConstraints(1, 3, 2, 1, 0.0, 0.0, GridBagConstraints.CENTER, GridBagConstraints.NONE, new Insets(0, 0, 0, 0), 0, 0));
jSaveButton.setText("save");
jSaveButton.addActionListener(this);
}
jTabbedPane.add("Volume", volumePane());
jTabbedPane.add("Detector", detectorPane());
jTabbedPane.add("Trajectory", trajectoryPane());
jTabbedPane.add("Other", otherPane());
jTabbedPane.add("Registry", regEditor);
pack();
} catch(Exception e) {
e.printStackTrace();
}
}
private class VoxelWorldFieldUpdater implements DocumentListener {
private JTextField world;
private JTextField voxel;
private JTextField spacing;
public VoxelWorldFieldUpdater (JTextField world, JTextField voxel, JTextField spacing) {
this.world = world;
this.voxel = voxel;
this.spacing = spacing;
}
public void changedUpdate(DocumentEvent e) {
updateDependentField();
}
public void insertUpdate(DocumentEvent e) {
updateDependentField();
}
public void removeUpdate(DocumentEvent e) {
updateDependentField();
}
private void updateDependentField(){
SwingUtilities.invokeLater(new Runnable() {
public void run() {
try{
double spacingDouble = Double.parseDouble(spacing.getText());
double worldDouble = Double.parseDouble(world.getText());
double voxelDouble = General.worldToVoxel(0.0, spacingDouble, worldDouble);
voxel.setText(new Double(voxelDouble).toString());
} catch (Exception e) {
System.out.println("Could not parse field. Will update as soon as valid number is available.");
}
}
});
}
}
}
/*
* Copyright (C) 2010-2014 - Andreas Maier
* CONRAD is developed as an Open Source project under the GNU General Public License (GPL).
*/