From 90eeb8f46fd737a8da4ee980133e76df572769de Mon Sep 17 00:00:00 2001 From: baseendje Date: Wed, 10 Jun 2020 19:14:57 +0200 Subject: [PATCH 01/67] Loading post-processing scripts part 1 --- src/dataIO/CumulativeLoad.java | 49 ++ src/dataIO/FolderOperations.java | 94 +++ src/gui/GuiActions.java | 521 +++++++++------ src/gui/GuiMenu.java | 1065 +++++++++++++++--------------- src/idynomics/Idynomics.java | 19 + src/idynomics/PostProcess.java | 32 + src/utility/Helper.java | 8 + 7 files changed, 1056 insertions(+), 732 deletions(-) create mode 100644 src/dataIO/CumulativeLoad.java create mode 100644 src/dataIO/FolderOperations.java create mode 100644 src/idynomics/PostProcess.java diff --git a/src/dataIO/CumulativeLoad.java b/src/dataIO/CumulativeLoad.java new file mode 100644 index 000000000..3a5b6f550 --- /dev/null +++ b/src/dataIO/CumulativeLoad.java @@ -0,0 +1,49 @@ +package dataIO; + +import org.w3c.dom.Element; + +import compartment.Compartment; +import idynomics.Idynomics; +import instantiable.Instance; +import processManager.ProcessManager; +import referenceLibrary.XmlRef; +import utility.Helper; + +public class CumulativeLoad { + + Element document; + + public CumulativeLoad() + { + + } + + public CumulativeLoad(String xml) + { + document = XmlHandler.loadDocument(xml); + } + + public void postProcess() + { + Compartment comp = null; + for ( Element e : XmlHandler.getElements( document, XmlRef.process) ) + { + comp.addProcessManager( + (ProcessManager) Instance.getNew(e, comp, (String[])null)); + } + } + + public Compartment getCompartment(String comp) + { + if( Idynomics.simulator.getCompartmentNames().contains(comp)) + return Idynomics.simulator.getCompartment(comp); + if( Helper.intParseable(comp) ) + return Idynomics.simulator.getCompartment( + Idynomics.simulator.getCompartmentNames().get( + Integer.valueOf(comp) ) ); + Log.out(this.getClass().getSimpleName() + " could not retrieve " + + "compartment: " + comp); + return null; + + } +} diff --git a/src/dataIO/FolderOperations.java b/src/dataIO/FolderOperations.java new file mode 100644 index 000000000..26b28603a --- /dev/null +++ b/src/dataIO/FolderOperations.java @@ -0,0 +1,94 @@ +package dataIO; + +import java.io.File; +import java.util.LinkedList; +import java.util.List; + +public class FolderOperations { + + public static final String[] extensions = new String[] { "exi", "xml" }; + + /** + * \brief Check whether passed files contain at least 1 folder + * @param files + * @return + */ + public static boolean includesfolders( File ... files ) + { + for( File f : files ) + if ( f.isDirectory() ) + return true; + return false; + } + + /** + * \brief return all files from passed file and folder list but do not + * include sub-folders + * + * @param subfolders + * @param files + * @return + */ + public static List getFiles( File ... files ) + { + LinkedList out = new LinkedList(); + for( File f : files ) + { + if ( f.isFile() ) + out.add( f ); + else + for (File fileEntry : f.listFiles()) + out.addAll( getFiles( false, fileEntry ) ); + } + return out; + } + + /** + * \brief return all files and optionally all files in all sub-folders + * @param subfolders + * @param files + * @return + */ + public static List getFiles( boolean subfolders, File ... files ) + { + LinkedList out = new LinkedList(); + for( File f : files ) + { + if ( f.isFile() ) + out.add( f ); + else if ( subfolders ) + for (File fileEntry : f.listFiles()) + out.addAll( getFiles( subfolders, fileEntry ) ); + } + return out; + } + + /** + * \brief filter all files with common iDynoMiCS extensions + * @param files + * @return + */ + public static List filterFiles( File ... files ) + { + return filterFiles( extensions, files); + } + + /** + * \brief filter all files with given extensions + * @param extension + * @param files + * @return + */ + public static List filterFiles( String[] extension, File ... files ) + { + LinkedList out = new LinkedList(); + for( File file : files ) + for( String s : extension ) + if( file.getName().toLowerCase().contains( s ) ) + { + out.add( file ); + break; + } + return out; + } +} diff --git a/src/gui/GuiActions.java b/src/gui/GuiActions.java index 9ba9ec510..f3af2bead 100644 --- a/src/gui/GuiActions.java +++ b/src/gui/GuiActions.java @@ -1,211 +1,310 @@ -/** - * - */ -package gui; - -import java.awt.EventQueue; -import java.io.File; -import java.io.FileNotFoundException; -import java.io.FileOutputStream; -import java.io.IOException; -import java.io.InputStream; -import java.net.MalformedURLException; -import java.net.URL; - -import javax.swing.JFileChooser; -import javax.swing.JFrame; -import javax.swing.JOptionPane; - -import dataIO.FileHandler; -import dataIO.Log; -import idynomics.Global; -import idynomics.Idynomics; -import idynomics.Simulator; -import render.AgentMediator; -import render.Render; -import utility.Helper; - -/** - * - * - * @author Robert Clegg (r.j.clegg@bham.ac.uk) University of Birmingham, U.K. - * @author Bastiaan Cockx @BastiaanCockx (baco@env.dtu.dk), DTU, Denmark - */ -public final class GuiActions -{ - - /************************************************************************* - * DEALING WITH FILES - ************************************************************************/ - - /** - * \brief Method to select protocol files from a file selection dialog - * - * @return XML file selected from the dialog box. - */ - public static void chooseFile() - { - /* Open a FileChooser window in the current directory. */ - JFileChooser chooser = new JFileChooser("" + - System.getProperty("user.dir")+"/protocol"); - chooser.setFileSelectionMode(JFileChooser.FILES_ONLY); - // TODO Allow the user to select multiple files. - chooser.setMultiSelectionEnabled(false); - File f = null; - if ( chooser.showOpenDialog(null) == JFileChooser.APPROVE_OPTION ) - f = chooser.getSelectedFile(); - - openFile(f); - } - - public static void openFile(File f) - { - Idynomics.simulator = new Simulator(); - Idynomics.global = new Global(); - /* load content if a protocol file has been selected */ - if ( f == null ) - { - Idynomics.global.protocolFile = null; - GuiConsole.writeOut("No protocol file selected.\n"); - } - else - { - Idynomics.global.protocolFile = f.getAbsolutePath(); - GuiConsole.writeOut(Idynomics.global.protocolFile + " \n"); - checkProtocol(); - GuiButtons.resetProgressBar(); - GuiActions.loadCurrentState(); - GuiMain.setStatus( Idynomics.global.protocolFile ); - } - } - - public static String inputUrl() - { - JFrame f; - f=new JFrame(); - return JOptionPane.showInputDialog(f,"Enter URL"); - } - - public static void downloadFile(String url) - { - String local = "tmp_dl.xml"; - FileHandler handler = new FileHandler(); - - if (url == null) - url = inputUrl(); - - Log.out("Downloading file: " + url + " -> " + local ); - handler.fnew(local); - InputStream webIS = null; - FileOutputStream fo = null; - URL urly = null; - - try { - urly = new URL(url); - } catch ( MalformedURLException e) { - e.printStackTrace(); - } - - - try { - webIS = urly.openStream(); - int c = 0; - do { - c = webIS.read(); - if (c !=-1) { - handler.write((byte) c); - } - } while(c != -1); - webIS.close(); - handler.fclose(); - Log.out("finished Download"); - } catch (IOException e) { - e.printStackTrace(); - } - File in = new File(local); - openFile(in); - } - - public static void checkProtocol() - { - if ( Idynomics.global.protocolFile == null ) - { - GuiConsole.writeErr("No protocol file specified.\n"); - } - else - { - Idynomics.setupSimulator(Idynomics.global.protocolFile); - if ( Idynomics.simulator.isReadyForLaunch() ) - GuiConsole.writeOut("Protocol is ready to launch...\n"); - else - GuiConsole.writeErr("Problem in protocol file!\n"); - } - } - - public static void loadCurrentState() - { - GuiMain.update(); - } - - /************************************************************************* - * SIMULATION CONTROL - ************************************************************************/ - - public static void runSimulation() - { - GuiEditor.setAttributes(); - if ( Idynomics.simulator == null ) - Log.printToScreen( "no simulation set.", true); - else - { - Idynomics.simulator.setNode(); - GuiButtons.resetProgressBar(); - Idynomics.launchSimulator(); - } - } - - public static void pauseSimulation() - { - if ( Idynomics.simulator == null ) - return; - try - { - // TODO This doesn't work yet... - Idynomics.simulator.wait(); - } - catch (InterruptedException e) - { - // TODO Auto-generated catch block - e.printStackTrace(); - } - } - - public static void stopSimulation() - { - if ( Idynomics.simulator == null ) - return; - // TODO this can probably be made a lot cleaner! - Idynomics.simulator.timer.setEndOfSimulation( - Idynomics.simulator.timer.getEndOfCurrentIteration()); - } - - /************************************************************************* - * RENDERING 3D SCENE - ************************************************************************/ - - public static void render() - { - /* is the simulator set? */ - if ( Idynomics.simulator == null ) - Log.printToScreen("No simulator available.", false); - else if ( Helper.selectSpatialCompartment() == null ) - Log.printToScreen("No spatial compartment available.", false); - else - { - /* create and invoke the renderer */ - Render myRender = new Render( - new AgentMediator( Helper.selectSpatialCompartment() ) ); - EventQueue.invokeLater(myRender); - } - } -} +/** + * + */ +package gui; + +import java.awt.EventQueue; +import java.io.File; +import java.io.FileNotFoundException; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.net.MalformedURLException; +import java.net.URL; +import java.util.List; + +import javax.swing.JFileChooser; +import javax.swing.JFrame; +import javax.swing.JOptionPane; + +import dataIO.FileHandler; +import dataIO.FolderOperations; +import dataIO.Log; +import idynomics.Global; +import idynomics.Idynomics; +import idynomics.PostProcess; +import idynomics.Simulator; +import render.AgentMediator; +import render.Render; +import utility.Helper; + +/** + * + * + * @author Robert Clegg (r.j.clegg@bham.ac.uk) University of Birmingham, U.K. + * @author Bastiaan Cockx @BastiaanCockx (baco@env.dtu.dk), DTU, Denmark + */ +public final class GuiActions +{ + + /************************************************************************* + * DEALING WITH FILES + ************************************************************************/ + + /** + * \brief Method to select protocol files from a file selection dialog + * + * @return XML file selected from the dialog box. + */ + public static void chooseFile() + { + /* Open a FileChooser window in the current directory. */ + JFileChooser chooser = new JFileChooser("" + + System.getProperty("user.dir")+"/protocol"); + chooser.setFileSelectionMode(JFileChooser.FILES_ONLY); + // TODO Allow the user to select multiple files. + chooser.setMultiSelectionEnabled(false); + File f = null; + if ( chooser.showOpenDialog(null) == JFileChooser.APPROVE_OPTION ) + f = chooser.getSelectedFile(); + + openFile(f); + } + + public static File chooseFile(String relPath, String description) + { + /* Open a FileChooser window in the current directory. */ + JFileChooser chooser = new JFileChooser("" + + System.getProperty("user.dir")+"/protocol"); + chooser.setFileSelectionMode(JFileChooser.FILES_ONLY); + // TODO Allow the user to select multiple files. + chooser.setMultiSelectionEnabled(false); + chooser.setToolTipText(description); + chooser.setDialogTitle(description); + File f = null; + if ( chooser.showOpenDialog(null) == JFileChooser.APPROVE_OPTION ) + f = chooser.getSelectedFile(); + return f; + } + + public static File chooseFolder(String description) + { + /* Open a FileChooser window in the current directory. */ + JFileChooser chooser = new JFileChooser("" + + System.getProperty("user.dir")); + chooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY); + // TODO Allow the user to select multiple files. + chooser.setMultiSelectionEnabled(false); + chooser.setToolTipText(description); + chooser.setDialogTitle(description); + File f = null; + if ( chooser.showOpenDialog(null) == JFileChooser.APPROVE_OPTION ) + f = chooser.getSelectedFile(); + return f; + } + + public static File[] chooseMulitple(String description) + { + /* Open a FileChooser window in the current directory. */ + JFileChooser chooser = new JFileChooser("" + + System.getProperty("user.dir")); + chooser.setFileSelectionMode(JFileChooser.FILES_ONLY); + // TODO Allow the user to select multiple files. + chooser.setMultiSelectionEnabled(true); + chooser.setToolTipText(description); + chooser.setDialogTitle(description); + File[] f = null; + if ( chooser.showOpenDialog(null) == JFileChooser.APPROVE_OPTION ) + f = chooser.getSelectedFiles(); + return f; + } + + public static File[] chooseFilesAndFolders(String description) + { + /* Open a FileChooser window in the current directory. */ + JFileChooser chooser = new JFileChooser("" + + System.getProperty("user.dir")); + chooser.setFileSelectionMode(JFileChooser.FILES_AND_DIRECTORIES); + // TODO Allow the user to select multiple files. + chooser.setMultiSelectionEnabled(true); + chooser.setToolTipText(description); + chooser.setDialogTitle(description); + File[] f = null; + if ( chooser.showOpenDialog(null) == JFileChooser.APPROVE_OPTION ) + f = chooser.getSelectedFiles(); + return f; + } + + public static void postProcess() + { + File script = chooseFile( "postprocessing", + "Select post-processing script" ); + File[] files = chooseFilesAndFolders( + "Select simulation state files (.exi or .xml)" ); + List finalFiles = null; + if( FolderOperations.includesfolders(files)) + { + if( Helper.obtainInput( + "Would you like to include sub-folders?", false) ) + /* note do look into the first line of folders */ + finalFiles = FolderOperations.getFiles(true, files); + else + finalFiles = FolderOperations.getFiles(files); + } + else + { + finalFiles = FolderOperations.getFiles(true, files); + } + if( Helper.obtainInput( "Would you like to continue processing " + + finalFiles.size() + " files?", false) ) + { + Idynomics.postProcess = new PostProcess(script, finalFiles); + Idynomics.runPostProcess(); + } + else + { + Log.out("post-processing cancelled by user"); + } + } + + public static void openFile(File f) + { + Idynomics.simulator = new Simulator(); + Idynomics.global = new Global(); + /* load content if a protocol file has been selected */ + if ( f == null ) + { + Idynomics.global.protocolFile = null; + GuiConsole.writeOut("No protocol file selected.\n"); + } + else + { + Idynomics.global.protocolFile = f.getAbsolutePath(); + GuiConsole.writeOut(Idynomics.global.protocolFile + " \n"); + checkProtocol(); + GuiButtons.resetProgressBar(); + GuiActions.loadCurrentState(); + GuiMain.setStatus( Idynomics.global.protocolFile ); + } + } + + public static String inputUrl() + { + JFrame f; + f=new JFrame(); + return JOptionPane.showInputDialog(f,"Enter URL"); + } + + public static void downloadFile(String url) + { + String local = "tmp_dl.xml"; + FileHandler handler = new FileHandler(); + + if (url == null) + url = inputUrl(); + + Log.out("Downloading file: " + url + " -> " + local ); + handler.fnew(local); + InputStream webIS = null; + FileOutputStream fo = null; + URL urly = null; + + try { + urly = new URL(url); + } catch ( MalformedURLException e) { + e.printStackTrace(); + } + + + try { + webIS = urly.openStream(); + int c = 0; + do { + c = webIS.read(); + if (c !=-1) { + handler.write((byte) c); + } + } while(c != -1); + webIS.close(); + handler.fclose(); + Log.out("finished Download"); + } catch (IOException e) { + e.printStackTrace(); + } + File in = new File(local); + openFile(in); + } + + public static void checkProtocol() + { + if ( Idynomics.global.protocolFile == null ) + { + GuiConsole.writeErr("No protocol file specified.\n"); + } + else + { + Idynomics.setupSimulator(Idynomics.global.protocolFile); + if ( Idynomics.simulator.isReadyForLaunch() ) + GuiConsole.writeOut("Protocol loaded successfully.\n"); + else + GuiConsole.writeErr("Problem in protocol file!\n"); + } + } + + public static void loadCurrentState() + { + GuiMain.update(); + } + + /************************************************************************* + * SIMULATION CONTROL + ************************************************************************/ + + public static void runSimulation() + { + GuiEditor.setAttributes(); + if ( Idynomics.simulator == null ) + Log.printToScreen( "no simulation set.", true); + else + { + Idynomics.simulator.setNode(); + GuiButtons.resetProgressBar(); + Idynomics.launchSimulator(); + } + } + + public static void pauseSimulation() + { + if ( Idynomics.simulator == null ) + return; + try + { + // TODO This doesn't work yet... + Idynomics.simulator.wait(); + } + catch (InterruptedException e) + { + // TODO Auto-generated catch block + e.printStackTrace(); + } + } + + public static void stopSimulation() + { + if ( Idynomics.simulator == null ) + return; + // TODO this can probably be made a lot cleaner! + Idynomics.simulator.timer.setEndOfSimulation( + Idynomics.simulator.timer.getEndOfCurrentIteration()); + } + + /************************************************************************* + * RENDERING 3D SCENE + ************************************************************************/ + + public static void render() + { + /* is the simulator set? */ + if ( Idynomics.simulator == null ) + Log.printToScreen("No simulator available.", false); + else if ( Helper.selectSpatialCompartment() == null ) + Log.printToScreen("No spatial compartment available.", false); + else + { + /* create and invoke the renderer */ + Render myRender = new Render( + new AgentMediator( Helper.selectSpatialCompartment() ) ); + EventQueue.invokeLater(myRender); + } + } +} diff --git a/src/gui/GuiMenu.java b/src/gui/GuiMenu.java index f2b87c255..6ba2c1b04 100644 --- a/src/gui/GuiMenu.java +++ b/src/gui/GuiMenu.java @@ -1,521 +1,544 @@ -/** - * - */ -package gui; - -import java.awt.event.ActionEvent; -import java.awt.event.KeyEvent; - -import javax.swing.AbstractAction; -import javax.swing.JMenu; -import javax.swing.JMenuBar; -import javax.swing.JMenuItem; -import javax.swing.JRadioButtonMenuItem; -import javax.swing.KeyStroke; - -import analysis.FilteredTable; -import analysis.quantitative.Raster; -import dataIO.Diagram; -import dataIO.DrawMediator; -import dataIO.Log; -import dataIO.Log.Tier; -import idynomics.Idynomics; -import idynomics.Simulator; -import idynomics.launchable.SamplerLaunch; -import utility.Helper; - -/** - * - * @author Bastiaan Cockx @BastiaanCockx (baco@env.dtu.dk), DTU, Denmark - * @author Robert Clegg (r.j.clegg@bham.ac.uk) University of Birmingham, U.K. - */ -public final class GuiMenu -{ - private static JMenuBar _menuBar; - - public static JMenuBar getMenuBar() - { - _menuBar = new JMenuBar(); - _menuBar.add(fileMenu()); - _menuBar.add(interactionMenu()); - return _menuBar; - } - - - private static JMenu fileMenu() - { - JMenu menu, levelMenu; - JMenuItem menuItem; - JRadioButtonMenuItem rbMenuItem; - /* - * Set up the File menu. - */ - menu = new JMenu("File"); - menu.setMnemonic(KeyEvent.VK_F); - menu.getAccessibleContext().setAccessibleDescription("File options"); - /* - * Add the option of making a new simulation. - */ - menuItem = new JMenuItem(new GuiMenu.NewFile()); - menuItem.setAccelerator(KeyStroke.getKeyStroke( - KeyEvent.VK_N, ActionEvent.CTRL_MASK)); - menuItem.getAccessibleContext().setAccessibleDescription( - "Make a new simulation"); - menu.add(menuItem); - /* - * Add the option of opening a protocol file. - */ - menuItem = new JMenuItem(new GuiMenu.FileOpen()); - menuItem.setAccelerator(KeyStroke.getKeyStroke( - KeyEvent.VK_O, ActionEvent.CTRL_MASK)); - menuItem.getAccessibleContext().setAccessibleDescription( - "Open existing protocol file"); - menu.add(menuItem); - - - menuItem = new JMenuItem(new GuiMenu.FileDownload()); - menuItem.setAccelerator(KeyStroke.getKeyStroke( - KeyEvent.VK_D, ActionEvent.CTRL_MASK)); - menuItem.getAccessibleContext().setAccessibleDescription( - "Download protocol file"); - menu.add(menuItem); - - /* - * Add the option of rendering a compartment. - */ - menuItem = new JMenuItem(new GuiMenu.RenderThis()); - menuItem.setAccelerator(KeyStroke.getKeyStroke( - KeyEvent.VK_R, ActionEvent.CTRL_MASK)); - menuItem.getAccessibleContext().setAccessibleDescription( - "Render a spatial compartment"); - menu.add(menuItem); - /* - * Output level. - * NOTE this will not work through the menu bar, instead edit trough - * simulation state. - menu.addSeparator(); - levelMenu = new JMenu("OutputLevel"); - levelMenu.setMnemonic(KeyEvent.VK_L); - ButtonGroup group = new ButtonGroup(); - for ( Log.Tier t : Log.Tier.values() ) - { - rbMenuItem = new JRadioButtonMenuItem(new GuiMenu.LogTier(t)); - group.add(rbMenuItem); - levelMenu.add(rbMenuItem); - } - menu.add(levelMenu); - */ - - /* - * Master protocol sampling - */ - menu.addSeparator(); - menuItem = new JMenuItem(new GuiMenu.Sampling()); - menuItem.getAccessibleContext().setAccessibleDescription( - "Sample master protocol file"); - menu.add(menuItem); - - /* - * Finally, return the File menu. - */ - return menu; - } - - - private static JMenu interactionMenu() - { - JMenu menu; - JMenuItem menuItem; - /* - * Set up the File menu. - */ - menu = new JMenu("Interact"); - menu.setMnemonic(KeyEvent.VK_G); - menu.getAccessibleContext().setAccessibleDescription("Interactive"); - /* - * Add the option of rendering a compartment. - */ - menuItem = new JMenuItem(new GuiMenu.Current()); - menuItem.setAccelerator(KeyStroke.getKeyStroke( - KeyEvent.VK_L, ActionEvent.CTRL_MASK)); - menuItem.getAccessibleContext().setAccessibleDescription( - "Edit simulation state"); - menu.add(menuItem); - /* - * Draw to graphics file - */ - menuItem = new JMenuItem(new GuiMenu.Draw()); - menuItem.setAccelerator(KeyStroke.getKeyStroke( - KeyEvent.VK_D, ActionEvent.CTRL_MASK)); - menuItem.getAccessibleContext().setAccessibleDescription( - "Draw to file"); - menu.add(menuItem); - /* - * Draw raster - */ - menuItem = new JMenuItem(new GuiMenu.StructureAnalysis()); - menuItem.getAccessibleContext().setAccessibleDescription( - "Draw raster to file"); - menu.add(menuItem); - /* - * Draw species diagram - */ - menuItem = new JMenuItem(new GuiMenu.SpeciesDiagram()); - menuItem.setAccelerator(KeyStroke.getKeyStroke( - KeyEvent.VK_D, ActionEvent.CTRL_MASK)); - menuItem.getAccessibleContext().setAccessibleDescription( - "Request agent information"); - menu.add(menuItem); - /* - * Draw reaction diagram - */ - menuItem = new JMenuItem(new ReactionDiagram()); - menuItem.setAccelerator(KeyStroke.getKeyStroke( - KeyEvent.VK_D, ActionEvent.CTRL_MASK)); - menuItem.getAccessibleContext().setAccessibleDescription( - "Request agent information"); - menu.add(menuItem); - /* - * Query some agents - */ - menuItem = new JMenuItem(new GuiMenu.Query()); - menuItem.setAccelerator(KeyStroke.getKeyStroke( - KeyEvent.VK_T, ActionEvent.CTRL_MASK)); - menuItem.getAccessibleContext().setAccessibleDescription( - "Request agent information"); - menu.add(menuItem); - /* - * Query some agents - */ - menuItem = new JMenuItem(new GuiMenu.QueryToFile()); - menuItem.setAccelerator(KeyStroke.getKeyStroke( - KeyEvent.VK_Y, ActionEvent.CTRL_MASK)); - menuItem.getAccessibleContext().setAccessibleDescription( - "Request agent information and store in output folder"); - menu.add(menuItem); - /* - * Finally, return the File menu. - */ - return menu; - } - - /************************************************************************* - * - ************************************************************************/ - - public static class NewFile extends AbstractAction - { - private static final long serialVersionUID = 8931286266304166474L; - - /** - * Action for the file open sub-menu. - */ - public NewFile() - { - super("Make new protocol"); - } - - public void actionPerformed(ActionEvent e) - { - Idynomics.simulator = new Simulator(); - GuiActions.loadCurrentState(); - } - } - - public static class FileOpen extends AbstractAction - { - private static final long serialVersionUID = 2247122248926681550L; - - /** - * Action for the file open sub-menu. - */ - public FileOpen() - { - super("Open.."); - } - - public void actionPerformed(ActionEvent e) - { - GuiActions.chooseFile(); - } - } - - public static class FileDownload extends AbstractAction - { - private static final long serialVersionUID = 2247122248926681550L; - - /** - * Action for the file open sub-menu. - */ - public FileDownload() - { - super("Download.."); - } - - public void actionPerformed(ActionEvent e) - { - GuiActions.downloadFile(null); - } - } - - public static class RenderThis extends AbstractAction - { - private static final long serialVersionUID = 974971035938028563L; - - /** - * Create a new {@code Render} object and invoke it. - * - *

The {@code Render} object handles its own {@code JFrame}.

- */ - public RenderThis() - { - super("Render"); - } - - public void actionPerformed(ActionEvent e) - { - GuiActions.render(); - } - } - - public static class SpeciesDiagram extends AbstractAction - { - - /** - * - */ - private static final long serialVersionUID = 3011117385035501302L; - - public SpeciesDiagram() - { - super("Species Diagram"); - } - - @Override - public void actionPerformed(ActionEvent e) { - if (Helper.compartmentAvailable()) - { - String fileName = "speciesDiagram"; - Diagram diag = new Diagram(); - diag.createCustomFile(fileName); - diag.speciesDiagram(); - diag.closeFile(); - Log.printToScreen("species diagram created.", false); - } - } - - } - - public static class ReactionDiagram extends AbstractAction - { - - /** - * - */ - private static final long serialVersionUID = 3011117385035501302L; - - public ReactionDiagram() - { - super("Reaction Diagram"); - } - - @Override - public void actionPerformed(ActionEvent e) { - if (Helper.compartmentAvailable()) - { - String fileName = "reactionDiagram"; - Diagram diag = new Diagram(); - diag.createCustomFile(fileName); - diag.reactionDiagram( Helper.selectCompartment() ); - diag.closeFile(); - Log.printToScreen("reaction diagram created.", false); - } - } - - } - - public static class Query extends AbstractAction - { - - /** - * - */ - private static final long serialVersionUID = 3011117385035501302L; - - public Query() - { - super("Query"); - } - - @Override - public void actionPerformed(ActionEvent e) { - if (Helper.compartmentAvailable()) - { - String table = GuiConsole.requestInput("Table logic"); - table = table.replaceAll("\\s+",""); - FilteredTable tab = new FilteredTable(table); - Log.printToScreen(tab.display(), false); - } - } - - } - - public static class QueryToFile extends AbstractAction - { - - /** - * - */ - private static final long serialVersionUID = 3011117385035501302L; - - public QueryToFile() - { - super("QueryToFile"); - } - - @Override - public void actionPerformed(ActionEvent e) { - if (Helper.compartmentAvailable()) - { - String table = GuiConsole.requestInput("Table logic"); - table = table.replaceAll("\\s+",""); - FilteredTable tab = new FilteredTable(table); - tab.toFile(); - } - } - - } - - public static class StructureAnalysis extends AbstractAction - { - - /** - * - */ - private static final long serialVersionUID = 3011117385035501302L; - - public StructureAnalysis() - { - super("StructureAnalysis"); - } - - @Override - public void actionPerformed(ActionEvent e) { - if (Helper.compartmentAvailable()) - { - if ( Helper.selectSpatialCompartment() == null ) - Log.printToScreen("No spatial compartment available.", - false ); - { - Raster raster = new Raster( - Helper.selectSpatialCompartment(), true ); - raster.rasterize( Double.valueOf( - Helper.obtainInput( null, "Raster scale" ) ) ); - raster.plot( raster.agentMap(), 1.0, - Helper.obtainInput( null, "filename") ); - } - } - } - - } - - public static class Draw extends AbstractAction - { - - /** - * - */ - private static final long serialVersionUID = 3011117385035501302L; - - public Draw() - { - super("Draw to file"); - } - - @Override - public void actionPerformed(ActionEvent e) { - DrawMediator.drawState(); - } - - } - - public static class Current extends AbstractAction - { - - /** - * - */ - private static final long serialVersionUID = 3011117385035501302L; - - public Current() - { - super("Edit simulation"); - } - - @Override - public void actionPerformed(ActionEvent e) { - if (Helper.compartmentAvailable()) - GuiActions.loadCurrentState(); - } - - } - - public static class LogTier extends AbstractAction - { - private static final long serialVersionUID = 2660256074849177100L; - - /** - * The output level {@code Tier} for the log file that this button - * represents. - */ - private Tier _tier; - - /** - * Action for the set Log Tier sub-menu. - */ - public LogTier(Log.Tier tier) - { - super(tier.toString()); - this._tier = tier; - } - - public void actionPerformed(ActionEvent e) - { - Log.set(this._tier); - } - } - - public static class Sampling extends AbstractAction - { - - private SamplerLaunch smp = new SamplerLaunch(); - - public Sampling() - { - super("Sample master"); - } - - @Override - public void actionPerformed(ActionEvent e) { - smp.initialize(null); - } - } - -// public static class GuiView extends AbstractAction -// { -// private static final long serialVersionUID = 8725075624293930079L; -// -// private ViewType _view; -// -// public GuiView(ViewType view) -// { -// super(view.toString()); -// this._view = view; -// } -// -// public void actionPerformed(ActionEvent e) -// { -// GuiLaunch.setView(this._view); -// } -// } -} +/** + * + */ +package gui; + +import java.awt.event.ActionEvent; +import java.awt.event.KeyEvent; + +import javax.swing.AbstractAction; +import javax.swing.JMenu; +import javax.swing.JMenuBar; +import javax.swing.JMenuItem; +import javax.swing.JRadioButtonMenuItem; +import javax.swing.KeyStroke; + +import analysis.FilteredTable; +import analysis.quantitative.Raster; +import dataIO.Diagram; +import dataIO.DrawMediator; +import dataIO.Log; +import dataIO.Log.Tier; +import idynomics.Idynomics; +import idynomics.Simulator; +import idynomics.launchable.SamplerLaunch; +import utility.Helper; + +/** + * + * @author Bastiaan Cockx @BastiaanCockx (baco@env.dtu.dk), DTU, Denmark + * @author Robert Clegg (r.j.clegg@bham.ac.uk) University of Birmingham, U.K. + */ +public final class GuiMenu +{ + private static JMenuBar _menuBar; + + public static JMenuBar getMenuBar() + { + _menuBar = new JMenuBar(); + _menuBar.add(fileMenu()); + _menuBar.add(interactionMenu()); + return _menuBar; + } + + + private static JMenu fileMenu() + { + JMenu menu, levelMenu; + JMenuItem menuItem; + JRadioButtonMenuItem rbMenuItem; + /* + * Set up the File menu. + */ + menu = new JMenu("File"); + menu.setMnemonic(KeyEvent.VK_F); + menu.getAccessibleContext().setAccessibleDescription("File options"); + /* + * Add the option of making a new simulation. + */ + menuItem = new JMenuItem(new GuiMenu.NewFile()); + menuItem.setAccelerator(KeyStroke.getKeyStroke( + KeyEvent.VK_N, ActionEvent.CTRL_MASK)); + menuItem.getAccessibleContext().setAccessibleDescription( + "Make a new simulation"); + menu.add(menuItem); + /* + * Add the option of opening a protocol file. + */ + menuItem = new JMenuItem(new GuiMenu.FileOpen()); + menuItem.setAccelerator(KeyStroke.getKeyStroke( + KeyEvent.VK_O, ActionEvent.CTRL_MASK)); + menuItem.getAccessibleContext().setAccessibleDescription( + "Open existing protocol file"); + menu.add(menuItem); + + + menuItem = new JMenuItem(new GuiMenu.FileDownload()); + menuItem.setAccelerator(KeyStroke.getKeyStroke( + KeyEvent.VK_D, ActionEvent.CTRL_MASK)); + menuItem.getAccessibleContext().setAccessibleDescription( + "Download protocol file"); + menu.add(menuItem); + + /* + * Add the option of rendering a compartment. + */ + menuItem = new JMenuItem(new GuiMenu.RenderThis()); + menuItem.setAccelerator(KeyStroke.getKeyStroke( + KeyEvent.VK_R, ActionEvent.CTRL_MASK)); + menuItem.getAccessibleContext().setAccessibleDescription( + "Render a spatial compartment"); + menu.add(menuItem); + /* + * Output level. + * NOTE this will not work through the menu bar, instead edit trough + * simulation state. + menu.addSeparator(); + levelMenu = new JMenu("OutputLevel"); + levelMenu.setMnemonic(KeyEvent.VK_L); + ButtonGroup group = new ButtonGroup(); + for ( Log.Tier t : Log.Tier.values() ) + { + rbMenuItem = new JRadioButtonMenuItem(new GuiMenu.LogTier(t)); + group.add(rbMenuItem); + levelMenu.add(rbMenuItem); + } + menu.add(levelMenu); + */ + + /* + * Master protocol sampling + */ + menu.addSeparator(); + menuItem = new JMenuItem(new GuiMenu.Sampling()); + menuItem.getAccessibleContext().setAccessibleDescription( + "Sample master protocol file"); + menu.add(menuItem); + + menuItem = new JMenuItem(new GuiMenu.PostProcess()); + menuItem.getAccessibleContext().setAccessibleDescription( + "Perform post processing"); + menu.add(menuItem); + + /* + * Finally, return the File menu. + */ + return menu; + } + + + private static JMenu interactionMenu() + { + JMenu menu; + JMenuItem menuItem; + /* + * Set up the File menu. + */ + menu = new JMenu("Interact"); + menu.setMnemonic(KeyEvent.VK_G); + menu.getAccessibleContext().setAccessibleDescription("Interactive"); + /* + * Add the option of rendering a compartment. + */ + menuItem = new JMenuItem(new GuiMenu.Current()); + menuItem.setAccelerator(KeyStroke.getKeyStroke( + KeyEvent.VK_L, ActionEvent.CTRL_MASK)); + menuItem.getAccessibleContext().setAccessibleDescription( + "Edit simulation state"); + menu.add(menuItem); + /* + * Draw to graphics file + */ + menuItem = new JMenuItem(new GuiMenu.Draw()); + menuItem.setAccelerator(KeyStroke.getKeyStroke( + KeyEvent.VK_D, ActionEvent.CTRL_MASK)); + menuItem.getAccessibleContext().setAccessibleDescription( + "Draw to file"); + menu.add(menuItem); + /* + * Draw raster + */ + menuItem = new JMenuItem(new GuiMenu.StructureAnalysis()); + menuItem.getAccessibleContext().setAccessibleDescription( + "Draw raster to file"); + menu.add(menuItem); + /* + * Draw species diagram + */ + menuItem = new JMenuItem(new GuiMenu.SpeciesDiagram()); + menuItem.setAccelerator(KeyStroke.getKeyStroke( + KeyEvent.VK_D, ActionEvent.CTRL_MASK)); + menuItem.getAccessibleContext().setAccessibleDescription( + "Request agent information"); + menu.add(menuItem); + /* + * Draw reaction diagram + */ + menuItem = new JMenuItem(new ReactionDiagram()); + menuItem.setAccelerator(KeyStroke.getKeyStroke( + KeyEvent.VK_D, ActionEvent.CTRL_MASK)); + menuItem.getAccessibleContext().setAccessibleDescription( + "Request agent information"); + menu.add(menuItem); + /* + * Query some agents + */ + menuItem = new JMenuItem(new GuiMenu.Query()); + menuItem.setAccelerator(KeyStroke.getKeyStroke( + KeyEvent.VK_T, ActionEvent.CTRL_MASK)); + menuItem.getAccessibleContext().setAccessibleDescription( + "Request agent information"); + menu.add(menuItem); + /* + * Query some agents + */ + menuItem = new JMenuItem(new GuiMenu.QueryToFile()); + menuItem.setAccelerator(KeyStroke.getKeyStroke( + KeyEvent.VK_Y, ActionEvent.CTRL_MASK)); + menuItem.getAccessibleContext().setAccessibleDescription( + "Request agent information and store in output folder"); + menu.add(menuItem); + /* + * Finally, return the File menu. + */ + return menu; + } + + /************************************************************************* + * + ************************************************************************/ + + public static class NewFile extends AbstractAction + { + private static final long serialVersionUID = 8931286266304166474L; + + /** + * Action for the file open sub-menu. + */ + public NewFile() + { + super("Make new protocol"); + } + + public void actionPerformed(ActionEvent e) + { + Idynomics.simulator = new Simulator(); + GuiActions.loadCurrentState(); + } + } + + public static class FileOpen extends AbstractAction + { + private static final long serialVersionUID = 2247122248926681550L; + + /** + * Action for the file open sub-menu. + */ + public FileOpen() + { + super("Open.."); + } + + public void actionPerformed(ActionEvent e) + { + GuiActions.chooseFile(); + } + } + + public static class FileDownload extends AbstractAction + { + private static final long serialVersionUID = 2247122248926681550L; + + /** + * Action for the file open sub-menu. + */ + public FileDownload() + { + super("Download.."); + } + + public void actionPerformed(ActionEvent e) + { + GuiActions.downloadFile(null); + } + } + + public static class RenderThis extends AbstractAction + { + private static final long serialVersionUID = 974971035938028563L; + + /** + * Create a new {@code Render} object and invoke it. + * + *

The {@code Render} object handles its own {@code JFrame}.

+ */ + public RenderThis() + { + super("Render"); + } + + public void actionPerformed(ActionEvent e) + { + GuiActions.render(); + } + } + + public static class PostProcess extends AbstractAction + { + private static final long serialVersionUID = 2247122248926681550L; + + /** + * Action for the file open sub-menu. + */ + public PostProcess() + { + super("Post-process"); + } + + public void actionPerformed(ActionEvent e) + { + GuiActions.postProcess(); + } + } + + public static class SpeciesDiagram extends AbstractAction + { + + /** + * + */ + private static final long serialVersionUID = 3011117385035501302L; + + public SpeciesDiagram() + { + super("Species Diagram"); + } + + @Override + public void actionPerformed(ActionEvent e) { + if (Helper.compartmentAvailable()) + { + String fileName = "speciesDiagram"; + Diagram diag = new Diagram(); + diag.createCustomFile(fileName); + diag.speciesDiagram(); + diag.closeFile(); + Log.printToScreen("species diagram created.", false); + } + } + + } + + public static class ReactionDiagram extends AbstractAction + { + + /** + * + */ + private static final long serialVersionUID = 3011117385035501302L; + + public ReactionDiagram() + { + super("Reaction Diagram"); + } + + @Override + public void actionPerformed(ActionEvent e) { + if (Helper.compartmentAvailable()) + { + String fileName = "reactionDiagram"; + Diagram diag = new Diagram(); + diag.createCustomFile(fileName); + diag.reactionDiagram( Helper.selectCompartment() ); + diag.closeFile(); + Log.printToScreen("reaction diagram created.", false); + } + } + + } + + public static class Query extends AbstractAction + { + + /** + * + */ + private static final long serialVersionUID = 3011117385035501302L; + + public Query() + { + super("Query"); + } + + @Override + public void actionPerformed(ActionEvent e) { + if (Helper.compartmentAvailable()) + { + String table = GuiConsole.requestInput("Table logic"); + table = table.replaceAll("\\s+",""); + FilteredTable tab = new FilteredTable(table); + Log.printToScreen(tab.display(), false); + } + } + + } + + public static class QueryToFile extends AbstractAction + { + + /** + * + */ + private static final long serialVersionUID = 3011117385035501302L; + + public QueryToFile() + { + super("QueryToFile"); + } + + @Override + public void actionPerformed(ActionEvent e) { + if (Helper.compartmentAvailable()) + { + String table = GuiConsole.requestInput("Table logic"); + table = table.replaceAll("\\s+",""); + FilteredTable tab = new FilteredTable(table); + tab.toFile(); + } + } + + } + + public static class StructureAnalysis extends AbstractAction + { + + /** + * + */ + private static final long serialVersionUID = 3011117385035501302L; + + public StructureAnalysis() + { + super("StructureAnalysis"); + } + + @Override + public void actionPerformed(ActionEvent e) { + if (Helper.compartmentAvailable()) + { + if ( Helper.selectSpatialCompartment() == null ) + Log.printToScreen("No spatial compartment available.", + false ); + { + Raster raster = new Raster( + Helper.selectSpatialCompartment(), true ); + raster.rasterize( Double.valueOf( + Helper.obtainInput( null, "Raster scale" ) ) ); + raster.plot( raster.agentMap(), 1.0, + Helper.obtainInput( null, "filename") ); + } + } + } + + } + + public static class Draw extends AbstractAction + { + + /** + * + */ + private static final long serialVersionUID = 3011117385035501302L; + + public Draw() + { + super("Draw to file"); + } + + @Override + public void actionPerformed(ActionEvent e) { + DrawMediator.drawState(); + } + + } + + public static class Current extends AbstractAction + { + + /** + * + */ + private static final long serialVersionUID = 3011117385035501302L; + + public Current() + { + super("Edit simulation"); + } + + @Override + public void actionPerformed(ActionEvent e) { + if (Helper.compartmentAvailable()) + GuiActions.loadCurrentState(); + } + + } + + public static class LogTier extends AbstractAction + { + private static final long serialVersionUID = 2660256074849177100L; + + /** + * The output level {@code Tier} for the log file that this button + * represents. + */ + private Tier _tier; + + /** + * Action for the set Log Tier sub-menu. + */ + public LogTier(Log.Tier tier) + { + super(tier.toString()); + this._tier = tier; + } + + public void actionPerformed(ActionEvent e) + { + Log.set(this._tier); + } + } + + public static class Sampling extends AbstractAction + { + + private SamplerLaunch smp = new SamplerLaunch(); + + public Sampling() + { + super("Sample master"); + } + + @Override + public void actionPerformed(ActionEvent e) { + smp.initialize(null); + } + } + +// public static class GuiView extends AbstractAction +// { +// private static final long serialVersionUID = 8725075624293930079L; +// +// private ViewType _view; +// +// public GuiView(ViewType view) +// { +// super(view.toString()); +// this._view = view; +// } +// +// public void actionPerformed(ActionEvent e) +// { +// GuiLaunch.setView(this._view); +// } +// } +} diff --git a/src/idynomics/Idynomics.java b/src/idynomics/Idynomics.java index 6fb1586b0..89f18d45d 100644 --- a/src/idynomics/Idynomics.java +++ b/src/idynomics/Idynomics.java @@ -48,6 +48,11 @@ public strictfp class Idynomics */ public static Simulator simulator; + /** + * {@code PostProcess} object: there can only be one. + */ + public static PostProcess postProcess; + /** * iDynoMiCS internal unit system. */ @@ -64,6 +69,11 @@ public strictfp class Idynomics */ public static Thread simThread; + /** + * post-processing thread + */ + public static Thread postProcessingThread; + /** * Contains all predefined className package association for easy class * initiation from xml file. @@ -275,6 +285,15 @@ public static void launchSimulator() simThread.start(); } + /** + * run + */ + public static void runPostProcess() + { + postProcessingThread = new Thread(postProcess); + postProcessingThread.start(); + } + /** * \brief TODO * diff --git a/src/idynomics/PostProcess.java b/src/idynomics/PostProcess.java new file mode 100644 index 000000000..ff19a50c2 --- /dev/null +++ b/src/idynomics/PostProcess.java @@ -0,0 +1,32 @@ +package idynomics; + +import java.io.File; +import java.util.List; + +public class PostProcess implements Runnable { + + /** + * Files to be post processed + */ + private List _files; + + /** + * Post processing script + */ + private File _script; + + public PostProcess(File script, List files) + { + this._script = script; + this._files = files; + } + + @Override + public void run() + { + for( File f : _files) + { + Idynomics.setupSimulator( f.getAbsolutePath() ); + } + } +} diff --git a/src/utility/Helper.java b/src/utility/Helper.java index e5bc3b614..0512ffd06 100644 --- a/src/utility/Helper.java +++ b/src/utility/Helper.java @@ -737,6 +737,14 @@ public static boolean dblParseable(String strParse) return false; } + public static boolean intParseable(String strParse) + { + if (strParse.matches("\\d+")){ + return true; + } + return false; + } + public static boolean boolParseable(String strParse) { for( String s : Helper.rejections) From 5cf6655cf283cf27a64cabc5f43a28c2dd944bd9 Mon Sep 17 00:00:00 2001 From: baseendje Date: Thu, 11 Jun 2020 11:01:28 +0200 Subject: [PATCH 02/67] further work on post-process --- src/dataIO/CumulativeLoad.java | 15 +++++++++++++++ src/idynomics/PostProcess.java | 5 +++++ 2 files changed, 20 insertions(+) diff --git a/src/dataIO/CumulativeLoad.java b/src/dataIO/CumulativeLoad.java index 3a5b6f550..157b33158 100644 --- a/src/dataIO/CumulativeLoad.java +++ b/src/dataIO/CumulativeLoad.java @@ -1,6 +1,10 @@ package dataIO; +import java.util.Collection; +import java.util.List; + import org.w3c.dom.Element; +import org.w3c.dom.NodeList; import compartment.Compartment; import idynomics.Idynomics; @@ -23,6 +27,17 @@ public CumulativeLoad(String xml) document = XmlHandler.loadDocument(xml); } + public Collection getProcessNodes() + { + return XmlHandler.getElements( document ,XmlRef.process ); + } + + public String test() + { + + return ""; + } + public void postProcess() { Compartment comp = null; diff --git a/src/idynomics/PostProcess.java b/src/idynomics/PostProcess.java index ff19a50c2..c6936893a 100644 --- a/src/idynomics/PostProcess.java +++ b/src/idynomics/PostProcess.java @@ -3,6 +3,8 @@ import java.io.File; import java.util.List; +import dataIO.CumulativeLoad; + public class PostProcess implements Runnable { /** @@ -14,11 +16,14 @@ public class PostProcess implements Runnable { * Post processing script */ private File _script; + + private CumulativeLoad loader; public PostProcess(File script, List files) { this._script = script; this._files = files; + this.loader = new CumulativeLoad( this._script.getAbsolutePath() ); } @Override From 760b97b0b9c427833b6474ba47f43f3f4653a577 Mon Sep 17 00:00:00 2001 From: baseendje Date: Mon, 15 Jun 2020 13:48:13 +0200 Subject: [PATCH 03/67] functional prototype post-processing --- src/compartment/AgentContainer.java | 2 + src/compartment/Compartment.java | 1573 +++++++++-------- src/dataIO/CumulativeLoad.java | 14 +- src/dataIO/GraphicalExporter.java | 2 + src/dataIO/PovExport.java | 5 +- src/dataIO/SvgExport.java | 6 + src/gui/GuiActions.java | 2 +- src/idynomics/PostProcess.java | 4 + src/processManager/ProcessManager.java | 864 ++++----- .../library/GraphicalOutput.java | 3 +- src/referenceLibrary/AspectRef.java | 2 + 11 files changed, 1257 insertions(+), 1220 deletions(-) diff --git a/src/compartment/AgentContainer.java b/src/compartment/AgentContainer.java index 715910a28..70c445490 100644 --- a/src/compartment/AgentContainer.java +++ b/src/compartment/AgentContainer.java @@ -18,6 +18,7 @@ import dataIO.Log; import dataIO.Log.Tier; import gereralPredicates.IsSame; +import instantiable.object.InstantiableList; import linearAlgebra.Vector; import physicalObject.PhysicalObject; import referenceLibrary.AspectRef; @@ -777,6 +778,7 @@ public Module getModule() /* Add the agent childConstrutor for adding of additional agents. */ modelNode.addChildSpec( ClassRef.agent, Module.Requirements.ZERO_TO_MANY); + /* If there are agents, add them as child nodes. */ for ( Agent a : this.getAllAgents() ) modelNode.add( a.getModule() ); diff --git a/src/compartment/Compartment.java b/src/compartment/Compartment.java index 195405120..dde72748c 100644 --- a/src/compartment/Compartment.java +++ b/src/compartment/Compartment.java @@ -1,782 +1,791 @@ -package compartment; - -import java.util.Collection; -import java.util.Collections; -import java.util.HashMap; -import java.util.LinkedList; -import java.util.List; -import java.util.Map; -import java.util.TreeMap; - -import org.w3c.dom.Element; - -import agent.Agent; -import boundary.Boundary; -import boundary.SpatialBoundary; -import compartment.agentStaging.Spawner; -import dataIO.Log; -import dataIO.Log.Tier; -import dataIO.XmlHandler; -import generalInterfaces.CanPrelaunchCheck; -import grid.SpatialGrid; -import idynomics.Idynomics; -import instantiable.Instance; -import instantiable.Instantiable; -import linearAlgebra.Orientation; -import linearAlgebra.Vector; -import physicalObject.PhysicalObject; -import processManager.ProcessComparator; -import processManager.ProcessManager; -import reaction.RegularReaction; -import referenceLibrary.ClassRef; -import referenceLibrary.XmlRef; -import settable.Attribute; -import settable.Module; -import settable.Module.Requirements; -import settable.Settable; -import shape.Dimension.DimName; -import shape.Shape; -import spatialRegistry.TreeType; -import utility.Helper; - -/** - * \brief TODO - * - *

