package gdsc.smlm.ij.settings; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import com.thoughtworks.xstream.XStream; import com.thoughtworks.xstream.XStreamException; import com.thoughtworks.xstream.io.xml.DomDriver; /*----------------------------------------------------------------------------- * GDSC SMLM Software * * Copyright (C) 2013 Alex Herbert * Genome Damage and Stability Centre * University of Sussex, UK * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. *---------------------------------------------------------------------------*/ import gdsc.smlm.engine.FitEngineConfiguration; import gdsc.smlm.fitting.FitConfiguration; import ij.IJ; import ij.Prefs; /** * Manage the settings for the gdsc.fitting package */ public class SettingsManager { private static final String DEFAULT_FILENAME = System.getProperty("user.home") + System.getProperty("file.separator") + "gdsc.smlm.settings.xml"; private static XStream xs = null; /** * @return The settings filename (from the ImageJ preferences or the default in the home directory) */ public static String getSettingsFilename() { String filename = Prefs.get(Constants.settingsFilename, DEFAULT_FILENAME); return filename; } /** * Save settings filename. * * @param filename * the filename */ public static void saveSettingsFilename(String filename) { Prefs.set(Constants.settingsFilename, filename); } /** * Convert a list of objects into names (e.g. pass in (Object[])enum.getValues()). The first letter is capitalised. * The rest of the name is converted to lowercase if it is all uppercase. Remaining mixed case names are left * unchanged. * <p> * Used to convert the settings enumerations into names used with dialogs. * * @param objects * @return the names */ public static String[] getNames(Object... objects) { String[] names = new String[objects.length]; for (int i = 0; i < names.length; i++) { String name = objects[i].toString(); if (name.length() > 0) { // Capitalise first letter if (Character.isLowerCase(name.charAt(0))) name = Character.toUpperCase(name.charAt(0)) + name.substring(1); //// Check if all upper-case //boolean isUpper = true; //for (int j = 0; j < name.length(); j++) // if (Character.isLetter(name.charAt(j)) && !Character.isUpperCase(name.charAt(j))) // isUpper = false; // //if (isUpper) // Use sentence case // name = name.charAt(0) + name.substring(1).toLowerCase(); } names[i] = name; } return names; } /** * Save the configuration to file * * @param config * @param filename * @return True if saved */ public static boolean saveFitEngineConfiguration(FitEngineConfiguration config, String filename) { XStream xs = createXStream(); FileOutputStream fs = null; try { fs = new FileOutputStream(filename); xs.toXML(config, fs); return true; } catch (FileNotFoundException ex) { //ex.printStackTrace(); } catch (XStreamException ex) { ex.printStackTrace(); } finally { if (fs != null) { try { fs.close(); } catch (IOException e) { e.printStackTrace(); } } } return false; } private static XStream createXStream() { if (xs == null) { xs = new XStream(new DomDriver()); // Map the object names/fields for a nicer configuration file xs.alias("gdsc.fitting.settings", GlobalSettings.class); xs.alias("gdsc.fitting.configuration", FitEngineConfiguration.class); xs.aliasField("gdsc.fitting.configuration", GlobalSettings.class, "fitEngineConfiguration"); xs.aliasField("peakParameters", FitEngineConfiguration.class, "fitConfiguration"); xs.aliasField("smoothing", FitEngineConfiguration.class, "smooth"); //xs.aliasField("width0", FitConfiguration.class, "initialPeakWidth0"); //xs.aliasField("width1", FitConfiguration.class, "initialPeakWidth1"); //xs.aliasField("angle", FitConfiguration.class, "initialAngle"); xs.aliasField("enableValidation", FitConfiguration.class, "fitValidation"); xs.omitField(FitConfiguration.class, "flags"); xs.omitField(FitConfiguration.class, "signalThreshold"); //xs.omitField(FitConfiguration.class, "noise"); xs.omitField(FitConfiguration.class, "enableValidation"); xs.omitField(FitConfiguration.class, "computeResiduals"); // Smart filter settings xs.omitField(FitConfiguration.class, "directFilter"); xs.omitField(FitConfiguration.class, "dynamicPeakResult"); xs.omitField(FitConfiguration.class, "filterResult"); xs.omitField(FitConfiguration.class, "widthEnabled"); xs.omitField(FitConfiguration.class, "offset"); } return xs; } /** * Load the configuration within the specified file * * @param filename * @return The configuration (or null) */ public static FitEngineConfiguration unsafeLoadFitEngineConfiguration(String filename) { XStream xs = createXStream(); FitEngineConfiguration config = null; FileInputStream fs = null; try { fs = new FileInputStream(filename); config = (FitEngineConfiguration) xs.fromXML(fs); } catch (ClassCastException ex) { //ex.printStackTrace(); } catch (FileNotFoundException ex) { //ex.printStackTrace(); } catch (XStreamException ex) { ex.printStackTrace(); } finally { if (fs != null) { try { fs.close(); } catch (IOException e) { e.printStackTrace(); } } } return config; } /** * Load the configuration within the specified file * * @param filename * @return The configuration (or a default instance) */ public static FitEngineConfiguration loadFitEngineConfiguration(String filename) { FitEngineConfiguration config = unsafeLoadFitEngineConfiguration(filename); if (config == null) config = new FitEngineConfiguration(new FitConfiguration()); return config; } /** * Save the settings to file. * <p> * If this fails then an error message is written to the ImageJ log * * @param settings * the settings * @param filename * the filename * @return True if saved */ public static boolean saveSettings(GlobalSettings settings, String filename) { return saveSettings(settings, filename, false); } /** * Save the settings to file. * <p> * If this fails then an error message is written to the ImageJ log * * @param settings * the settings * @param filename * the filename * @param silent * Set to true to suppress writing an error message to the ImageJ log * @return True if saved */ public static boolean saveSettings(GlobalSettings settings, String filename, boolean silent) { XStream xs = createXStream(); FileOutputStream fs = null; try { fs = new FileOutputStream(filename); xs.toXML(settings, fs); return true; } catch (FileNotFoundException ex) { //ex.printStackTrace(); } catch (XStreamException ex) { ex.printStackTrace(); } finally { if (fs != null) { try { fs.close(); } catch (IOException e) { e.printStackTrace(); } } } if (!silent) IJ.log("Unable to save settings to: " + filename); return false; } /** * Save the settings to the default file. * <p> * If this fails then an error message is written to the ImageJ log * * @param settings * the settings * @return True if saved */ public static boolean saveSettings(GlobalSettings settings) { return saveSettings(settings, getSettingsFilename(), false); } /** * Load the settings within the specified file * <p> * If this fails then an error message is written to the ImageJ log * * @param filename * @param silent * Set to true to suppress writing an error message to the ImageJ log * @return The settings (or null) */ public static GlobalSettings unsafeLoadSettings(String filename, boolean silent) { XStream xs = createXStream(); GlobalSettings config = null; FileInputStream fs = null; try { fs = new FileInputStream(filename); config = (GlobalSettings) xs.fromXML(fs); } catch (ClassCastException ex) { //ex.printStackTrace(); } catch (FileNotFoundException ex) { //ex.printStackTrace(); } catch (XStreamException ex) { ex.printStackTrace(); } finally { if (fs != null) { try { fs.close(); } catch (IOException e) { e.printStackTrace(); } } } if (config == null) if (!silent) IJ.log("Unable to load settings from: " + filename); return config; } /** * Load the settings from the input stream. The stream will be closed. * <p> * If this fails then an error message is written to the ImageJ log * * @param inputStream * the input stream * @param silent * Set to true to suppress writing an error message to the ImageJ log * @return The settings (or null) */ public static GlobalSettings unsafeLoadSettings(InputStream inputStream, boolean silent) { XStream xs = createXStream(); GlobalSettings config = null; try { config = (GlobalSettings) xs.fromXML(inputStream); } catch (ClassCastException ex) { //ex.printStackTrace(); } catch (XStreamException ex) { ex.printStackTrace(); } finally { try { inputStream.close(); } catch (IOException e) { e.printStackTrace(); } } if (config == null) if (!silent) IJ.log("Unable to load settings from input stream"); return config; } /** * Load the settings within the specified file * <p> * If this fails then an error message is written to the ImageJ log * * @param filename * @return The settings (or a default instance) */ public static GlobalSettings loadSettings(String filename) { return loadSettings(filename, false); } /** * Load the settings within the specified file * <p> * If this fails then an error message is written to the ImageJ log * * @param filename * @param silent * Set to true to suppress writing an error message to the ImageJ log * @return The settings (or a default instance) */ public static GlobalSettings loadSettings(String filename, boolean silent) { GlobalSettings config = unsafeLoadSettings(filename, silent); if (config == null) { config = new GlobalSettings(); } else { config.getFitEngineConfiguration().initialiseState(); config.getCreateDataSettings().initialiseState(); config.getResultsSettings().initialiseState(); } return config; } /** * Load the settings from the default file * <p> * If this fails then an error message is written to the ImageJ log * * @return The settings (or a default instance) */ public static GlobalSettings loadSettings() { return loadSettings(getSettingsFilename(), false); } }