//----------------------------------------------------------------------------//
// //
// G l y p h T r a i n e r //
// //
//----------------------------------------------------------------------------//
// <editor-fold defaultstate="collapsed" desc="hdr"> //
// Copyright © Hervé Bitteur and others 2000-2013. All rights reserved. //
// This software is released under the GNU General Public License. //
// Goto http://kenai.com/projects/audiveris to report bugs or suggestions. //
//----------------------------------------------------------------------------//
// </editor-fold>
package omr.glyph.ui.panel;
import omr.constant.ConstantManager;
import omr.glyph.GlyphNetwork;
import omr.ui.MainGui;
import omr.ui.util.Panel;
import omr.ui.util.UILookAndFeel;
import com.jgoodies.forms.builder.PanelBuilder;
import com.jgoodies.forms.layout.CellConstraints;
import com.jgoodies.forms.layout.FormLayout;
import org.jdesktop.application.ResourceMap;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.util.Observable;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
/**
* Class {@code GlyphTrainer} handles a User Interface dedicated to the
* training and testing of a glyph evaluator.
* This class can be launched as a stand-alone program.
*
* <p>The frame is divided vertically in 4 parts:
* <ol>
* <li>The selection in repository of known glyphs ({@link SelectionPanel})
* <li>The training of the neural network evaluator ({@link TrainingPanel})
* <li>The validation of the neural network evaluator ({@link ValidationPanel})
* <li>The training of the linear evaluator ({@link RegressionPanel})
* </ol>
*
* @author Hervé Bitteur
*/
public class GlyphTrainer
{
//~ Static fields/initializers ---------------------------------------------
/** Usual logger utility */
private static final Logger logger = LoggerFactory.getLogger(
GlyphTrainer.class);
/** The single instance of this class */
private static volatile GlyphTrainer INSTANCE;
/** To differentiate the exit action, according to the launch context */
private static boolean standAlone = false;
/** Standard width for fields/buttons in DLUs */
private static final String standardWidth = "50dlu";
/** An adapter trigerred on window closing */
private static final WindowAdapter windowCloser = new WindowAdapter()
{
@Override
public void windowClosing (WindowEvent e)
{
// Store latest constant values
ConstantManager.getInstance()
.storeResource();
// That's all folks !
System.exit(0);
}
};
//~ Instance fields --------------------------------------------------------
/** Related frame */
private final JFrame frame;
/** Panel for selection in repository */
private final SelectionPanel selectionPanel;
/** Panel for Neural network training */
private final NetworkPanel networkPanel;
/** Panel for Neural network validation */
private final ValidationPanel validationPanel;
/** Panel for Regression training */
private final TrainingPanel regressionPanel;
/** Current task */
private final Task task = new Task();
/** Frame title */
private String frameTitle;
//~ Constructors -----------------------------------------------------------
//--------------//
// GlyphTrainer //
//--------------//
/**
* Create an instance of Glyph Trainer (there should be just one)
*/
private GlyphTrainer ()
{
if (standAlone) {
// UI Look and Feel
UILookAndFeel.setUI(null);
}
frame = new JFrame();
frame.setName("trainerFrame");
// Listener on remaining error
ChangeListener errorListener = new ChangeListener()
{
@Override
public void stateChanged (ChangeEvent e)
{
frame.setTitle(
String.format(
"%.5f - %s",
networkPanel.getBestError(),
frameTitle));
}
};
// Create the three companions
selectionPanel = new SelectionPanel(task, standardWidth);
networkPanel = new NetworkPanel(
task,
standardWidth,
errorListener,
selectionPanel);
selectionPanel.setTrainingPanel(networkPanel);
validationPanel = new ValidationPanel(
task,
standardWidth,
GlyphNetwork.getInstance(),
selectionPanel,
networkPanel);
regressionPanel = new RegressionPanel(
task,
standardWidth,
selectionPanel);
frame.add(createGlobalPanel());
// Initial state
task.setActivity(Task.Activity.INACTIVE);
// Specific ending if stand alone
if (standAlone) {
frame.addWindowListener(windowCloser);
}
// Resource injection
ResourceMap resource = MainGui.getInstance()
.getContext()
.getResourceMap(getClass());
resource.injectComponents(frame);
frameTitle = frame.getTitle();
}
//~ Methods ----------------------------------------------------------------
//--------//
// launch //
//--------//
/**
* (Re)activate the trainer tool
*/
public static void launch ()
{
MainGui.getInstance()
.show(getInstance().frame);
}
//------//
// main //
//------//
/**
* Just to allow stand-alone testing of this class
*
* @param args not used
*/
public static void main (String... args)
{
standAlone = true;
getInstance();
}
//-------------//
// getInstance //
//-------------//
private static GlyphTrainer getInstance ()
{
if (INSTANCE == null) {
INSTANCE = new GlyphTrainer();
}
return INSTANCE;
}
//-------------------//
// createGlobalPanel //
//-------------------//
private JPanel createGlobalPanel ()
{
final String panelInterline = Panel.getPanelInterline();
FormLayout layout = new FormLayout(
"pref",
"pref," + panelInterline + "," + "pref," + panelInterline + ","
+ "pref," + panelInterline + "," + "pref");
CellConstraints cst = new CellConstraints();
PanelBuilder builder = new PanelBuilder(layout, new Panel());
builder.setDefaultDialogBorder();
int r = 1; // --------------------------------
builder.add(selectionPanel.getComponent(), cst.xy(1, r));
r += 2; // --------------------------------
builder.add(networkPanel.getComponent(), cst.xy(1, r));
r += 2; // --------------------------------
builder.add(validationPanel.getComponent(), cst.xy(1, r));
r += 2; // --------------------------------
builder.add(regressionPanel.getComponent(), cst.xy(1, r));
return builder.getPanel();
}
//~ Inner Classes ----------------------------------------------------------
//------//
// Task //
//------//
/**
* Class {@code Task} handles which activity is currently being carried
* out, only one being current at any time.
*/
static class Task
extends Observable
{
//~ Enumerations -------------------------------------------------------
/**
* Enum {@code Activity} defines the possible activities in
* training.
*/
static enum Activity
{
//~ Enumeration constant initializers ------------------------------
/** No ongoing activity */
INACTIVE,
/** Selecting
* glyph to build a population for training */
SELECTING,
/** Using the
* population to train the evaluator */
TRAINING;
}
//~ Instance fields ----------------------------------------------------
/** Current activity */
private Activity activity = Activity.INACTIVE;
//~ Methods ------------------------------------------------------------
//-------------//
// getActivity //
//-------------//
/**
* Report the current training activity
*
* @return current activity
*/
public Activity getActivity ()
{
return activity;
}
//-------------//
// setActivity //
//-------------//
/**
* Assign a new current activity and notify all observers
*
* @param activity
*/
public void setActivity (Activity activity)
{
this.activity = activity;
setChanged();
notifyObservers();
}
}
}