A compartment owns

    - *
  • one shape
  • - *
  • one environment container
  • - *
  • one agent container
  • - *
  • zero to many process managers

- * - *

The environment container and the agent container both have a reference - * to the shape, but do not know about each other. Agent-environment - * interactions must be mediated by a process manager. Each process manager has - * a reference to the environment container and the agent container, and - * therefore can ask either of these about the compartment shape. It is - * important though, that process managers do not have a reference to the - * compartment they belong to: otherwise, a naive developer could have a - * process manager call the {@code step()} method in {@code Compartment}, - * causing such chaos that even the thought of it keeps Rob awake at night.

- * - *

In summary, the hierarchy of ownership is: shape -> agent/environment - * containers -> process managers -> compartment. All the arrows point in the - * same direction, meaning no entanglement of the kind iDynoMiCS 1 suffered.

- * - * @author Robert Clegg (r.j.clegg@bham.ac.uk) University of Birmingham, U.K. - * @author Bastiaan Cockx @BastiaanCockx (baco@env.dtu.dk), DTU, Denmark - * @author Stefan Lang (stefan.lang@uni-jena.de) - * Friedrich-Schiller University Jena, Germany - * @author Sankalp Arya (sankalp.arya@nottingham.ac.uk) University of Nottingham, U.K. - */ -public class Compartment implements CanPrelaunchCheck, Instantiable, Settable, Comparable -{ - /** - * This has a name for reporting purposes. - */ - public String name; - /** - * Shape describes the geometry and size. - * - * TODO also the resolution calculators? - */ - protected Shape _shape; - /** - * Scaling factor determines the ratio of real to modelled size. - * All calculations for boundary movement will use this for scaling up from - * the modelled size to actual biofilm size. - */ - protected double _scalingFactor = 1.0; - /** - * AgentContainer deals with all agents, whether they have spatial location - * or not. - */ - public AgentContainer agents; - /** - * EnvironmentContainer deals with all solutes. - */ - public EnvironmentContainer environment; - /** - * ProcessManagers handle the interactions between agents and solutes. - * The order of the list is important. - */ - protected LinkedList _processes = - new LinkedList(); - /** - * ProcessComparator orders Process Managers by their time priority. - */ - protected ProcessComparator _procComp = new ProcessComparator(); - /** - * Local time should always be between {@code Timer.getCurrentTime()} and - * {@code Timer.getEndOfCurrentTime()}. - */ - // TODO temporary fix, reassess - //protected double _localTime = Idynomics.simulator.timer.getCurrentTime(); - protected double _localTime; - - /** - * the compartment parent node constructor (simulator) - */ - private Settable _parentNode; - - /** - * - */ - private int _priority = Integer.MAX_VALUE; - - /* *********************************************************************** - * CONSTRUCTORS - * **********************************************************************/ - - public Compartment() - { - - } - - public Compartment(String name) - { - this.name = name; - } - - public void remove(Object object) - { - if ( object instanceof ProcessManager ) - this._processes.remove(object); - } - - public Settable newBlank() - { - Compartment newComp = new Compartment(); - return newComp; - } - - /** - * \brief - * - * @param aShape - */ - public void setShape(Shape aShape) - { - if( Log.shouldWrite(Tier.EXPRESSIVE)) - Log.out(Tier.EXPRESSIVE, "Compartment \""+this.name+ - "\" taking shape \""+aShape.getName()+"\""); - this._shape = aShape; - this.environment = new EnvironmentContainer(this._shape); - this.agents = new AgentContainer(this._shape); - } - /** - * \brief Initialise this {@code Compartment} from an XML node. - * - * TODO diffusivity - * @param xmlElem An XML element from a protocol file. - */ - public void instantiate(Element xmlElem, Settable parent) - { - /* - * Compartment initiation - */ - this.name = XmlHandler.obtainAttribute( - xmlElem, XmlRef.nameAttribute, XmlRef.compartment); - if( XmlHandler.hasAttribute(xmlElem, XmlRef.priority)) - this._priority = Integer.valueOf( XmlHandler.gatherAttribute( - xmlElem, XmlRef.priority) ); - Idynomics.simulator.addCompartment(this); - /* - * Set up the shape. - */ - Element elem = XmlHandler.findUniqueChild(xmlElem, XmlRef.compartmentShape); - String[] str = new String[] { XmlHandler.gatherAttribute(elem, XmlRef.classAttribute) }; - if ( str[0] == null ) - str = Shape.getAllOptions(); - this.setShape( (Shape) Instance.getNew(elem, this, str) ); - /* NOTE density scaling is done on individual basis {@Link - * DensityScaling} so agents can maintain constant radius for 2D and 3D - * cases. */ - - double[] simulatedLengths = this.getShape().getDimensionLengths(); - // Check for scale attribute, specifying explicitly provided scale. - String scalingFac = XmlHandler.gatherAttribute(xmlElem, XmlRef.compartmentScale); - if ( !Helper.isNullOrEmpty(scalingFac) ) - { - double scFac = Double.valueOf(scalingFac); - this.setScalingFactor(scFac); - } - // Check for significant dimensions. - else if (simulatedLengths.length != 0) - { - // Scaling factor not provided explicitly, calculate from realLengths - Shape compShape = this.getShape(); - DimName dimN = compShape.getRealDimExtremeName(); - if ( Helper.isNullOrEmpty(compShape.getRealDimExtremeName()) ) - { - double simulatedVolume = compShape.getTotalVolume(); - double realVolume = compShape.getTotalRealVolume(); - this.setScalingFactor(realVolume / simulatedVolume); - } - else - { - double simulatedArea = compShape.getBoundarySurfaceArea(dimN, 1); - double realArea = compShape.getRealSurfaceArea(dimN, 1); - this.setScalingFactor(realArea / simulatedArea); - } - } - - for( Boundary b : this._shape.getAllBoundaries()) - { - b.setContainers(environment, agents); - // FIXME trying to figure out how to get the well mixed region working, - // quite funky investigate -// if (b instanceof SpatialBoundary) -// ((SpatialBoundary) b).setLayerThickness(Double.valueOf( -// XmlHandler.obtainAttribute(xmlElem, -// XmlRef.layerThickness, XmlRef.compartment))); - } - /* - * set container parentNodes - */ - agents.setParent(this); - environment.setParent(this); - /* - * setup tree - */ - String type = XmlHandler.gatherAttribute(xmlElem, XmlRef.tree); - type = Helper.setIfNone(type, String.valueOf( agents.getSpatialTreeType() )); - this.agents.setSpatialTreeType(TreeType.valueOf(type)); - /* - * Look for spawner elements - */ - Spawner spawner; - TreeMap spawners = new TreeMap(); - for ( Element e : XmlHandler.getElements( xmlElem, XmlRef.spawnNode) ) - { - if ( e.hasAttribute( XmlRef.classAttribute ) ) - { - spawner = (Spawner) Instance.getNew(e, this); - /* check for duplicate priority */ - int priority = Helper.nextAvailableKey( - spawner.getPriority(),spawners.keySet() ); - if (spawners.containsKey( spawner.getPriority() )) - { - if( Log.shouldWrite(Tier.EXPRESSIVE)) - Log.out(Tier.EXPRESSIVE, "WARNING: Spawner with " - + "duplicate priority next priority is picked " - + "by simulator."); - } - spawners.put(priority, spawner); - } - } - /* verify whether this always returns in correct order (it should) */ - for( Spawner s : spawners.values() ) - s.spawn(); - - if( Log.shouldWrite(Tier.EXPRESSIVE)) - Log.out(Tier.EXPRESSIVE, "Compartment " + this.name + - " initialised with " + this.agents.getNumAllAgents() + - " agents."); - - /* - * Read in agents. - */ - for ( Element e : XmlHandler.getElements( xmlElem, XmlRef.agent) ) - this.addAgent(new Agent( e, this )); - if( Log.shouldWrite(Tier.EXPRESSIVE)) - Log.out(Tier.EXPRESSIVE, "Compartment "+this.name+" initialised with "+ - this.agents.getNumAllAgents()+" agents"); - /* - * Load solutes. - */ - if( Log.shouldWrite(Tier.EXPRESSIVE)) - Log.out(Tier.EXPRESSIVE, "Compartment reading in solutes"); - Element solutes = XmlHandler.findUniqueChild(xmlElem, XmlRef.solutes); - for ( Element e : XmlHandler.getElements(solutes, XmlRef.solute)) - { - new SpatialGrid( e, this.environment); - } - /* - * Load extra-cellular reactions. - */ - if( Log.shouldWrite(Tier.EXPRESSIVE)) - Log.out(Tier.EXPRESSIVE, "Compartment reading in (environmental) reactions"); - for ( Element e : XmlHandler.getElements( xmlElem, XmlRef.reaction) ) - new RegularReaction(e, this.environment); - /* - * Read in process managers. - */ - if( Log.shouldWrite(Tier.EXPRESSIVE)) - Log.out(Tier.EXPRESSIVE,"Compartment "+this.name+ " loading "+XmlHandler. - getElements(xmlElem, XmlRef.process).size()+" processManagers"); - for ( Element e : XmlHandler.getElements( xmlElem, XmlRef.process) ) - { - this.addProcessManager( - (ProcessManager) Instance.getNew(e, this, (String[])null)); - } - - for ( Element e : XmlHandler.getElements(xmlElem,XmlRef.physicalObject)) - { - this.addPhysicalObject( (PhysicalObject) Instance.getNew(e, this, - PhysicalObject.class.getName())); - } - - /* NOTE: we fetch the class from the xml node */ - elem = XmlHandler.findUniqueChild(xmlElem, XmlRef.orientation); - str = new String[] { XmlHandler.gatherAttribute(elem, XmlRef.variable) }; - if ( str[0] == null ) - { - this.getShape().setOrientation( new Orientation( Vector.zerosDbl( - this._shape.getNumberOfDimensions() ), this ) ); - } else { - this.getShape().setOrientation( (Orientation) Instance.getNew( elem, - this, Orientation.class.getName() ) ); - } - } - - - - /* *********************************************************************** - * BASIC SETTERS & GETTERS - * **********************************************************************/ - - public String getName() - { - return this.name; - } - - public Shape getShape() - { - return this._shape; - } - - public boolean isDimensionless() - { - return this._shape.getNumberOfDimensions() == 0; - } - - public int getNumDims() - { - return this._shape.getNumberOfDimensions(); - } - - public void setSideLengths(double[] sideLengths) - { - this._shape.setDimensionLengths(sideLengths); - } - - /** - * \brief Add a boundary to this compartment's shape. - * - * @param aBoundary Any boundary, whether spatial or non-spatial. - */ - // TODO move this spatial/non-spatial splitting to Shape? - public void addBoundary(Boundary aBoundary) - { - aBoundary.setContainers(this.environment, this.agents); - if ( aBoundary instanceof SpatialBoundary ) - { - SpatialBoundary sB = (SpatialBoundary) aBoundary; - DimName dim = sB.getDimName(); - int extreme = sB.getExtreme(); - this._shape.setBoundary(dim, extreme, sB); - } - else - this._shape.addOtherBoundary(aBoundary); - } - - /** - * \brief Add the given {@code ProcessManager} to the list, making sure - * that it is in the correct place. - * - * @param aProcessManager - */ - public void addProcessManager(ProcessManager aProcessManager) - { - this._processes.add(aProcessManager); - // TODO Rob [18Apr2016]: Check if the process's next time step is - // earlier than the current time. - Collections.sort(this._processes, this._procComp); - } - - /** - * \brief Add the given agent to this compartment. - * - * @param Agent Agent to add. - */ - public void addAgent(Agent agent) - { - - this.agents.addAgent(agent); - agent.setCompartment(this); - } - - public void addPhysicalObject(PhysicalObject p) - { - this.agents._physicalObjects.add(p); - } - - public void addReaction(RegularReaction reaction) - { - this.environment.addReaction(reaction); - } - - public void addSolute(SpatialGrid solute) - { - this.environment.addSolute(solute); - } - - /** - * \brief Remove the given agent from this compartment, registering its - * removal. - * - *

This should be used only removal from the entire simulation, and not - * for transfer to another compartment. For example, cell lysis.

- * - * @param agent Agent to remove. - */ - public void registerRemoveAgent(Agent agent) - { - agent.setCompartment(null); - this.agents.registerRemoveAgent(agent); - } - - /** - * \brief Get the {@code SpatialGrid} for the given solute name. - * - * @param soluteName {@code String} name of the solute required. - * @return The {@code SpatialGrid} for that solute, or {@code null} if it - * does not exist. - */ - public SpatialGrid getSolute(String soluteName) - { - return this.environment.getSoluteGrid(soluteName); - } - - /* *********************************************************************** - * STEPPING - * **********************************************************************/ - - /** - * \brief Connects any disconnected boundaries to a new partner boundary on - * the appropriate compartment. - * - * Note that generation of spatial boundaries by this method is not yet - * possible. It is therefore necessary to specify spatial boundaries and to - * omit their partners in the protocol file. - * @param compartments List of compartments to choose from. - */ - public void checkBoundaryConnections(Collection compartments) - { - List compartmentNames = new LinkedList(); - for ( Compartment c : compartments ) - compartmentNames.add(c.getName()); - - for ( Boundary b : this._shape.getDisconnectedBoundaries() ) - { - String name = b.getPartnerCompartmentName(); - Compartment comp = findByName(compartments, name); - while ( comp == null ) - { - if( Log.shouldWrite(Tier.CRITICAL) ) - Log.out(Tier.CRITICAL, - "Cannot connect boundary " + b.getName() + - " in compartment " + this.getName()); - name = Helper.obtainInput(compartmentNames, - "Please choose a compartment:", true); - comp = findByName(compartments, name); - } - if( Log.shouldWrite(Tier.EXPRESSIVE) ) - Log.out(Tier.EXPRESSIVE, - "Connecting boundary " + b.getName() + - " to a partner boundary of type " + - b.getPartnerClass().toString() + " in compartment " + - comp.getName()); - Boundary partner = b.makePartnerBoundary(); - comp.addBoundary(partner); - } - } - - /** - * \brief Do all inbound agent & solute transfers. - */ - public void preStep() - { - /* - * Ask all Agents waiting in boundary arrivals lounges to enter the - * compartment now. - */ - this.agents.agentsArrive(); - - this.agents.sortLocatedAgents(); - /* - * Ask all boundaries to update their solute concentrations. - */ - this.environment.updateSoluteBoundaries(); - } - - /** - * \brief Iterate over the process managers until the local time would - * exceed the global time step. - */ - public void step() - { - this._localTime = Idynomics.simulator.timer.getCurrentTime(); - if( Log.shouldWrite(Tier.DEBUG) ) - { - Log.out(Tier.DEBUG, "Compartment "+this.name+ - " at local time "+this._localTime); - } - - if ( this._processes.isEmpty() ) - return; - ProcessManager currentProcess = this._processes.getFirst(); - while ( (this._localTime = currentProcess.getTimeForNextStep() ) - < Idynomics.simulator.timer.getEndOfCurrentIteration() && - Idynomics.simulator.active() ) - { - if( Log.shouldWrite(Tier.DEBUG) ) - Log.out(Tier.DEBUG, "Compartment "+this.name+ - " running process "+currentProcess.getName()+ - " at local time "+this._localTime); - - /* - * First process on the list does its thing. This should then - * increase its next step time. - */ - currentProcess.step(); - /* - * Reinsert this process at the appropriate position in the list. - */ - Collections.sort(this._processes, this._procComp); - /* - * Choose the new first process for the next iteration. - */ - currentProcess = this._processes.getFirst(); - } - } - - /** - * \brief Do all outbound agent & solute transfers. - */ - public void postStep() - { - /* - * Boundaries grab the agents they want, settling any conflicts between - * boundaries. - */ - this.agents.boundariesGrabAgents(); - /* - * Tell all agents queued to leave the compartment to move now. - */ - this.agents.agentsDepart(); - } - - /* *********************************************************************** - * PRE-LAUNCH CHECK - * **********************************************************************/ - - public boolean isReadyForLaunch() - { - if ( this._shape == null ) - { - Log.out(Tier.CRITICAL, "Compartment shape is undefined!"); - return false; - } - if ( ! this._shape.isReadyForLaunch() ) - return false; - return true; - } - - /* *********************************************************************** - * REPORTING - * **********************************************************************/ - - public void printSoluteGrid(String soluteName) - { - this.environment.printSolute(soluteName); - } - - public void printAllSoluteGrids() - { - this.environment.printAllSolutes(); - } - - /** - * @return TODO - */ - public Map getRealTimeStats() - { - Map out = new HashMap(); - for ( ProcessManager pm : this._processes ) - { - if (out.containsKey(pm.getName())) - out.put(pm.getName(), out.get(pm.getName()) + pm.getRealTimeTaken()); - else - out.put(pm.getName(), pm.getRealTimeTaken()); - } - return out; - } - - /* *********************************************************************** - * Model Node factory - * **********************************************************************/ - - @Override - public Module getModule() - { - /* The compartment node. */ - Module modelNode = new Module(XmlRef.compartment, this); - modelNode.setRequirements(Requirements.ZERO_TO_FEW); - /* Set title for GUI. */ - if ( this.getName() != null ) - modelNode.setTitle(this.getName()); - - /* Add the name attribute. */ - modelNode.add( new Attribute(XmlRef.nameAttribute, - this.getName(), null, true ) ); - modelNode.add( new Attribute(XmlRef.priority, - String.valueOf(this._priority), null, true ) ); - - modelNode.add( new Attribute(XmlRef.compartmentScale, - String.valueOf(this.getScalingFactor()), null, true ) ); - /* Add the shape if it exists. */ - if ( this._shape != null ) - modelNode.add( this._shape.getModule() ); - /* Add the Environment node. */ - modelNode.add( this.environment.getModule() ); - /* Add the Agents node. */ - modelNode.add( this.agents.getModule() ); - /* Add the process managers node. */ - modelNode.add( this.getProcessNode() ); - - modelNode.add( getObjectNode() ); - - /* spatial registry NOTE we are handling this here since the agent - * container does not have the proper init infrastructure */ - modelNode.add( new Attribute(XmlRef.tree, - String.valueOf( this.agents.getSpatialTreeType() ) , - Helper.enumToStringArray( TreeType.class ), false ) ); - - return modelNode; - } - - /** - * \brief Helper method for {@link #getModule()}. - * - * @return Model node for the process managers. - */ - private Module getProcessNode() - { - /* The process managers node. */ - Module modelNode = new Module( XmlRef.processManagers, this ); - modelNode.setRequirements( Requirements.EXACTLY_ONE ); - /* - * Work around: we need an object in order to call the newBlank method - * from TODO investigate a cleaner way of doing this - */ - modelNode.addChildSpec( ClassRef.processManager, - Helper.collectionToArray( ProcessManager.getAllOptions() ), - Module.Requirements.ZERO_TO_MANY ); - - /* Add existing process managers as child nodes. */ - for ( ProcessManager p : this._processes ) - modelNode.add( p.getModule() ); - return modelNode; - } - - /** - * \brief Helper method for {@link #getModule()}. - * - * @return Model node for the process managers. - */ - private Module getObjectNode() - { - /* The process managers node. */ - Module modelNode = new Module( XmlRef.objects, this ); - modelNode.setRequirements( Requirements.EXACTLY_ONE ); - /* - * TODO add Object child spec - */ - - /* Add existing process managers as child nodes. */ - for (PhysicalObject p : this.agents._physicalObjects ) - modelNode.add( p.getModule() ); - return modelNode; - } - - @Override - public void setModule(Module node) - { - /* Set the modelNode for compartment. */ - if ( node.getTag().equals(this.defaultXmlTag()) ) - { - /* Update the name. */ - this.name = node.getAttribute( XmlRef.nameAttribute ).getValue(); - this._priority = Integer.valueOf(node.getAttribute( - XmlRef.priority ).getValue() ); - - /* set the tree type */ - String tree = node.getAttribute( XmlRef.tree ).getValue(); - if ( ! Helper.isNullOrEmpty( tree ) ) - this.agents.setSpatialTreeType( TreeType.valueOf( tree ) ); - } - /* - * Set the child nodes. - * Agents, process managers and solutes are container nodes: only - * child nodes need to be set here. - */ - Settable.super.setModule(node); - } - - public void removeModule(String specifier) - { - Idynomics.simulator.removeCompartment(this); - } - - @Override - public String defaultXmlTag() - { - return XmlRef.compartment; - } - - @Override - public void setParent(Settable parent) - { - this._parentNode = parent; - } - - @Override - public Settable getParent() - { - return this._parentNode; - } - - /* *********************************************************************** - * Helper methods - * **********************************************************************/ - - public static Compartment findByName( - Collection compartments, String name) - { - for ( Compartment c : compartments ) - if ( c.getName().equals(name) ) - return c; - return null; - } - - public void setScalingFactor(double scFac) - { - this._scalingFactor = scFac; - } - - public double getScalingFactor() - { - return this._scalingFactor; - } - - @Override - public int compareTo(Compartment o) - { - int temp = this._priority - o._priority; - if ( temp != 0 ) - return temp; - else - return this.name.compareTo(o.name); - } -} +package compartment; + +import java.util.Collection; +import java.util.Collections; +import java.util.HashMap; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; +import java.util.TreeMap; + +import org.w3c.dom.Element; + +import agent.Agent; +import boundary.Boundary; +import boundary.SpatialBoundary; +import compartment.agentStaging.Spawner; +import dataIO.Log; +import dataIO.Log.Tier; +import dataIO.XmlHandler; +import generalInterfaces.CanPrelaunchCheck; +import grid.SpatialGrid; +import idynomics.Idynomics; +import instantiable.Instance; +import instantiable.Instantiable; +import instantiable.object.InstantiableList; +import linearAlgebra.Orientation; +import linearAlgebra.Vector; +import physicalObject.PhysicalObject; +import processManager.ProcessComparator; +import processManager.ProcessManager; +import reaction.RegularReaction; +import referenceLibrary.ClassRef; +import referenceLibrary.XmlRef; +import settable.Attribute; +import settable.Module; +import settable.Module.Requirements; +import settable.Settable; +import shape.Dimension.DimName; +import shape.Shape; +import spatialRegistry.TreeType; +import utility.Helper; + +/** + * \brief TODO + * + *

A compartment owns

    + *
  • one shape
  • + *
  • one environment container
  • + *
  • one agent container
  • + *
  • zero to many process managers

+ * + *

The environment container and the agent container both have a reference + * to the shape, but do not know about each other. Agent-environment + * interactions must be mediated by a process manager. Each process manager has + * a reference to the environment container and the agent container, and + * therefore can ask either of these about the compartment shape. It is + * important though, that process managers do not have a reference to the + * compartment they belong to: otherwise, a naive developer could have a + * process manager call the {@code step()} method in {@code Compartment}, + * causing such chaos that even the thought of it keeps Rob awake at night.

+ * + *

In summary, the hierarchy of ownership is: shape -> agent/environment + * containers -> process managers -> compartment. All the arrows point in the + * same direction, meaning no entanglement of the kind iDynoMiCS 1 suffered.

+ * + * @author Robert Clegg (r.j.clegg@bham.ac.uk) University of Birmingham, U.K. + * @author Bastiaan Cockx @BastiaanCockx (baco@env.dtu.dk), DTU, Denmark + * @author Stefan Lang (stefan.lang@uni-jena.de) + * Friedrich-Schiller University Jena, Germany + * @author Sankalp Arya (sankalp.arya@nottingham.ac.uk) University of Nottingham, U.K. + */ +public class Compartment implements CanPrelaunchCheck, Instantiable, Settable, Comparable +{ + /** + * This has a name for reporting purposes. + */ + public String name; + /** + * Shape describes the geometry and size. + * + * TODO also the resolution calculators? + */ + protected Shape _shape; + /** + * Scaling factor determines the ratio of real to modelled size. + * All calculations for boundary movement will use this for scaling up from + * the modelled size to actual biofilm size. + */ + protected double _scalingFactor = 1.0; + /** + * AgentContainer deals with all agents, whether they have spatial location + * or not. + */ + public AgentContainer agents; + /** + * EnvironmentContainer deals with all solutes. + */ + public EnvironmentContainer environment; + /** + * ProcessManagers handle the interactions between agents and solutes. + * The order of the list is important. + */ + protected LinkedList _processes = + new LinkedList(); + /** + * ProcessComparator orders Process Managers by their time priority. + */ + protected ProcessComparator _procComp = new ProcessComparator(); + /** + * Local time should always be between {@code Timer.getCurrentTime()} and + * {@code Timer.getEndOfCurrentTime()}. + */ + // TODO temporary fix, reassess + //protected double _localTime = Idynomics.simulator.timer.getCurrentTime(); + protected double _localTime; + + /** + * the compartment parent node constructor (simulator) + */ + private Settable _parentNode; + + /** + * + */ + private int _priority = Integer.MAX_VALUE; + + /* *********************************************************************** + * CONSTRUCTORS + * **********************************************************************/ + + public Compartment() + { + + } + + public Compartment(String name) + { + this.name = name; + } + + public void remove(Object object) + { + if ( object instanceof ProcessManager ) + this._processes.remove(object); + } + + public Settable newBlank() + { + Compartment newComp = new Compartment(); + return newComp; + } + + /** + * \brief + * + * @param aShape + */ + public void setShape(Shape aShape) + { + if( Log.shouldWrite(Tier.EXPRESSIVE)) + Log.out(Tier.EXPRESSIVE, "Compartment \""+this.name+ + "\" taking shape \""+aShape.getName()+"\""); + this._shape = aShape; + this.environment = new EnvironmentContainer(this._shape); + this.agents = new AgentContainer(this._shape); + } + /** + * \brief Initialise this {@code Compartment} from an XML node. + * + * TODO diffusivity + * @param xmlElem An XML element from a protocol file. + */ + public void instantiate(Element xmlElem, Settable parent) + { + /* + * Compartment initiation + */ + this.name = XmlHandler.obtainAttribute( + xmlElem, XmlRef.nameAttribute, XmlRef.compartment); + if( XmlHandler.hasAttribute(xmlElem, XmlRef.priority)) + this._priority = Integer.valueOf( XmlHandler.gatherAttribute( + xmlElem, XmlRef.priority) ); + Idynomics.simulator.addCompartment(this); + /* + * Set up the shape. + */ + Element elem = XmlHandler.findUniqueChild(xmlElem, XmlRef.compartmentShape); + String[] str = new String[] { XmlHandler.gatherAttribute(elem, XmlRef.classAttribute) }; + if ( str[0] == null ) + str = Shape.getAllOptions(); + this.setShape( (Shape) Instance.getNew(elem, this, str) ); + /* NOTE density scaling is done on individual basis {@Link + * DensityScaling} so agents can maintain constant radius for 2D and 3D + * cases. */ + + double[] simulatedLengths = this.getShape().getDimensionLengths(); + // Check for scale attribute, specifying explicitly provided scale. + String scalingFac = XmlHandler.gatherAttribute(xmlElem, XmlRef.compartmentScale); + if ( !Helper.isNullOrEmpty(scalingFac) ) + { + double scFac = Double.valueOf(scalingFac); + this.setScalingFactor(scFac); + } + // Check for significant dimensions. + else if (simulatedLengths.length != 0) + { + // Scaling factor not provided explicitly, calculate from realLengths + Shape compShape = this.getShape(); + DimName dimN = compShape.getRealDimExtremeName(); + if ( Helper.isNullOrEmpty(compShape.getRealDimExtremeName()) ) + { + double simulatedVolume = compShape.getTotalVolume(); + double realVolume = compShape.getTotalRealVolume(); + this.setScalingFactor(realVolume / simulatedVolume); + } + else + { + double simulatedArea = compShape.getBoundarySurfaceArea(dimN, 1); + double realArea = compShape.getRealSurfaceArea(dimN, 1); + this.setScalingFactor(realArea / simulatedArea); + } + } + + for( Boundary b : this._shape.getAllBoundaries()) + { + b.setContainers(environment, agents); + // FIXME trying to figure out how to get the well mixed region working, + // quite funky investigate +// if (b instanceof SpatialBoundary) +// ((SpatialBoundary) b).setLayerThickness(Double.valueOf( +// XmlHandler.obtainAttribute(xmlElem, +// XmlRef.layerThickness, XmlRef.compartment))); + } + /* + * set container parentNodes + */ + agents.setParent(this); + environment.setParent(this); + /* + * setup tree + */ + String type = XmlHandler.gatherAttribute(xmlElem, XmlRef.tree); + type = Helper.setIfNone(type, String.valueOf( agents.getSpatialTreeType() )); + this.agents.setSpatialTreeType(TreeType.valueOf(type)); + /* + * Look for spawner elements + */ + Spawner spawner; + TreeMap spawners = new TreeMap(); + for ( Element e : XmlHandler.getElements( xmlElem, XmlRef.spawnNode) ) + { + if ( e.hasAttribute( XmlRef.classAttribute ) ) + { + spawner = (Spawner) Instance.getNew(e, this); + /* check for duplicate priority */ + int priority = Helper.nextAvailableKey( + spawner.getPriority(),spawners.keySet() ); + if (spawners.containsKey( spawner.getPriority() )) + { + if( Log.shouldWrite(Tier.EXPRESSIVE)) + Log.out(Tier.EXPRESSIVE, "WARNING: Spawner with " + + "duplicate priority next priority is picked " + + "by simulator."); + } + spawners.put(priority, spawner); + } + } + /* verify whether this always returns in correct order (it should) */ + for( Spawner s : spawners.values() ) + s.spawn(); + + if( Log.shouldWrite(Tier.EXPRESSIVE)) + Log.out(Tier.EXPRESSIVE, "Compartment " + this.name + + " initialised with " + this.agents.getNumAllAgents() + + " agents."); + + /* + * Read in agents. + */ + for ( Element e : XmlHandler.getElements( xmlElem, XmlRef.agent) ) + this.addAgent(new Agent( e, this )); + if( Log.shouldWrite(Tier.EXPRESSIVE)) + Log.out(Tier.EXPRESSIVE, "Compartment "+this.name+" initialised with "+ + this.agents.getNumAllAgents()+" agents"); + /* + * Load solutes. + */ + if( Log.shouldWrite(Tier.EXPRESSIVE)) + Log.out(Tier.EXPRESSIVE, "Compartment reading in solutes"); + Element solutes = XmlHandler.findUniqueChild(xmlElem, XmlRef.solutes); + for ( Element e : XmlHandler.getElements(solutes, XmlRef.solute)) + { + new SpatialGrid( e, this.environment); + } + /* + * Load extra-cellular reactions. + */ + if( Log.shouldWrite(Tier.EXPRESSIVE)) + Log.out(Tier.EXPRESSIVE, "Compartment reading in (environmental) reactions"); + for ( Element e : XmlHandler.getElements( xmlElem, XmlRef.reaction) ) + new RegularReaction(e, this.environment); + /* + * Read in process managers. + */ + if( Log.shouldWrite(Tier.EXPRESSIVE)) + Log.out(Tier.EXPRESSIVE,"Compartment "+this.name+ " loading "+XmlHandler. + getElements(xmlElem, XmlRef.process).size()+" processManagers"); + for ( Element e : XmlHandler.getElements( xmlElem, XmlRef.process) ) + { + this.addProcessManager( + (ProcessManager) Instance.getNew(e, this, (String[])null)); + } + + for ( Element e : XmlHandler.getElements(xmlElem,XmlRef.physicalObject)) + { + this.addPhysicalObject( (PhysicalObject) Instance.getNew(e, this, + PhysicalObject.class.getName())); + } + + /* NOTE: we fetch the class from the xml node */ + elem = XmlHandler.findUniqueChild(xmlElem, XmlRef.orientation); + str = new String[] { XmlHandler.gatherAttribute(elem, XmlRef.variable) }; + if ( str[0] == null ) + { + this.getShape().setOrientation( new Orientation( Vector.zerosDbl( + this._shape.getNumberOfDimensions() ), this ) ); + } else { + this.getShape().setOrientation( (Orientation) Instance.getNew( elem, + this, Orientation.class.getName() ) ); + } + } + + + + /* *********************************************************************** + * BASIC SETTERS & GETTERS + * **********************************************************************/ + + public String getName() + { + return this.name; + } + + public Shape getShape() + { + return this._shape; + } + + public boolean isDimensionless() + { + return this._shape.getNumberOfDimensions() == 0; + } + + public int getNumDims() + { + return this._shape.getNumberOfDimensions(); + } + + public void setSideLengths(double[] sideLengths) + { + this._shape.setDimensionLengths(sideLengths); + } + + /** + * \brief Add a boundary to this compartment's shape. + * + * @param aBoundary Any boundary, whether spatial or non-spatial. + */ + // TODO move this spatial/non-spatial splitting to Shape? + public void addBoundary(Boundary aBoundary) + { + aBoundary.setContainers(this.environment, this.agents); + if ( aBoundary instanceof SpatialBoundary ) + { + SpatialBoundary sB = (SpatialBoundary) aBoundary; + DimName dim = sB.getDimName(); + int extreme = sB.getExtreme(); + this._shape.setBoundary(dim, extreme, sB); + } + else + this._shape.addOtherBoundary(aBoundary); + } + + /** + * \brief Add the given {@code ProcessManager} to the list, making sure + * that it is in the correct place. + * + * @param aProcessManager + */ + public void addProcessManager(ProcessManager aProcessManager) + { + this._processes.add(aProcessManager); + // TODO Rob [18Apr2016]: Check if the process's next time step is + // earlier than the current time. + Collections.sort(this._processes, this._procComp); + } + + /** + * \brief Add the given agent to this compartment. + * + * @param Agent Agent to add. + */ + public void addAgent(Agent agent) + { + + this.agents.addAgent(agent); + agent.setCompartment(this); + } + + public void addPhysicalObject(PhysicalObject p) + { + this.agents._physicalObjects.add(p); + } + + public void addReaction(RegularReaction reaction) + { + this.environment.addReaction(reaction); + } + + public void addSolute(SpatialGrid solute) + { + this.environment.addSolute(solute); + } + + /** + * \brief Remove the given agent from this compartment, registering its + * removal. + * + *

This should be used only removal from the entire simulation, and not + * for transfer to another compartment. For example, cell lysis.

+ * + * @param agent Agent to remove. + */ + public void registerRemoveAgent(Agent agent) + { + agent.setCompartment(null); + this.agents.registerRemoveAgent(agent); + } + + /** + * \brief Get the {@code SpatialGrid} for the given solute name. + * + * @param soluteName {@code String} name of the solute required. + * @return The {@code SpatialGrid} for that solute, or {@code null} if it + * does not exist. + */ + public SpatialGrid getSolute(String soluteName) + { + return this.environment.getSoluteGrid(soluteName); + } + + /* *********************************************************************** + * STEPPING + * **********************************************************************/ + + /** + * \brief Connects any disconnected boundaries to a new partner boundary on + * the appropriate compartment. + * + * Note that generation of spatial boundaries by this method is not yet + * possible. It is therefore necessary to specify spatial boundaries and to + * omit their partners in the protocol file. + * @param compartments List of compartments to choose from. + */ + public void checkBoundaryConnections(Collection compartments) + { + List compartmentNames = new LinkedList(); + for ( Compartment c : compartments ) + compartmentNames.add(c.getName()); + + for ( Boundary b : this._shape.getDisconnectedBoundaries() ) + { + String name = b.getPartnerCompartmentName(); + Compartment comp = findByName(compartments, name); + while ( comp == null ) + { + if( Log.shouldWrite(Tier.CRITICAL) ) + Log.out(Tier.CRITICAL, + "Cannot connect boundary " + b.getName() + + " in compartment " + this.getName()); + name = Helper.obtainInput(compartmentNames, + "Please choose a compartment:", true); + comp = findByName(compartments, name); + } + if( Log.shouldWrite(Tier.EXPRESSIVE) ) + Log.out(Tier.EXPRESSIVE, + "Connecting boundary " + b.getName() + + " to a partner boundary of type " + + b.getPartnerClass().toString() + " in compartment " + + comp.getName()); + Boundary partner = b.makePartnerBoundary(); + comp.addBoundary(partner); + } + } + + /** + * \brief Do all inbound agent & solute transfers. + */ + public void preStep() + { + /* + * Ask all Agents waiting in boundary arrivals lounges to enter the + * compartment now. + */ + this.agents.agentsArrive(); + + this.agents.sortLocatedAgents(); + /* + * Ask all boundaries to update their solute concentrations. + */ + this.environment.updateSoluteBoundaries(); + } + + /** + * \brief Iterate over the process managers until the local time would + * exceed the global time step. + */ + public void step() + { + this._localTime = Idynomics.simulator.timer.getCurrentTime(); + if( Log.shouldWrite(Tier.DEBUG) ) + { + Log.out(Tier.DEBUG, "Compartment "+this.name+ + " at local time "+this._localTime); + } + + if ( this._processes.isEmpty() ) + return; + ProcessManager currentProcess = this._processes.getFirst(); + while ( (this._localTime = currentProcess.getTimeForNextStep() ) + < Idynomics.simulator.timer.getEndOfCurrentIteration() && + Idynomics.simulator.active() ) + { + if( Log.shouldWrite(Tier.DEBUG) ) + Log.out(Tier.DEBUG, "Compartment "+this.name+ + " running process "+currentProcess.getName()+ + " at local time "+this._localTime); + + /* + * First process on the list does its thing. This should then + * increase its next step time. + */ + currentProcess.step(); + /* + * Reinsert this process at the appropriate position in the list. + */ + Collections.sort(this._processes, this._procComp); + /* + * Choose the new first process for the next iteration. + */ + currentProcess = this._processes.getFirst(); + } + } + + /** + * \brief Do all outbound agent & solute transfers. + */ + public void postStep() + { + /* + * Boundaries grab the agents they want, settling any conflicts between + * boundaries. + */ + this.agents.boundariesGrabAgents(); + /* + * Tell all agents queued to leave the compartment to move now. + */ + this.agents.agentsDepart(); + } + + public void process(String process) + { + for ( ProcessManager p : this._processes ) + if( p.getName().equals(process) ) + p.step(); + } + + /* *********************************************************************** + * PRE-LAUNCH CHECK + * **********************************************************************/ + + public boolean isReadyForLaunch() + { + if ( this._shape == null ) + { + Log.out(Tier.CRITICAL, "Compartment shape is undefined!"); + return false; + } + if ( ! this._shape.isReadyForLaunch() ) + return false; + return true; + } + + /* *********************************************************************** + * REPORTING + * **********************************************************************/ + + public void printSoluteGrid(String soluteName) + { + this.environment.printSolute(soluteName); + } + + public void printAllSoluteGrids() + { + this.environment.printAllSolutes(); + } + + /** + * @return TODO + */ + public Map getRealTimeStats() + { + Map out = new HashMap(); + for ( ProcessManager pm : this._processes ) + { + if (out.containsKey(pm.getName())) + out.put(pm.getName(), out.get(pm.getName()) + pm.getRealTimeTaken()); + else + out.put(pm.getName(), pm.getRealTimeTaken()); + } + return out; + } + + /* *********************************************************************** + * Model Node factory + * **********************************************************************/ + + @Override + public Module getModule() + { + /* The compartment node. */ + Module modelNode = new Module(XmlRef.compartment, this); + modelNode.setRequirements(Requirements.ZERO_TO_FEW); + /* Set title for GUI. */ + if ( this.getName() != null ) + modelNode.setTitle(this.getName()); + + /* Add the name attribute. */ + modelNode.add( new Attribute(XmlRef.nameAttribute, + this.getName(), null, true ) ); + modelNode.add( new Attribute(XmlRef.priority, + String.valueOf(this._priority), null, true ) ); + + modelNode.add( new Attribute(XmlRef.compartmentScale, + String.valueOf(this.getScalingFactor()), null, true ) ); + /* Add the shape if it exists. */ + if ( this._shape != null ) + modelNode.add( this._shape.getModule() ); + /* Add the Environment node. */ + modelNode.add( this.environment.getModule() ); + /* Add the Agents node. */ + modelNode.add( this.agents.getModule() ); + + /* Add the process managers node. */ + modelNode.add( this.getProcessNode() ); + + modelNode.add( getObjectNode() ); + + /* spatial registry NOTE we are handling this here since the agent + * container does not have the proper init infrastructure */ + modelNode.add( new Attribute(XmlRef.tree, + String.valueOf( this.agents.getSpatialTreeType() ) , + Helper.enumToStringArray( TreeType.class ), false ) ); + + return modelNode; + } + + /** + * \brief Helper method for {@link #getModule()}. + * + * @return Model node for the process managers. + */ + private Module getProcessNode() + { + /* The process managers node. */ + Module modelNode = new Module( XmlRef.processManagers, this ); + modelNode.setRequirements( Requirements.EXACTLY_ONE ); + /* + * Work around: we need an object in order to call the newBlank method + * from TODO investigate a cleaner way of doing this + */ + modelNode.addChildSpec( ClassRef.processManager, + Helper.collectionToArray( ProcessManager.getAllOptions() ), + Module.Requirements.ZERO_TO_MANY ); + + /* Add existing process managers as child nodes. */ + for ( ProcessManager p : this._processes ) + modelNode.add( p.getModule() ); + return modelNode; + } + + /** + * \brief Helper method for {@link #getModule()}. + * + * @return Model node for the process managers. + */ + private Module getObjectNode() + { + /* The process managers node. */ + Module modelNode = new Module( XmlRef.objects, this ); + modelNode.setRequirements( Requirements.EXACTLY_ONE ); + /* + * TODO add Object child spec + */ + + /* Add existing process managers as child nodes. */ + for (PhysicalObject p : this.agents._physicalObjects ) + modelNode.add( p.getModule() ); + return modelNode; + } + + @Override + public void setModule(Module node) + { + /* Set the modelNode for compartment. */ + if ( node.getTag().equals(this.defaultXmlTag()) ) + { + /* Update the name. */ + this.name = node.getAttribute( XmlRef.nameAttribute ).getValue(); + this._priority = Integer.valueOf(node.getAttribute( + XmlRef.priority ).getValue() ); + + /* set the tree type */ + String tree = node.getAttribute( XmlRef.tree ).getValue(); + if ( ! Helper.isNullOrEmpty( tree ) ) + this.agents.setSpatialTreeType( TreeType.valueOf( tree ) ); + } + /* + * Set the child nodes. + * Agents, process managers and solutes are container nodes: only + * child nodes need to be set here. + */ + Settable.super.setModule(node); + } + + public void removeModule(String specifier) + { + Idynomics.simulator.removeCompartment(this); + } + + @Override + public String defaultXmlTag() + { + return XmlRef.compartment; + } + + @Override + public void setParent(Settable parent) + { + this._parentNode = parent; + } + + @Override + public Settable getParent() + { + return this._parentNode; + } + + /* *********************************************************************** + * Helper methods + * **********************************************************************/ + + public static Compartment findByName( + Collection compartments, String name) + { + for ( Compartment c : compartments ) + if ( c.getName().equals(name) ) + return c; + return null; + } + + public void setScalingFactor(double scFac) + { + this._scalingFactor = scFac; + } + + public double getScalingFactor() + { + return this._scalingFactor; + } + + @Override + public int compareTo(Compartment o) + { + int temp = this._priority - o._priority; + if ( temp != 0 ) + return temp; + else + return this.name.compareTo(o.name); + } +} diff --git a/src/dataIO/CumulativeLoad.java b/src/dataIO/CumulativeLoad.java index 157b33158..e2f34714d 100644 --- a/src/dataIO/CumulativeLoad.java +++ b/src/dataIO/CumulativeLoad.java @@ -6,10 +6,12 @@ import org.w3c.dom.Element; import org.w3c.dom.NodeList; +import aspect.AspectReg; import compartment.Compartment; import idynomics.Idynomics; import instantiable.Instance; import processManager.ProcessManager; +import referenceLibrary.AspectRef; import referenceLibrary.XmlRef; import utility.Helper; @@ -38,13 +40,19 @@ public String test() return ""; } - public void postProcess() + public void postProcess(int num) { Compartment comp = null; for ( Element e : XmlHandler.getElements( document, XmlRef.process) ) { - comp.addProcessManager( - (ProcessManager) Instance.getNew(e, comp, (String[])null)); + String name = XmlHandler.gatherAttribute(e, XmlRef.nameAttribute); + String compartment = XmlHandler.gatherAttribute(e.getParentNode(), XmlRef.nameAttribute); + comp = Idynomics.simulator.getCompartment(compartment); + ProcessManager p = (ProcessManager) Instance.getNew(e, comp, (String[])null); + p.set(AspectRef.fileNumber, num); + comp.addProcessManager( p ); + comp.process(name); + } } diff --git a/src/dataIO/GraphicalExporter.java b/src/dataIO/GraphicalExporter.java index 8873c5c0e..e65d141a0 100644 --- a/src/dataIO/GraphicalExporter.java +++ b/src/dataIO/GraphicalExporter.java @@ -177,5 +177,7 @@ public default void init(String _prefix, Shape shape) } public void createCustomFile(String fileName); + + public void setFileNumber(Integer number); } diff --git a/src/dataIO/PovExport.java b/src/dataIO/PovExport.java index f356d33a0..49647caaa 100644 --- a/src/dataIO/PovExport.java +++ b/src/dataIO/PovExport.java @@ -83,7 +83,10 @@ public void createCustomFile(String fileName) } - + public void setFileNumber(Integer number) + { + this._filewriterfilenr = number; + } /** * diff --git a/src/dataIO/SvgExport.java b/src/dataIO/SvgExport.java index b03f593d7..7731ec4f9 100644 --- a/src/dataIO/SvgExport.java +++ b/src/dataIO/SvgExport.java @@ -108,6 +108,12 @@ public void closeFile() * */ + + public void setFileNumber(Integer number) + { + this._filewriterfilenr = number; + } + /** * */ diff --git a/src/gui/GuiActions.java b/src/gui/GuiActions.java index f3af2bead..f3ee2cc99 100644 --- a/src/gui/GuiActions.java +++ b/src/gui/GuiActions.java @@ -65,7 +65,7 @@ public static File chooseFile(String relPath, String description) { /* Open a FileChooser window in the current directory. */ JFileChooser chooser = new JFileChooser("" + - System.getProperty("user.dir")+"/protocol"); + System.getProperty("user.dir")+"/"+relPath); chooser.setFileSelectionMode(JFileChooser.FILES_ONLY); // TODO Allow the user to select multiple files. chooser.setMultiSelectionEnabled(false); diff --git a/src/idynomics/PostProcess.java b/src/idynomics/PostProcess.java index c6936893a..8881485cc 100644 --- a/src/idynomics/PostProcess.java +++ b/src/idynomics/PostProcess.java @@ -29,9 +29,13 @@ public PostProcess(File script, List files) @Override public void run() { + int num = 0; for( File f : _files) { Idynomics.setupSimulator( f.getAbsolutePath() ); + loader.postProcess(num); + Idynomics.simulator = new Simulator(); + num++; } } } diff --git a/src/processManager/ProcessManager.java b/src/processManager/ProcessManager.java index 57c60a7fd..357595ae4 100644 --- a/src/processManager/ProcessManager.java +++ b/src/processManager/ProcessManager.java @@ -1,433 +1,433 @@ -package processManager; - -import java.math.BigDecimal; -import java.util.List; - -import org.w3c.dom.Element; - -import aspect.AspectInterface; -import aspect.AspectReg; -import compartment.AgentContainer; -import compartment.Compartment; -import compartment.EnvironmentContainer; -import dataIO.Log; -import dataIO.Log.Tier; -import dataIO.XmlHandler; -import generalInterfaces.Redirectable; -import idynomics.Idynomics; -import instantiable.Instantiable; -import referenceLibrary.ClassRef; -import referenceLibrary.XmlRef; -import settable.Attribute; -import settable.Module; -import settable.Module.Requirements; -import settable.Settable; -import utility.Helper; - -/** - * \brief Abstract class for managing a process within a {@code Compartment}. - * - * @author Robert Clegg (r.j.clegg@bham.ac.uk) University of Birmingham, U.K. - * @author Bastiaan Cockx @BastiaanCockx (baco@env.dtu.dk), DTU, Denmark. - */ -public abstract class ProcessManager implements Instantiable, AspectInterface, - Settable, Redirectable -{ - /** - * The name of this {@code ProcessManager}, for reporting. - */ - protected String _name; - /** - * In the event of a time-clash between {@code ProcessManager}s, the one - * with greater priority goes first. - */ - protected int _priority; - /** - * The time at which this should next perform its step. - */ - protected double _timeForNextStep = 0.0; - /** - * How often this should perform its step. - */ - protected double _timeStepSize; - /** - * Force one internal step before simulation. - */ - protected int _skips = 0; - /** - * How often this has been skipped since last run. - */ - private int _skipped = 0; - /** - * The aspect registry. - */ - private AspectReg _aspectRegistry = new AspectReg(); - /** - * Reference to the environment of the compartment this process belongs to. - * Contains a reference to the compartment shape. - */ - protected EnvironmentContainer _environment; - /** - * Reference to the agents of the compartment this process belongs to. - * Contains a reference to the compartment shape. - */ - protected AgentContainer _agents; - - /** - * - */ - protected String _compartmentName; - - /** - * Parent (owner) node, used for proper object removal via gui. - */ - protected Settable _parentNode; - - /** - * Used to track time used per process manager - */ - private long _realTimeTaken = 0; - - /** - * Used to track time used per process manager - */ - private long _tick; - - /* *********************************************************************** - * CONSTRUCTORS - * **********************************************************************/ - - /** - * Generic init for Instantiatable implementation - * - * - * NOTE this implementation is a bit 'hacky' to deal with - * 1) The layered structure of process managers. - * 2) The fact that process managers are initiated with environment, agents - * and compartment name, something the instantiatable interface can only - * Provide by supplying parent. - * - * - * @param xmlElem - * @param parent (in this case the compartment). - */ - public void instantiate(Element xmlElem, Settable parent) - { - this.init(xmlElem, ((Compartment) parent).environment, - ((Compartment) parent).agents,((Compartment) parent).getName()); - } - - /** - * \brief Initialise the process from XML protocol file, plus the relevant - * information about the compartment it belongs to. - * - * @param xmlElem Relevant part of the XML protocol file. - * @param environment The {@code EnvironmentContainer} of the - * {@code Compartment} this process belongs to. - * @param agents The {@code AgentContainer} of the - * {@code Compartment} this process belongs to. - * @param compartmentName The name of the {@code Compartment} this process - * belongs to. - */ - public void init(Element xmlElem, EnvironmentContainer environment, - AgentContainer agents, String compartmentName) - { - this._environment = environment; - this._agents = agents; - this._compartmentName = compartmentName; - - if (xmlElem != null) - this.loadAspects(xmlElem); - /* - * Read in the process attributes. - */ - Element p = (Element) xmlElem; - if (Helper.isNullOrEmpty(this._name)) - this.setName( XmlHandler.obtainAttribute(p, XmlRef.nameAttribute, - this.defaultXmlTag())); - /* Process priority - default is zero. */ - int priority = 0; - if ( XmlHandler.hasAttribute(p, XmlRef.processPriority) ) - priority = Integer.valueOf(p.getAttribute(XmlRef.processPriority) ); - this.setPriority(priority); - /* Initial time to step. */ - double time = Idynomics.simulator.timer.getCurrentTime(); - if ( XmlHandler.hasAttribute(p, XmlRef.processFirstStep) ) - time = Double.valueOf(p.getAttribute(XmlRef.processFirstStep) ); - this.setTimeForNextStep(time); - /* Time step size. */ - time = Idynomics.simulator.timer.getTimeStepSize(); - if ( XmlHandler.hasAttribute(p, XmlRef.processTimeStepSize) ) - time = Double.valueOf( p.getAttribute(XmlRef.processTimeStepSize)); - this.setTimeStepSize(time); - if ( XmlHandler.hasAttribute(p, XmlRef.processSkips )) - { - this._skips = Integer.valueOf( p.getAttribute(XmlRef.processSkips)); - } - this.redirect(xmlElem); - if( Log.shouldWrite(Tier.EXPRESSIVE)) - Log.out(Tier.EXPRESSIVE, this._name + " loaded"); - } - - /* *********************************************************************** - * BASIC SETTERS & GETTERS - * ***********************************************************************/ - - /** - * \brief Return the aspect registry (implementation of aspect interface). - */ - public AspectReg reg() - { - return _aspectRegistry; - } - - /** - * \brief Get this {@code ProcessManager}'s name. - * - * @return {@code String} name. - */ - public String getName() - { - if (this._name == null) - return ""; - else - return this._name; - } - - /** - * \brief Set this {@code ProcessManager}'s name. - * - * @param {@code String} name. - */ - public void setName(String name) - { - this._name = name; - } - - /** - * \brief Set the priority of this {@code ProcessManager}. - * - *

A higher priority {@code ProcessManager} goes first if two have a - * time clash in the {@code Compartment} they belong to.

- * - * @param priority Any integer value. - */ - public void setPriority(int priority) - { - this._priority = priority; - } - - /** - * @return The priority of this {@code ProcessManager}. - */ - public int getPriority() - { - return this._priority; - } - - /**] - * \brief Set the time point at which this will next step: useful for - * testing. - * - * @param newTime The time point at which this should next step. - */ - public void setTimeForNextStep(double newTime) - { - this._timeForNextStep = newTime; - } - - /** - * @return The time point at which this will next step. - */ - public double getTimeForNextStep() - { - return this._timeForNextStep; - } - - /** - * \brief Set the time step directly: useful for testing. - * - * @param newStepSize Time step to use. - */ - public void setTimeStepSize(double newStepSize) - { - this._timeStepSize = newStepSize; - } - - /** - * @return The local time step. - */ - public double getTimeStepSize() - { - return this._timeStepSize; - } - - /* *********************************************************************** - * STEPPING - * **********************************************************************/ - - /** - * \brief Perform the step of this process manager, also updating its local - * time manager. - * - * @param environment The {@code EnvironmentContainer} of the - * {@code Compartment} this process belongs to. - * @param agents The {@code AgentContainer} of the - * {@code Compartment} this process belongs to. - */ - public void step() - { - double now = this._timeForNextStep; - /* Move the time for next step forward by the step size. */ - this._timeForNextStep = BigDecimal.valueOf( _timeForNextStep ).add( - BigDecimal.valueOf( _timeStepSize ) ).doubleValue(); - - if ( this._skips > ++this._skipped ) - { - /* skip */ - } - else - { - this._tick = System.currentTimeMillis(); - /*This is where subclasses of ProcessManager do their step. Note - * that this._timeStepSize may change if an adaptive timestep is - * used. */ - this.internalStep(); - if ( !Idynomics.simulator.active()) - return; - - Tier level = Tier.EXPRESSIVE; - if ( Log.shouldWrite(level) ) - { - /* logging time, using BigDecimal prevents weird last decimal - * round-off errors. */ - Log.out( level, this._name + ": " + now + " -> " + - this._timeForNextStep + " (" + ( BigDecimal.valueOf( - System.currentTimeMillis() - _tick ).multiply( - BigDecimal.valueOf( 0.001 ) ).doubleValue() ) + "s)"); - } - this._realTimeTaken += (System.currentTimeMillis() - _tick); - this._skipped = 0; - } - } - - /** - * \brief Perform the internal step for this process manager: this will be - * implemented by each sub-class of {@code ProcessManager}. - */ - protected abstract void internalStep(); - - /* *********************************************************************** - * REPORTING - * **********************************************************************/ - - public long getRealTimeTaken() - { - return this._realTimeTaken; - } - - /* *********************************************************************** - * NODE CONSTRUCTION - * **********************************************************************/ - - /** - * \brief returns all known (ClassRef) process managers - * @return all known (ClassRef) process managers - */ - public static List getAllOptions() - { - return ClassRef.getAllOptions("processManager.library"); - } - - /** - * Obtain module for xml output and gui representation. - */ - public Module getModule() - { - Module modelNode = new Module(defaultXmlTag(), this); - modelNode.setRequirements(Requirements.ZERO_TO_MANY); - modelNode.setTitle(this._name); - - modelNode.add(new Attribute(XmlRef.nameAttribute, - this._name, null, true )); - - if ( Idynomics.xmlPackageLibrary.has( this.getClass().getSimpleName() )) - modelNode.add(new Attribute(XmlRef.classAttribute, - this.getClass().getSimpleName(), null, false )); - else - modelNode.add(new Attribute(XmlRef.classAttribute, - this.getClass().getName(), null, false )); - - modelNode.add(new Attribute(XmlRef.processPriority, - String.valueOf(this._priority), null, true )); - - modelNode.add(new Attribute(XmlRef.processTimeStepSize, - String.valueOf(this._timeStepSize), null, true )); - - modelNode.add(new Attribute(XmlRef.processFirstStep, - String.valueOf(this._timeForNextStep), null, true )); - - for ( String key : this.reg().getLocalAspectNames() ) - modelNode.add(reg().getAspectNode(key)); - - modelNode.addChildSpec( ClassRef.aspect, - Module.Requirements.ZERO_TO_MANY); - - return modelNode; - } - - - /** - * Set value's that (may) have been changed trough the gui. - */ - public void setModule(Module node) - { - /* Set the name */ - this._name = node.getAttribute( XmlRef.nameAttribute ).getValue(); - - /* Set the priority */ - this._priority = Integer.valueOf( node.getAttribute( - XmlRef.processPriority ).getValue() ); - - /* Set the timestep */ - this._timeStepSize = Double.valueOf( node.getAttribute( - XmlRef.processTimeStepSize ).getValue() ); - - /* Set the time for the first step from now */ - this._timeForNextStep = Double.valueOf( node.getAttribute( - XmlRef.processFirstStep ).getValue() ); - - /* Set any potential child modules */ - Settable.super.setModule(node); - } - - /** - * Remove processManager from the compartment - * NOTE a bit of a work around but this prevents the pm form having to have - * access to the compartment directly - */ - public void removeModule(String specifier) - { - Idynomics.simulator.deleteFromCompartment(this._compartmentName, this); - } - - /** - * - */ - public String defaultXmlTag() - { - return XmlRef.process; - } - - - public void setParent(Settable parent) - { - this._parentNode = parent; - } - - @Override - public Settable getParent() - { - return this._parentNode; - } +package processManager; + +import java.math.BigDecimal; +import java.util.List; + +import org.w3c.dom.Element; + +import aspect.AspectInterface; +import aspect.AspectReg; +import compartment.AgentContainer; +import compartment.Compartment; +import compartment.EnvironmentContainer; +import dataIO.Log; +import dataIO.Log.Tier; +import dataIO.XmlHandler; +import generalInterfaces.Redirectable; +import idynomics.Idynomics; +import instantiable.Instantiable; +import referenceLibrary.ClassRef; +import referenceLibrary.XmlRef; +import settable.Attribute; +import settable.Module; +import settable.Module.Requirements; +import settable.Settable; +import utility.Helper; + +/** + * \brief Abstract class for managing a process within a {@code Compartment}. + * + * @author Robert Clegg (r.j.clegg@bham.ac.uk) University of Birmingham, U.K. + * @author Bastiaan Cockx @BastiaanCockx (baco@env.dtu.dk), DTU, Denmark. + */ +public abstract class ProcessManager implements Instantiable, AspectInterface, + Settable, Redirectable +{ + /** + * The name of this {@code ProcessManager}, for reporting. + */ + protected String _name; + /** + * In the event of a time-clash between {@code ProcessManager}s, the one + * with greater priority goes first. + */ + protected int _priority; + /** + * The time at which this should next perform its step. + */ + protected double _timeForNextStep = 0.0; + /** + * How often this should perform its step. + */ + protected double _timeStepSize; + /** + * Force one internal step before simulation. + */ + protected int _skips = 0; + /** + * How often this has been skipped since last run. + */ + private int _skipped = 0; + /** + * The aspect registry. + */ + private AspectReg _aspectRegistry = new AspectReg(); + /** + * Reference to the environment of the compartment this process belongs to. + * Contains a reference to the compartment shape. + */ + protected EnvironmentContainer _environment; + /** + * Reference to the agents of the compartment this process belongs to. + * Contains a reference to the compartment shape. + */ + protected AgentContainer _agents; + + /** + * + */ + protected String _compartmentName; + + /** + * Parent (owner) node, used for proper object removal via gui. + */ + protected Settable _parentNode; + + /** + * Used to track time used per process manager + */ + private long _realTimeTaken = 0; + + /** + * Used to track time used per process manager + */ + private long _tick; + + /* *********************************************************************** + * CONSTRUCTORS + * **********************************************************************/ + + /** + * Generic init for Instantiatable implementation + * + * + * NOTE this implementation is a bit 'hacky' to deal with + * 1) The layered structure of process managers. + * 2) The fact that process managers are initiated with environment, agents + * and compartment name, something the instantiatable interface can only + * Provide by supplying parent. + * + * + * @param xmlElem + * @param parent (in this case the compartment). + */ + public void instantiate(Element xmlElem, Settable parent) + { + this.init(xmlElem, ((Compartment) parent).environment, + ((Compartment) parent).agents,((Compartment) parent).getName()); + } + + /** + * \brief Initialise the process from XML protocol file, plus the relevant + * information about the compartment it belongs to. + * + * @param xmlElem Relevant part of the XML protocol file. + * @param environment The {@code EnvironmentContainer} of the + * {@code Compartment} this process belongs to. + * @param agents The {@code AgentContainer} of the + * {@code Compartment} this process belongs to. + * @param compartmentName The name of the {@code Compartment} this process + * belongs to. + */ + public void init(Element xmlElem, EnvironmentContainer environment, + AgentContainer agents, String compartmentName) + { + this._environment = environment; + this._agents = agents; + this._compartmentName = compartmentName; + + if (xmlElem != null) + this.loadAspects(xmlElem); + /* + * Read in the process attributes. + */ + Element p = (Element) xmlElem; + if (Helper.isNullOrEmpty(this._name)) + this.setName( XmlHandler.obtainAttribute(p, XmlRef.nameAttribute, + this.defaultXmlTag())); + /* Process priority - default is zero. */ + int priority = 0; + if ( XmlHandler.hasAttribute(p, XmlRef.processPriority) ) + priority = Integer.valueOf(p.getAttribute(XmlRef.processPriority) ); + this.setPriority(priority); + /* Initial time to step. */ + double time = Idynomics.simulator.timer.getCurrentTime(); + if ( XmlHandler.hasAttribute(p, XmlRef.processFirstStep) ) + time = Double.valueOf(p.getAttribute(XmlRef.processFirstStep) ); + this.setTimeForNextStep(time); + /* Time step size. */ + time = Idynomics.simulator.timer.getTimeStepSize(); + if ( XmlHandler.hasAttribute(p, XmlRef.processTimeStepSize) ) + time = Double.valueOf( p.getAttribute(XmlRef.processTimeStepSize)); + this.setTimeStepSize(time); + if ( XmlHandler.hasAttribute(p, XmlRef.processSkips )) + { + this._skips = Integer.valueOf( p.getAttribute(XmlRef.processSkips)); + } + this.redirect(xmlElem); + if( Log.shouldWrite(Tier.EXPRESSIVE)) + Log.out(Tier.EXPRESSIVE, this._name + " loaded"); + } + + /* *********************************************************************** + * BASIC SETTERS & GETTERS + * ***********************************************************************/ + + /** + * \brief Return the aspect registry (implementation of aspect interface). + */ + public AspectReg reg() + { + return _aspectRegistry; + } + + /** + * \brief Get this {@code ProcessManager}'s name. + * + * @return {@code String} name. + */ + public String getName() + { + if (this._name == null) + return ""; + else + return this._name; + } + + /** + * \brief Set this {@code ProcessManager}'s name. + * + * @param {@code String} name. + */ + public void setName(String name) + { + this._name = name; + } + + /** + * \brief Set the priority of this {@code ProcessManager}. + * + *

A higher priority {@code ProcessManager} goes first if two have a + * time clash in the {@code Compartment} they belong to.

+ * + * @param priority Any integer value. + */ + public void setPriority(int priority) + { + this._priority = priority; + } + + /** + * @return The priority of this {@code ProcessManager}. + */ + public int getPriority() + { + return this._priority; + } + + /**] + * \brief Set the time point at which this will next step: useful for + * testing. + * + * @param newTime The time point at which this should next step. + */ + public void setTimeForNextStep(double newTime) + { + this._timeForNextStep = newTime; + } + + /** + * @return The time point at which this will next step. + */ + public double getTimeForNextStep() + { + return this._timeForNextStep; + } + + /** + * \brief Set the time step directly: useful for testing. + * + * @param newStepSize Time step to use. + */ + public void setTimeStepSize(double newStepSize) + { + this._timeStepSize = newStepSize; + } + + /** + * @return The local time step. + */ + public double getTimeStepSize() + { + return this._timeStepSize; + } + + /* *********************************************************************** + * STEPPING + * **********************************************************************/ + + /** + * \brief Perform the step of this process manager, also updating its local + * time manager. + * + * @param environment The {@code EnvironmentContainer} of the + * {@code Compartment} this process belongs to. + * @param agents The {@code AgentContainer} of the + * {@code Compartment} this process belongs to. + */ + public void step() + { + double now = this._timeForNextStep; + /* Move the time for next step forward by the step size. */ + this._timeForNextStep = BigDecimal.valueOf( _timeForNextStep ).add( + BigDecimal.valueOf( _timeStepSize ) ).doubleValue(); + + if ( this._skips > ++this._skipped ) + { + /* skip */ + } + else + { + this._tick = System.currentTimeMillis(); + /*This is where subclasses of ProcessManager do their step. Note + * that this._timeStepSize may change if an adaptive timestep is + * used. */ + this.internalStep(); + if ( !Idynomics.simulator.active()) + return; + + Tier level = Tier.EXPRESSIVE; + if ( Log.shouldWrite(level) ) + { + /* logging time, using BigDecimal prevents weird last decimal + * round-off errors. */ + Log.out( level, this._name + ": " + now + " -> " + + this._timeForNextStep + " (" + ( BigDecimal.valueOf( + System.currentTimeMillis() - _tick ).multiply( + BigDecimal.valueOf( 0.001 ) ).doubleValue() ) + "s)"); + } + this._realTimeTaken += (System.currentTimeMillis() - _tick); + this._skipped = 0; + } + } + + /** + * \brief Perform the internal step for this process manager: this will be + * implemented by each sub-class of {@code ProcessManager}. + */ + protected abstract void internalStep(); + + /* *********************************************************************** + * REPORTING + * **********************************************************************/ + + public long getRealTimeTaken() + { + return this._realTimeTaken; + } + + /* *********************************************************************** + * NODE CONSTRUCTION + * **********************************************************************/ + + /** + * \brief returns all known (ClassRef) process managers + * @return all known (ClassRef) process managers + */ + public static List getAllOptions() + { + return ClassRef.getAllOptions("processManager.library"); + } + + /** + * Obtain module for xml output and gui representation. + */ + public Module getModule() + { + Module modelNode = new Module(defaultXmlTag(), this); + modelNode.setRequirements(Requirements.ZERO_TO_MANY); + modelNode.setTitle(this._name); + + modelNode.add(new Attribute(XmlRef.nameAttribute, + this._name, null, true )); + + if ( Idynomics.xmlPackageLibrary.has( this.getClass().getSimpleName() )) + modelNode.add(new Attribute(XmlRef.classAttribute, + this.getClass().getSimpleName(), null, false )); + else + modelNode.add(new Attribute(XmlRef.classAttribute, + this.getClass().getName(), null, false )); + + modelNode.add(new Attribute(XmlRef.processPriority, + String.valueOf(this._priority), null, true )); + + modelNode.add(new Attribute(XmlRef.processTimeStepSize, + String.valueOf(this._timeStepSize), null, true )); + + modelNode.add(new Attribute(XmlRef.processFirstStep, + String.valueOf(this._timeForNextStep), null, true )); + + for ( String key : this.reg().getLocalAspectNames() ) + modelNode.add(reg().getAspectNode(key)); + + modelNode.addChildSpec( ClassRef.aspect, + Module.Requirements.ZERO_TO_MANY); + + return modelNode; + } + + + /** + * Set value's that (may) have been changed trough the gui. + */ + public void setModule(Module node) + { + /* Set the name */ + this._name = node.getAttribute( XmlRef.nameAttribute ).getValue(); + + /* Set the priority */ + this._priority = Integer.valueOf( node.getAttribute( + XmlRef.processPriority ).getValue() ); + + /* Set the timestep */ + this._timeStepSize = Double.valueOf( node.getAttribute( + XmlRef.processTimeStepSize ).getValue() ); + + /* Set the time for the first step from now */ + this._timeForNextStep = Double.valueOf( node.getAttribute( + XmlRef.processFirstStep ).getValue() ); + + /* Set any potential child modules */ + Settable.super.setModule(node); + } + + /** + * Remove processManager from the compartment + * NOTE a bit of a work around but this prevents the pm form having to have + * access to the compartment directly + */ + public void removeModule(String specifier) + { + Idynomics.simulator.deleteFromCompartment(this._compartmentName, this); + } + + /** + * + */ + public String defaultXmlTag() + { + return XmlRef.process; + } + + + public void setParent(Settable parent) + { + this._parentNode = parent; + } + + @Override + public Settable getParent() + { + return this._parentNode; + } } \ No newline at end of file diff --git a/src/processManager/library/GraphicalOutput.java b/src/processManager/library/GraphicalOutput.java index 072977d21..06b0a37e4 100644 --- a/src/processManager/library/GraphicalOutput.java +++ b/src/processManager/library/GraphicalOutput.java @@ -128,7 +128,6 @@ public void init(Element xmlElem, EnvironmentContainer environment, str = Helper.obtainIfNone( this.getString(OUTPUT_WRITER), "output writer", true, this.options() ); this._graphics = (GraphicalExporter) Instance.getNew(null, null, str); - /* write scene files (used by pov ray) */ this._graphics.init( this._prefix, this._shape ); @@ -152,6 +151,8 @@ private Collection options() @Override protected void internalStep() { + if ( this.getInt(AspectRef.fileNumber) != null ) + this._graphics.setFileNumber(this.getInt(AspectRef.fileNumber)); /* Initiate new file. */ this._graphics.createFile(this._prefix); diff --git a/src/referenceLibrary/AspectRef.java b/src/referenceLibrary/AspectRef.java index cfedadf5e..14123bd09 100644 --- a/src/referenceLibrary/AspectRef.java +++ b/src/referenceLibrary/AspectRef.java @@ -580,4 +580,6 @@ public static String[] getAllOptions() public static final String decompressionCellLength = "decompressionCellLength"; public static final String decompressionThreshold = "decompressionThreshold"; + + public static final String fileNumber = "fileNumber"; } From 3799597b7e84942ca1d4eeec4b7302a098f5970f Mon Sep 17 00:00:00 2001 From: baseendje Date: Mon, 15 Jun 2020 13:48:30 +0200 Subject: [PATCH 04/67] test processing script --- postprocessing/test.xml | 8 ++++++++ 1 file changed, 8 insertions(+) create mode 100644 postprocessing/test.xml diff --git a/postprocessing/test.xml b/postprocessing/test.xml new file mode 100644 index 000000000..51577a8e8 --- /dev/null +++ b/postprocessing/test.xml @@ -0,0 +1,8 @@ + + + + + + + \ No newline at end of file From 5ccce7278cb9c4168ba8b2e8fe0f9e66b720bf4b Mon Sep 17 00:00:00 2001 From: baseendje Date: Mon, 15 Jun 2020 16:38:01 +0200 Subject: [PATCH 05/67] implementing file conversion, looking for bug --- src/dataIO/XmlExport.java | 21 ++++++++- src/gui/GuiActions.java | 82 ++++++++++++++++++++++++++++++++++++ src/gui/GuiMenu.java | 54 ++++++++++++++++++++++++ src/idynomics/Simulator.java | 6 +++ 4 files changed, 162 insertions(+), 1 deletion(-) diff --git a/src/dataIO/XmlExport.java b/src/dataIO/XmlExport.java index d782f8f70..cb527d7c4 100644 --- a/src/dataIO/XmlExport.java +++ b/src/dataIO/XmlExport.java @@ -87,7 +87,19 @@ public void newXml(String prefix) this._xmlFile.write(XML_HEADER); } - + public void newXml(String filePath, boolean absolutePath) + { + String fileString; + if( this._exiEncoding ) + this._xmlFile.bufferOutput(); + if( absolutePath ) + fileString = filePath + (this._exiEncoding ? ".exi" : ".xml"); + else + fileString = Idynomics.global.outputLocation + filePath + + (this._exiEncoding ? ".exi" : ".xml"); + this._xmlFile.fnew(fileString); + this._xmlFile.write(XML_HEADER); + } /** * Close the XML file and increment the file number counter for the next @@ -118,4 +130,11 @@ public void writeFile() this.writeState(); this.closeXml(); } + + public void writeFile(String file) + { + this.newXml(file, true); + this.writeState(); + this.closeXml(); + } } diff --git a/src/gui/GuiActions.java b/src/gui/GuiActions.java index f3ee2cc99..301f082a7 100644 --- a/src/gui/GuiActions.java +++ b/src/gui/GuiActions.java @@ -61,6 +61,29 @@ public static void chooseFile() openFile(f); } + public static File saveFile() + { + boolean confirm = true; + + JFileChooser chooser = new JFileChooser("" + + System.getProperty("user.dir")); + File file = new File(System.getProperty("user.dir")+ "/filename"); + chooser.setFileSelectionMode(JFileChooser.SAVE_DIALOG); + chooser.setCurrentDirectory(file); + // TODO Allow the user to select multiple files. + chooser.setMultiSelectionEnabled(false); + File f = null; + if ( chooser.showSaveDialog(null) == JFileChooser.APPROVE_OPTION ) + f = chooser.getSelectedFile(); + if( f.exists() ) + confirm = Helper.confirmation("Would you like to overwrite: " + + f.getName()); + if( confirm ) + return f; + else + return null; + } + public static File chooseFile(String relPath, String description) { /* Open a FileChooser window in the current directory. */ @@ -225,6 +248,65 @@ public static void downloadFile(String url) openFile(in); } + public static void saveToFile(File f) + { + if ( f == null ) + { + GuiConsole.writeOut("Saving canceled.\n"); + } + else + { + Idynomics.simulator.saveSimulationState(f.getAbsolutePath(), + Helper.confirmation("Would you like to compress to exi format?")); + } + } + + public static void convertFiles() + { + File[] files = chooseFilesAndFolders( + "Select simulation state files (.exi or .xml)" ); + List finalFiles = null; + if( FolderOperations.includesfolders(files)) + { + if( Helper.obtainInput( + "Would you like to include sub-folders?", false) ) + /* note do look into the first line of folders */ + finalFiles = FolderOperations.getFiles(true, files); + else + finalFiles = FolderOperations.getFiles(files); + } + else + { + finalFiles = FolderOperations.getFiles(true, files); + } + if( Helper.obtainInput( "Would you like to continue processing " + + finalFiles.size() + " files?", false) ) + { + for( File f : files ) + { + boolean exi = false; + String out = null; + String path = f.getAbsolutePath(); + if( path.toLowerCase().contains(".xml")) + { + exi = true; + out = path.toLowerCase().replaceAll(".xml", ".exi"); + } else if( path.toLowerCase().contains(".exi")) + { + exi = false; + out = path.toLowerCase().replaceAll(".exi", ".xml"); + } + Idynomics.setupSimulator( f.getAbsolutePath() ); + Idynomics.simulator.saveSimulationState(out, exi); + Idynomics.simulator = new Simulator(); + } + } + else + { + Log.out("post-processing cancelled by user"); + } + } + public static void checkProtocol() { if ( Idynomics.global.protocolFile == null ) diff --git a/src/gui/GuiMenu.java b/src/gui/GuiMenu.java index 6ba2c1b04..1ff4f4de0 100644 --- a/src/gui/GuiMenu.java +++ b/src/gui/GuiMenu.java @@ -80,6 +80,19 @@ private static JMenu fileMenu() "Download protocol file"); menu.add(menuItem); + + menuItem = new JMenuItem(new GuiMenu.FileSave()); + menuItem.setAccelerator(KeyStroke.getKeyStroke( + KeyEvent.VK_S, ActionEvent.CTRL_MASK)); + menuItem.getAccessibleContext().setAccessibleDescription( + "Save protocol file"); + menu.add(menuItem); + + menuItem = new JMenuItem(new GuiMenu.ConvertFiles()); + menuItem.getAccessibleContext().setAccessibleDescription( + "Batch convert files"); + menu.add(menuItem); + /* * Add the option of rendering a compartment. */ @@ -227,6 +240,7 @@ public void actionPerformed(ActionEvent e) } } + public static class FileOpen extends AbstractAction { private static final long serialVersionUID = 2247122248926681550L; @@ -259,10 +273,50 @@ public FileDownload() public void actionPerformed(ActionEvent e) { + GuiActions.chooseFile(); GuiActions.downloadFile(null); } } + public static class FileSave extends AbstractAction + { + + private static final long serialVersionUID = 1L; + + /** + * Action for the file open sub-menu. + */ + public FileSave() + { + super("Save"); + } + + public void actionPerformed(ActionEvent e) + { + GuiActions.saveToFile( GuiActions.saveFile() ); + } + } + + public static class ConvertFiles extends AbstractAction + { + + private static final long serialVersionUID = 1L; + + /** + * Action for the file open sub-menu. + */ + public ConvertFiles() + { + super("Convert Files"); + } + + public void actionPerformed(ActionEvent e) + { + GuiActions.convertFiles(); + } + } + + public static class RenderThis extends AbstractAction { private static final long serialVersionUID = 974971035938028563L; diff --git a/src/idynomics/Simulator.java b/src/idynomics/Simulator.java index 3207dc842..c5f25d6ca 100644 --- a/src/idynomics/Simulator.java +++ b/src/idynomics/Simulator.java @@ -626,6 +626,12 @@ public String getXml() { return this._modelNode.getXML(); } + + public void saveSimulationState(String path, boolean exi) + { + XmlExport xmlOut = new XmlExport(exi); + xmlOut.writeFile(path); + } @Override public void setParent(Settable parent) From b464b70f186d0c5fe88be645e1bf6cbc1af23edc Mon Sep 17 00:00:00 2001 From: baseendje Date: Mon, 15 Jun 2020 16:48:13 +0200 Subject: [PATCH 06/67] Solve issue that would result in crash after the removal of whitespace --- src/linearAlgebra/Array.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/linearAlgebra/Array.java b/src/linearAlgebra/Array.java index da04b6bca..54c70451c 100644 --- a/src/linearAlgebra/Array.java +++ b/src/linearAlgebra/Array.java @@ -33,7 +33,7 @@ public final class Array */ // NOTE arrayString.split(DELIMITER) does not work when we use "|" here! // This can change, but check it works with testJUnit.LinearAlgebraTest - public final static String DELIMITER = "% \n"; + public final static String DELIMITER = "%"; /************************************************************************* * STANDARD NEW ARRAYS From 5a7fa3171c5aa6971662fe55cdc3d8ac19e0c7ff Mon Sep 17 00:00:00 2001 From: baseendje Date: Mon, 15 Jun 2020 17:10:03 +0200 Subject: [PATCH 07/67] Implemented basic file conversion xml exi --- src/gui/GuiActions.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/gui/GuiActions.java b/src/gui/GuiActions.java index 301f082a7..573723241 100644 --- a/src/gui/GuiActions.java +++ b/src/gui/GuiActions.java @@ -282,7 +282,7 @@ public static void convertFiles() if( Helper.obtainInput( "Would you like to continue processing " + finalFiles.size() + " files?", false) ) { - for( File f : files ) + for( File f : finalFiles ) { boolean exi = false; String out = null; @@ -290,11 +290,11 @@ public static void convertFiles() if( path.toLowerCase().contains(".xml")) { exi = true; - out = path.toLowerCase().replaceAll(".xml", ".exi"); + out = path.toLowerCase().replaceAll(".xml", ""); } else if( path.toLowerCase().contains(".exi")) { exi = false; - out = path.toLowerCase().replaceAll(".exi", ".xml"); + out = path.toLowerCase().replaceAll(".exi", ""); } Idynomics.setupSimulator( f.getAbsolutePath() ); Idynomics.simulator.saveSimulationState(out, exi); From 95f23d0240c7003f3effd2edc2c3e7d3d909018e Mon Sep 17 00:00:00 2001 From: Bastiaan Date: Thu, 26 Nov 2020 13:49:58 +0100 Subject: [PATCH 08/67] check-out fresh branch for todos --- src/agent/Body.java | 1 - 1 file changed, 1 deletion(-) diff --git a/src/agent/Body.java b/src/agent/Body.java index 198f15907..2c86e4b45 100644 --- a/src/agent/Body.java +++ b/src/agent/Body.java @@ -353,7 +353,6 @@ public void instantiate(Element xmlElem, Settable parent) constructBody(); } - } /************************************************************************* From 251585ae4ea678ef0933ed91ee412dd4d1e5b649 Mon Sep 17 00:00:00 2001 From: Bastiaan Date: Thu, 26 Nov 2020 14:46:18 +0100 Subject: [PATCH 09/67] getter for HSB and RGB spec of color --- protocol/ecoli tests/ecoli2D.xml | 4 +-- protocol/unit-tests/reaction_diffusion.xml | 1 - src/colour/Colour.java | 42 ++++++++++++++++------ src/colour/ColourSpecification.java | 8 ++--- src/compartment/Compartment.java | 8 ++--- 5 files changed, 39 insertions(+), 24 deletions(-) diff --git a/protocol/ecoli tests/ecoli2D.xml b/protocol/ecoli tests/ecoli2D.xml index 243629b65..92d1c1dfd 100644 --- a/protocol/ecoli tests/ecoli2D.xml +++ b/protocol/ecoli tests/ecoli2D.xml @@ -153,14 +153,14 @@ + firstStep="0.0" > + firstStep="0.0" > diff --git a/protocol/unit-tests/reaction_diffusion.xml b/protocol/unit-tests/reaction_diffusion.xml index 7373ea81a..390ff86bd 100644 --- a/protocol/unit-tests/reaction_diffusion.xml +++ b/protocol/unit-tests/reaction_diffusion.xml @@ -37,7 +37,6 @@ - diff --git a/src/colour/Colour.java b/src/colour/Colour.java index 00a3ef4d3..eb1fb3eaf 100644 --- a/src/colour/Colour.java +++ b/src/colour/Colour.java @@ -1,5 +1,6 @@ package colour; +import java.awt.Color; import java.util.LinkedList; import java.util.List; @@ -13,6 +14,8 @@ public enum Format RGB; } + private Color jColor; + public final float[] zeros = new float[3]; private Format format; @@ -33,12 +36,20 @@ public enum Format public Colour(float[] baseColour, String format, String name) { - this.initialColour = baseColour; - this.format = Format.valueOf(format); + this.format = Format.valueOf( format ); + if( Format.HSB.equals( this.format )) + this.initialColour = baseColour; + else + { + this.initialColour = Color.RGBtoHSB( + Math.round( baseColour[0]*255 ), + Math.round( baseColour[1]*255 ), + Math.round( baseColour[2]*255 ), null); + } this.name = name; } - public void addGradient(float[] gradient) + public void addGradient( float[] gradient ) { if( gradients.size() >= 3) { @@ -48,13 +59,13 @@ public void addGradient(float[] gradient) this.gradients.add( gradient ); } - public void addGradient(String first, String second, String third) + public void addGradient( String first, String second, String third ) { float[] out = new float[3]; if( first == null ) out[0] = 0.0f; else - out[0] = Float.valueOf(first); + out[0] = Float.valueOf( first ); if( second == null ) out[1] = 0.0f; else @@ -72,7 +83,7 @@ public void addGradient(String first, String second, String third) * @param opacity - given opacity * @return */ - public float[] returnColour(float[] dial, float opacity) + public float[] returnColourHSB(float[] dial, float opacity) { this.opacity = opacity; float[] HSBOOut = {0.0f, 0.0f, 0.0f, this.opacity}; @@ -86,10 +97,9 @@ public float[] returnColour(float[] dial, float opacity) public float line(int gradient, int field) { - float[] grad = (this.gradients.size() > gradient ? - this.gradients.get( gradient ) : - zeros ); - return dial[gradient]*(grad[field]-initialColour[field]); + float[] grad = ( this.gradients.size() > gradient ? + this.gradients.get( gradient ) : zeros ); + return dial[gradient] * ( grad[field] - initialColour[field] ); } /** @@ -101,7 +111,7 @@ public float line(int gradient, int field) * object, which is 1.0 at setup unless defined in the palette). * @return */ - public float[] returnColour(float[] dial) + public float[] returnColourHSB(float[] dial) { float[] HSBOOut = {0.0f, 0.0f, 0.0f}; for (int i = 0; i < 3; i++) @@ -111,6 +121,16 @@ public float[] returnColour(float[] dial) } return HSBOOut; } + + public float[] returnColourRGB(float[] dial) + { + float[] hsb = returnColourHSB(dial); + jColor = new Color(Color.HSBtoRGB( hsb[0], hsb[1], hsb[2] )); + return new float[] { + jColor.getRed() / 255, + jColor.getGreen() / 255, + jColor.getBlue() / 255 }; + } public void setOpacity(Float opacity) { diff --git a/src/colour/ColourSpecification.java b/src/colour/ColourSpecification.java index f0718f333..d5a8b0b43 100644 --- a/src/colour/ColourSpecification.java +++ b/src/colour/ColourSpecification.java @@ -26,9 +26,9 @@ public ColourSpecification(Palette palette, String filter) public float[] colorize(AspectInterface subject) { /* placeholder code before merge */ - String factor = subject.getString(filter); - if( !factors.containsKey(factor) ) - this.factors.put(factor, palette.getNext()); - return this.factors.get(factor).returnColour(new float[3]); + String factor = subject.getString( filter ); + if( !factors.containsKey( factor ) ) + this.factors.put( factor, palette.getNext() ); + return this.factors.get( factor ).returnColourRGB( new float[3] ); } } diff --git a/src/compartment/Compartment.java b/src/compartment/Compartment.java index 0593ab718..ce9d014d4 100644 --- a/src/compartment/Compartment.java +++ b/src/compartment/Compartment.java @@ -528,10 +528,6 @@ public void preStep() this.agents.agentsArrive(); this.agents.sortLocatedAgents(); - /* - * Ask all boundaries to update their solute concentrations. - */ - this.environment.updateSoluteBoundaries(); } /** @@ -640,7 +636,8 @@ public Map getRealTimeStats() for ( ProcessManager pm : this._processes ) { if (out.containsKey(pm.getName())) - out.put(pm.getName(), out.get(pm.getName()) + pm.getRealTimeTaken()); + out.put(pm.getName(), out.get(pm.getName()) + + pm.getRealTimeTaken()); else out.put(pm.getName(), pm.getRealTimeTaken()); } @@ -823,4 +820,3 @@ public int compareTo(Compartment o) return this.name.compareTo(o.name); } } ->>>>>>> Process From 749f7196e1d8770e1f44aef832628bcd6852a9cd Mon Sep 17 00:00:00 2001 From: Bastiaan Date: Thu, 26 Nov 2020 14:50:42 +0100 Subject: [PATCH 10/67] fixed issue with loading in un-numbered agents --- src/agent/Agent.java | 5 ++++- src/compartment/Compartment.java | 1 - 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/src/agent/Agent.java b/src/agent/Agent.java index 50d8338cd..730ab52e4 100644 --- a/src/agent/Agent.java +++ b/src/agent/Agent.java @@ -113,7 +113,10 @@ public void init(Node xmlNode, Compartment comp) { String in = XmlHandler.gatherAttribute(xmlNode, XmlRef.identity); - this.number(Integer.valueOf(in)); + if( in == null) + this.number(null); + else + this.number(Integer.valueOf(in)); // Place located agents loadAspects(xmlNode); } diff --git a/src/compartment/Compartment.java b/src/compartment/Compartment.java index ce9d014d4..608788563 100644 --- a/src/compartment/Compartment.java +++ b/src/compartment/Compartment.java @@ -26,7 +26,6 @@ import idynomics.Idynomics; import instantiable.Instance; import instantiable.Instantiable; -import instantiable.object.InstantiableList; import linearAlgebra.Orientation; import linearAlgebra.Vector; import physicalObject.PhysicalObject; From 2d1c06815f9870d5fbb04bb7bd9ed79ffea45359 Mon Sep 17 00:00:00 2001 From: Bastiaan Date: Thu, 26 Nov 2020 18:12:20 +0100 Subject: [PATCH 11/67] colour palette in Render classes, fixed issue with rounding HSB hue --- colourPalettes/Colours.xml | 6 +- src/agent/Agent.java | 4 +- src/colour/Colour.java | 6 +- src/colour/ColourSpecification.java | 5 + src/colour/Palette.java | 13 +- src/gui/GuiActions.java | 11 +- src/gui/GuiMenu.java | 1 - src/idynomics/Global.java | 6 + .../library/GraphicalOutput.java | 7 +- src/referenceLibrary/AspectRef.java | 2 + src/render/AgentMediator.java | 115 ++++++++++++------ src/render/Render.java | 45 +++++++ 12 files changed, 165 insertions(+), 56 deletions(-) diff --git a/colourPalettes/Colours.xml b/colourPalettes/Colours.xml index de5a1529b..2881cec29 100644 --- a/colourPalettes/Colours.xml +++ b/colourPalettes/Colours.xml @@ -1,14 +1,14 @@ - - - diff --git a/src/agent/Agent.java b/src/agent/Agent.java index 730ab52e4..7a5cd5783 100644 --- a/src/agent/Agent.java +++ b/src/agent/Agent.java @@ -89,7 +89,8 @@ public void init(Node xmlNode, Compartment comp) // Spawn random agents for(int i = 0; i < temp.getLength(); i++) { - /* TODO this is a cheat, make a standard method for this */ + /* NOTE this remains here for older protocols, for newer ones we + * should use the spawner classes. */ int n = Integer.valueOf(XmlHandler.obtainAttribute( temp.item(i), XmlRef.numberOfAgents, this.defaultXmlTag() ) ); @@ -125,7 +126,6 @@ public void init(Node xmlNode, Compartment comp) private void number(Integer in) { - if(in != null) { if ( UNIQUE_ID <= in ) diff --git a/src/colour/Colour.java b/src/colour/Colour.java index eb1fb3eaf..73d1ea74c 100644 --- a/src/colour/Colour.java +++ b/src/colour/Colour.java @@ -127,9 +127,9 @@ public float[] returnColourRGB(float[] dial) float[] hsb = returnColourHSB(dial); jColor = new Color(Color.HSBtoRGB( hsb[0], hsb[1], hsb[2] )); return new float[] { - jColor.getRed() / 255, - jColor.getGreen() / 255, - jColor.getBlue() / 255 }; + jColor.getRed() / 255.0f, + jColor.getGreen() / 255.0f, + jColor.getBlue() / 255.0f }; } public void setOpacity(Float opacity) diff --git a/src/colour/ColourSpecification.java b/src/colour/ColourSpecification.java index d5a8b0b43..b215552c1 100644 --- a/src/colour/ColourSpecification.java +++ b/src/colour/ColourSpecification.java @@ -31,4 +31,9 @@ public float[] colorize(AspectInterface subject) this.factors.put( factor, palette.getNext() ); return this.factors.get( factor ).returnColourRGB( new float[3] ); } + + public String toString() + { + return this.filter; + } } diff --git a/src/colour/Palette.java b/src/colour/Palette.java index 7388227ad..718dbd447 100644 --- a/src/colour/Palette.java +++ b/src/colour/Palette.java @@ -7,6 +7,7 @@ import org.w3c.dom.Element; import dataIO.Log; +import dataIO.Log.Tier; import dataIO.XmlHandler; import linearAlgebra.Vector; @@ -84,13 +85,21 @@ public Palette(String paletteName) c.getAttribute( Property.OPACITY.tag ) ) ); } } - Log.out( "Loaded " + this.unAssigned.size() + " colours from palette."); + Log.out(Tier.EXPRESSIVE, "Loaded " + this.unAssigned.size() + + " colours from palette."); + } + + public void reset() + { + this.unAssigned.clear(); + for( String n : colours.keySet() ) + this.unAssigned.add(n); } public Colour getNext() { String out = unAssigned.getFirst(); - unAssigned.remove(out); + unAssigned.remove( out ); return colours.get( out ); } } diff --git a/src/gui/GuiActions.java b/src/gui/GuiActions.java index d7bfcb2ad..dd0454e5b 100644 --- a/src/gui/GuiActions.java +++ b/src/gui/GuiActions.java @@ -20,6 +20,7 @@ import dataIO.FileHandler; import dataIO.FolderOperations; import dataIO.Log; +import dataIO.Log.Tier; import idynomics.Global; import idynomics.Idynomics; import idynomics.PostProcess; @@ -225,7 +226,7 @@ public static void downloadFile(String url) try { urly = new URL(url); } catch ( MalformedURLException e) { - e.printStackTrace(); + Log.out(Tier.NORMAL, "unable to aquire protocol from url: " + url); } @@ -241,11 +242,11 @@ public static void downloadFile(String url) webIS.close(); handler.fclose(); Log.out("finished Download"); - } catch (IOException e) { - e.printStackTrace(); + File in = new File(local); + openFile(in); + } catch (IOException | NullPointerException e) { + Log.out(Tier.NORMAL, "File download failed"); } - File in = new File(local); - openFile(in); } public static void saveToFile(File f) diff --git a/src/gui/GuiMenu.java b/src/gui/GuiMenu.java index 1ff4f4de0..aee641248 100644 --- a/src/gui/GuiMenu.java +++ b/src/gui/GuiMenu.java @@ -273,7 +273,6 @@ public FileDownload() public void actionPerformed(ActionEvent e) { - GuiActions.chooseFile(); GuiActions.downloadFile(null); } } diff --git a/src/idynomics/Global.java b/src/idynomics/Global.java index cb01640cb..f6b0c5368 100644 --- a/src/idynomics/Global.java +++ b/src/idynomics/Global.java @@ -166,6 +166,12 @@ public void updateSettings() */ public static boolean csv_bookkeeping = false; + /** + * the default color specification for graphical output, NOTE in the future + * we probably want to set this to "species" + */ + public static String default_colour_specification = "pigment"; + /** * enable xml bookkeeping (also logging complete agent xml) * Warning: very slow diff --git a/src/processManager/library/GraphicalOutput.java b/src/processManager/library/GraphicalOutput.java index 91d9b0c61..45d70afeb 100644 --- a/src/processManager/library/GraphicalOutput.java +++ b/src/processManager/library/GraphicalOutput.java @@ -145,8 +145,11 @@ public void init(Element xmlElem, EnvironmentContainer environment, this.palette = new Palette( String.valueOf( this.getOr( AspectRef.colourPalette, Global.default_palette) ) ); - /* placeholder spec */ - colSpec = new ColourSpecification(palette, "species"); + + /* In the future we may want to change the default to "species" */ + colSpec = new ColourSpecification(palette, (String) + this.getOr( AspectRef.colourSpecification, + Global.default_colour_specification)); } diff --git a/src/referenceLibrary/AspectRef.java b/src/referenceLibrary/AspectRef.java index 1888ccc96..15c1ace20 100644 --- a/src/referenceLibrary/AspectRef.java +++ b/src/referenceLibrary/AspectRef.java @@ -620,4 +620,6 @@ public static String[] getAllOptions() public static final String linearFunction = "linearFunction"; public static final String fileNumber = "fileNumber"; + + public static final String colourSpecification = "colourSpecification"; } diff --git a/src/render/AgentMediator.java b/src/render/AgentMediator.java index 11db8dba8..586cc74c2 100644 --- a/src/render/AgentMediator.java +++ b/src/render/AgentMediator.java @@ -14,10 +14,13 @@ import com.jogamp.opengl.util.gl2.GLUT; import agent.Agent; +import colour.ColourSpecification; +import colour.Palette; import compartment.AgentContainer; import compartment.Compartment; import grid.ArrayType; import grid.SpatialGrid; +import idynomics.Global; import linearAlgebra.Vector; import referenceLibrary.AspectRef; import shape.CartesianShape; @@ -137,6 +140,10 @@ public class AgentMediator implements CommandMediator { private int j; + private Palette palette; + + private ColourSpecification colSpec; + /** * used to set up the open gl camera */ @@ -145,6 +152,29 @@ public float kickback() { return _kickback; } + public String currentColourSpecification() + { + return this.colSpec.toString(); + } + + public void setColourSpecification(String filter) + { + this.colSpec = new ColourSpecification(palette, filter); + } + + + public void setPalette(String palette) + { + this.palette = new Palette( palette ); + this.colSpec = new ColourSpecification( this.palette, + currentColourSpecification() ); + } + + public void resetPalette() + { + palette.reset(); + } + public double[] orientation() { if (this._shape instanceof CartesianShape) @@ -178,6 +208,13 @@ public AgentMediator(Compartment c) if( solutes.size() > 2 ) soluteColors.put("Blue", (String)solutes.toArray()[2]); + this.palette = new Palette( String.valueOf( Global.default_palette )); + + /* In the future we may want to change the default to "species" */ + this.colSpec = new ColourSpecification( palette, + Global.default_colour_specification ); + + this._compartment = c; /* keep dimensions that are not significant at 0 */ @@ -240,44 +277,45 @@ public void draw(GLAutoDrawable drawable) { AspectRef.surfaceList) ? a.get(AspectRef.surfaceList) : new LinkedList())) { - _pigment = a.getValue("pigment"); - _pigment = Helper.setIfNone(_pigment, "WHITE"); - if (!(_pigment instanceof String)) - { - double[] _pigmentDouble = (double[]) _pigment; - for (int i = 0; i < _pigmentDouble.length; i++) - { - _rgba[i] = (float) _pigmentDouble[i]; - } - } - else - { - switch ((String) _pigment) - { - case "GREEN" : - _rgba = new float[] {0.0f, 1.0f, 0.0f}; - break; - case "RED" : - _rgba = new float[] {1.0f, 0.0f, 0.0f}; - break; - case "BLUE" : - _rgba = new float[] {0.01f, 0.0f, 1.0f}; - break; - case "PURPLE" : - _rgba = new float[] {1.0f, 0.0f, 1.0f}; - break; - case "ORANGE" : - _rgba = new float[] {1.0f, 0.6f, 0.1f}; - break; - case "BLACK" : - _rgba = new float[] {0.0f, 0.0f, 0.0f}; - break; - case "WHITE" : - default : - _rgba = new float[] {1.0f, 1.0f, 1.0f}; - break; - } - } + _rgba = colSpec.colorize(a); +// _pigment = a.getValue("pigment"); +// _pigment = Helper.setIfNone(_pigment, "WHITE"); +// if (!(_pigment instanceof String)) +// { +// double[] _pigmentDouble = (double[]) _pigment; +// for (int i = 0; i < _pigmentDouble.length; i++) +// { +// _rgba[i] = (float) _pigmentDouble[i]; +// } +// } +// else +// { +// switch ((String) _pigment) +// { +// case "GREEN" : +// _rgba = new float[] {0.0f, 1.0f, 0.0f}; +// break; +// case "RED" : +// _rgba = new float[] {1.0f, 0.0f, 0.0f}; +// break; +// case "BLUE" : +// _rgba = new float[] {0.01f, 0.0f, 1.0f}; +// break; +// case "PURPLE" : +// _rgba = new float[] {1.0f, 0.0f, 1.0f}; +// break; +// case "ORANGE" : +// _rgba = new float[] {1.0f, 0.6f, 0.1f}; +// break; +// case "BLACK" : +// _rgba = new float[] {0.0f, 0.0f, 0.0f}; +// break; +// case "WHITE" : +// default : +// _rgba = new float[] {1.0f, 1.0f, 1.0f}; +// break; +// } +// } /* * Render the appropriate surface @@ -661,4 +699,5 @@ public void solutTranparancy() { _soluteTranparancy += 0.05f; } + } diff --git a/src/render/Render.java b/src/render/Render.java index 6decd367c..afe4df91a 100644 --- a/src/render/Render.java +++ b/src/render/Render.java @@ -27,6 +27,7 @@ import javax.swing.InputMap; import javax.swing.JComponent; import javax.swing.JFrame; +import javax.swing.JOptionPane; import javax.swing.JPanel; import javax.swing.KeyStroke; @@ -42,6 +43,7 @@ import dataIO.Log; import dataIO.Log.Tier; +import gui.GuiActions; import idynomics.Global; import idynomics.Idynomics; @@ -789,5 +791,48 @@ public void actionPerformed(ActionEvent g) { } }); + /* Palette */ + inputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_F1, 0), "Palette") ; + actionMap.put("Palette", new AbstractAction(){ + private static final long serialVersionUID = 346448974654345823L; + + @Override + public void actionPerformed(ActionEvent g) { + System.out.println("Palette"); + File f = GuiActions.chooseFile("colourPalettes", + "Choose palette file."); + if( f.canRead() ) + ((AgentMediator) r._commandMediator).setPalette( + f.getName() ); + else + Log.out("Could not read palette file."); + } + }); + + /* Palette */ + inputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_F2, 0), "Colour specification") ; + actionMap.put("Colour specification", new AbstractAction(){ + private static final long serialVersionUID = 346448974654345823L; + + @Override + public void actionPerformed(ActionEvent g) { + System.out.println("Colour specification"); + /* We could do this a bit cleaner */ + String in = inputDialog("Colour specification", ((AgentMediator) + r._commandMediator).currentColourSpecification()); + ((AgentMediator) r._commandMediator).setColourSpecification(in); + ((AgentMediator) r._commandMediator).resetPalette(); + } + }); + } + + public static String inputDialog(String message, String initial) + { + JFrame f; + f=new JFrame(); + if( initial == null ) + return JOptionPane.showInputDialog( f,message ); + else + return JOptionPane.showInputDialog( f, message, initial ); } } From 3bf38349d9b34d3724ef3677aaadfe35edc0ac65 Mon Sep 17 00:00:00 2001 From: Bastiaan Date: Thu, 26 Nov 2020 18:12:35 +0100 Subject: [PATCH 12/67] alternative colour palette --- colourPalettes/rainbow.xml | 51 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 51 insertions(+) create mode 100644 colourPalettes/rainbow.xml diff --git a/colourPalettes/rainbow.xml b/colourPalettes/rainbow.xml new file mode 100644 index 000000000..48ad9b51e --- /dev/null +++ b/colourPalettes/rainbow.xml @@ -0,0 +1,51 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + From ffbd9c5a080885e3176207e31648e554b71ed0b2 Mon Sep 17 00:00:00 2001 From: baseendje Date: Tue, 1 Dec 2020 20:23:25 +0100 Subject: [PATCH 13/67] Eco Ego and multigrid investigations --- protocol/Strep/Eco Ego.xml | 153 ++++++++ protocol/benchmark_3.xml | 14 +- protocol/ecoli tests/ecoli.xml | 341 +++++++++--------- protocol/ecoli tests/ecoli2D.xml | 4 +- .../library/SolveDiffusionSteadyState.java | 4 +- src/solver/PDEmultigrid.java | 61 ++-- 6 files changed, 369 insertions(+), 208 deletions(-) create mode 100644 protocol/Strep/Eco Ego.xml diff --git a/protocol/Strep/Eco Ego.xml b/protocol/Strep/Eco Ego.xml new file mode 100644 index 000000000..c67175f7a --- /dev/null +++ b/protocol/Strep/Eco Ego.xml @@ -0,0 +1,153 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/protocol/benchmark_3.xml b/protocol/benchmark_3.xml index bb7b9d50e..ea5bd5e2e 100644 --- a/protocol/benchmark_3.xml +++ b/protocol/benchmark_3.xml @@ -6,10 +6,6 @@ - - - - - - + firstStep="0.0"> @@ -186,7 +178,7 @@ + firstStep="0.0"> @@ -204,7 +196,7 @@ + firstStep="0.0"> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/protocol/ecoli tests/ecoli2D.xml b/protocol/ecoli tests/ecoli2D.xml index 92d1c1dfd..ad2dc8308 100644 --- a/protocol/ecoli tests/ecoli2D.xml +++ b/protocol/ecoli tests/ecoli2D.xml @@ -132,8 +132,8 @@ - - + + diff --git a/src/processManager/library/SolveDiffusionSteadyState.java b/src/processManager/library/SolveDiffusionSteadyState.java index 9e52f31bd..9f754e841 100644 --- a/src/processManager/library/SolveDiffusionSteadyState.java +++ b/src/processManager/library/SolveDiffusionSteadyState.java @@ -56,9 +56,9 @@ public void init(Element xmlElem, EnvironmentContainer environment, { super.init(xmlElem, environment, agents, compartmentName); - double absTol = (double) this.getOr(ABS_TOLERANCE, 1.0e-18); + double absTol = (double) this.getOr(ABS_TOLERANCE, 1.0e-9); - double relTol = (double) this.getOr(REL_TOLERANCE, 1.0e-18); + double relTol = (double) this.getOr(REL_TOLERANCE, 1.0e-3); // TODO Let the user choose which ODEsolver to use. this._solver = new PDEmultigrid( diff --git a/src/solver/PDEmultigrid.java b/src/solver/PDEmultigrid.java index 195cde8e5..11b9488eb 100644 --- a/src/solver/PDEmultigrid.java +++ b/src/solver/PDEmultigrid.java @@ -73,7 +73,7 @@ public class PDEmultigrid extends PDEsolver /** * maximum number of pre-steps */ - private int _numPreSteps = 150; + private int _numPreSteps = 1500; /** * maximum number of coarse steps */ @@ -81,7 +81,7 @@ public class PDEmultigrid extends PDEsolver /** * maximum number of post steps */ - private int _numPostSteps = 150; // 1 -> 1000, 0.5 -> 2500 seems to work + private int _numPostSteps = 1500; // 1 -> 1000, 0.5 -> 2500 seems to work /** * Absolute threshold of the residual value at which relaxation is @@ -100,7 +100,7 @@ public class PDEmultigrid extends PDEsolver /** * Enable stopping relaxation when stop conditions are met */ - private boolean _enableEarlyStop = false; + private boolean _enableEarlyStop = true; /** * Warn for large differences between Vcycle residuals (Debugging tool) */ @@ -113,6 +113,8 @@ public class PDEmultigrid extends PDEsolver * Stored old residual (Debugging tool internal use) */ private double tempRes[]; + + private double tempRel[]; /** * Stored layer number (Debugging tool internal use) */ @@ -499,6 +501,8 @@ private boolean doVCycle(Collection variables, int numLayers) currentCommon = this._commonMultigrid.getGrid(); if( tempRes == null) tempRes = new double[variables.size()]; + if( tempRel == null) + tempRel = new double[variables.size()]; int i = 0; for ( SpatialGrid variable : variables ) @@ -529,9 +533,6 @@ private boolean doVCycle(Collection variables, int numLayers) this.num = 0; } - this.tempRes[i] = residual; - i++; - continueVCycle = (continueVCycle || residual > truncationError); if ( continueVCycle && Log.shouldWrite(Tier.DEBUG) ) Log.out(Tier.DEBUG, "residual " + residual+ " > truncation" @@ -552,6 +553,9 @@ private void relaxAll(int numRepetitions) currentGrids.add(layer.getGrid()); SpatialGrid currentCommon = this._commonMultigrid.getGrid(); + tempRes = new double[this._variableNames.length]; + tempRel = new double[this._variableNames.length]; + int nGrid = currentGrids.size(); double[][] validate = new double[nGrid][3]; @@ -571,21 +575,30 @@ private void relaxAll(int numRepetitions) boolean stop = true; for ( SpatialGrid grid : currentGrids ) { - tempRes = new double[this._variableNames.length]; this.relax(grid, currentCommon); if ( !this._reachedStopCondition ) stop = false; } if ( stop ) { // if( Log.shouldWrite(Tier.DEBUG) ) - Log.out("Breaking early: "+ i +" of " + Log.out("Met stop conditions at: "+ i+1 +" of " + numRepetitions ); break relaxLoops; } - if( i+1 >= numRepetitions && Log.shouldWrite(Tier.DEBUG) ) + if( i+1 >= numRepetitions && Log.shouldWrite(Tier.NORMAL) ) { - Log.out(Tier.DEBUG, i + " " + Vector.max(this.tempRes) + " > " + - this._absToleranceLevel ); + if( Vector.max(this.tempRes) > this._absToleranceLevel ) + { + Log.out(Tier.NORMAL, i+1 + " " + Vector.max(this.tempRes) + + " > " + this._absToleranceLevel ); + Log.out(Vector.toString(tempRes)); + } + else + { + Log.out(Tier.NORMAL, i+1 + " " + Vector.max(this.tempRel) + + " > " + this._relToleranceLevel ); + Log.out(Vector.toString(tempRel)); + } } } /* update reaction rate matrix at current concn */ @@ -727,6 +740,13 @@ private void relax(SpatialGrid variable, SpatialGrid commonGrid) residual = (lop - rhs) / totalNhbWeight; this.tempRes[pos] = Math.max(this.tempRes[pos], Math.abs(residual)); double relChange = residual / concn; + if( concn <= 0.0 ) + { + relChange = 0.0; + if( residual < 0.0 ) /* seriously? */ + residual = 0.0; + } + this.tempRel[pos] = Math.max(this.tempRel[pos], Math.abs(relChange)); /* Prepare to update the local concentration. */ concn += residual; if (Math.abs(residual) > this._absToleranceLevel && @@ -871,6 +891,13 @@ private void calculateResidual(SpatialGrid variable, if ( this._enableEarlyStop ) this._reachedStopCondition = true; + int pos = 0; + for (int i = 0; i < this._variableNames.length; i++) + { + if( variable.getName().equals(this._variableNames[i])) + pos = i; + } + /* FIXME: inverting the order we iterate the grid changes the result * I don't think the method should be sensitive to the direction of * evaluation! Bas [09.12.2019] @@ -959,18 +986,8 @@ private void calculateResidual(SpatialGrid variable, * TODO */ residual = (lop - rhs) / totalNhbWeight; - double relChange = residual / concn; - /* Prepare to update the local concentration. */ concn += residual; - if (Math.abs(residual) > this._absToleranceLevel && - Math.abs(relChange) > this._relToleranceLevel) - { - this._reachedStopCondition = false; - } else { - if( Log.shouldWrite(Tier.DEBUG) ) - Log.out(Tier.DEBUG, "residual = "+residual+" relChange = "+ - relChange ); - } + /* Check if we need to remain non-negative. */ if ( (!this._allowNegatives) && (concn < 0.0) ) concn = 0.0; From 9b0b312a83b7f87e91481cfa914cebacc2128e60 Mon Sep 17 00:00:00 2001 From: baseendje Date: Wed, 2 Dec 2020 16:51:19 +0100 Subject: [PATCH 14/67] multigrid investigations --- protocol/Strep/Eco Ego.xml | 16 +- protocol/case_study2/eight_a_edit.xml | 248 +++++++++++++++ src/idynomics/Global.java | 2 +- src/processManager/ProcessDiffusion.java | 15 +- src/solver/PDEmultigrid.java | 369 +++++++++++------------ 5 files changed, 446 insertions(+), 204 deletions(-) create mode 100644 protocol/case_study2/eight_a_edit.xml diff --git a/protocol/Strep/Eco Ego.xml b/protocol/Strep/Eco Ego.xml index c67175f7a..2e492a990 100644 --- a/protocol/Strep/Eco Ego.xml +++ b/protocol/Strep/Eco Ego.xml @@ -3,7 +3,7 @@ - + @@ -47,13 +47,13 @@ - + - + - + @@ -82,7 +82,7 @@ - + @@ -134,11 +134,13 @@ - + - + + diff --git a/protocol/case_study2/eight_a_edit.xml b/protocol/case_study2/eight_a_edit.xml new file mode 100644 index 000000000..d49a8e3b6 --- /dev/null +++ b/protocol/case_study2/eight_a_edit.xml @@ -0,0 +1,248 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/idynomics/Global.java b/src/idynomics/Global.java index f6b0c5368..e2141d47b 100644 --- a/src/idynomics/Global.java +++ b/src/idynomics/Global.java @@ -170,7 +170,7 @@ public void updateSettings() * the default color specification for graphical output, NOTE in the future * we probably want to set this to "species" */ - public static String default_colour_specification = "pigment"; + public static String default_colour_specification = "species"; /** * enable xml bookkeeping (also logging complete agent xml) diff --git a/src/processManager/ProcessDiffusion.java b/src/processManager/ProcessDiffusion.java index f8043ba0d..76aa39323 100644 --- a/src/processManager/ProcessDiffusion.java +++ b/src/processManager/ProcessDiffusion.java @@ -275,13 +275,14 @@ protected void applyEnvReactions(Collection solutes) } } - if( Global.bookkeeping ) - for (String t : totals.keySet()) - /* NOTE we should rewrite how to access the compartment because - * this is pretty inefficient. */ - Idynomics.simulator.getCompartment(this._compartmentName). - registerBook(EventType.REACTION, t, "ENIVIRONMENT", - String.valueOf( totals.get(t) ), null ); + // this class should only calculate, but values may not be final +// if( Global.bookkeeping ) +// for (String t : totals.keySet()) +// /* NOTE we should rewrite how to access the compartment because +// * this is pretty inefficient. */ +// Idynomics.simulator.getCompartment(this._compartmentName). +// registerBook(EventType.REACTION, t, "ENIVIRONMENT", +// String.valueOf( totals.get(t) ), null ); } diff --git a/src/solver/PDEmultigrid.java b/src/solver/PDEmultigrid.java index 11b9488eb..c865c4346 100644 --- a/src/solver/PDEmultigrid.java +++ b/src/solver/PDEmultigrid.java @@ -36,6 +36,9 @@ * reaction kinetics, this solver implements the Full Approximation Storage * (FAS) Algorithm discussed towards the end of the chapter.

* + * + * Read: Numerical Recipes in C page 885 +/- 5 + * *

Here are the meanings of the various symbols used in that chapter, * within the context of iDynoMiCS 2: