import java.awt.Component;
import java.awt.Dimension;
import java.awt.Rectangle;
import java.util.Random;
import javax.swing.JCheckBox;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.vecmath.Point2f;
import javax.vecmath.Point3f;
import org.cellmicrocosmos.cm2.membranepackingalgorithm.*;
/**
* This is a very simple membrane algorithm that i wrote to show a good example
* how a membrane algorithm works. It simply places new lipids at a rondom
* position untill the desired number of lipids has been reached or it is
* getting aborted. It provides a small GUI so that you can see how to use this
* feature and it also supports microdomains
*
*
* @author Tim Dingersen
This email address is being protected from spambots. You need JavaScript enabled to view it.
*
*/
public class MyMembraneAlgorithm extends MembranePackingAlgorithm {
// the desired number of lipids
int desiredNumberOfLipids;
// indicates if lipids should be rotated
boolean rotateLipids;
// a flag that can be toggled to abort the algorithm
boolean stop = false;
/*
* This method gets invoked before the fillWithLipids() process is started
* This is the point where you should present your GUI, like i'm doing here
*/
public boolean buildAndShowGui() {
/*
* Testing if there are any lipid templates available for the default
* area or at least in any microdomain.
*/
boolean makesSense = this.MembraneHasAnyExtracellularLipids()
|| this.MembraneHasAnyIntracellularLipids();
for (int i = 0; i < this.getMicroDomainCount(); i++) {
if ((this.getMicroDomainAt(i).hasAnyExtracellularLipids() || this
.getMicroDomainAt(i).hasAnyIntracellularLipids()) == false)
makesSense = false;
}
if (!makesSense) {
JOptionPane.showMessageDialog(null,
"No lipids that could be added available!", "No lipids",
JOptionPane.ERROR_MESSAGE);
return false;
}
// building up the options panel for the GUI
JPanel controlPanel = new JPanel();
JLabel textLabel = new JLabel("Desired number of lipids: ");
JTextField textField = new JTextField();
JCheckBox checkBox = new JCheckBox("Rotate lipids");
textField.setPreferredSize(new Dimension(100, 30));
controlPanel.add(textLabel);
controlPanel.add(textField);
controlPanel.add(checkBox);
/*
* showing the GUI to the user. The returnvalue indicates if the user
* confirmed or cancelled the dialog so far
*/
boolean returnValue = MembranePackingAlgorithmGUI.popUpGUI(controlPanel,
"Options", "Set up some options here");
// returning false if all should be cancelled
if (returnValue == false)
return false;
/*
* trying to retrieve the number of desired lipids from the textfield.
* in case of an error the algorithm gets cancelled with a message
*/
try {
this.desiredNumberOfLipids = Integer.parseInt(textField.getText());
if (this.desiredNumberOfLipids < 1
|| this.desiredNumberOfLipids > 1000)
throw new Exception();
} catch (Exception e) {
JOptionPane.showMessageDialog(null,
"You need to enter a number between 1 and 1000\n"
+ "into the textfield!", "Invalid Value",
JOptionPane.ERROR_MESSAGE);
return false;
}
this.rotateLipids = checkBox.isSelected();
/*
* the user settings are ok plus the user must have confirmed if the
* thread reaches this code, so true gets returned in order to proceed
*/
return true;
}
/*
* This method gets called when the algorithm gets started. Remember: The
* algorithm finishes when the thread leaves this method
*/
public void fillWithLipids() throws Exception {
// the current count of lipids that have been added on this run.
int currentCount = 0;
// the value indicates which membraneside should be handled
int mSide = MembranePackingAlgorithm.INTRA;
/*
* starting a loop that runs until the terminal condition is reached or
* the stop flag has been set on true
*/
while (stop == false && currentCount < this.desiredNumberOfLipids) {
// toggling membranesides to handle at each loop
if (mSide == MembranePackingAlgorithm.INTRA)
mSide = MembranePackingAlgorithm.EXTRA;
else
mSide = MembranePackingAlgorithm.INTRA;
// creating a random position on the x/z plane
Point2f randomPosition = this.createRandomXZPosition(new Rectangle(
0, 0, this.getMembraneSize().width,
this.getMembraneSize().height));
// initializing the new lipid for this run
Lipid newLipid;
/*
* determining the domainID for the microdomain at the random point.
* If no microdomains are available or if the point hits the default
* area, the value 0 gets returned
*/
int domainID = this.getMicroDomainAtPoint(randomPosition);
/*
* creating the new lipid by using the convenient methods for this
* if the random point should hit a microdomain, then the methods of
* the specified microdomains are used in order to get the proper
* lipids
*/
if (domainID > 0) {
// the lowest domainID is 1, so we have to use domainID-1 as the
// index
MicroDomain domain = this.getMicroDomainAt(domainID - 1);
newLipid = mSide == EXTRA ? domain
.createNextExtracellularLipid() : domain
.createNextIntracellularLipid();
} else {
newLipid = mSide == EXTRA ? this.createNextExtracellularLipid()
: this.createNextIntracellularLipid();
}
/*
* if the lipid should be null at this point, then the user dind't
* add any lipid templates to the membrane side of the domain (or
* default area) we are trying to create it for.
*/
if (newLipid == null)
continue;
/*
* Assigning the new position to the lipid while maintaining its
* y-translation that we don't want to change in this algorithm
*/
newLipid.setPosition(new Point3f(randomPosition.x, newLipid
.getYTranslation(), randomPosition.y));
// randomly rotating the lipid if this option has been selected
if (this.rotateLipids)
newLipid.rotY(new Random().nextInt(359)
+ new Random().nextFloat());
/*
* The most interesting part: Testing for intersections. First for
* intersections with the borders, then for intersections with any
* other molecules. If an intersection occured then we could
* initiate corrections, but instead we simply retry from the top
*/
if (this.intersectsBorders(newLipid) || this.intersects(newLipid))
continue;
/*
* If the lipid doesn't intersect at it's current alignment, we can
* add itonto its specified membrane side.
*/
if (mSide == EXTRA)
this.addExtracellularLipid(newLipid);
else
this.addIntracellularLipid(newLipid);
// one more lipid added here :)
currentCount++;
}
}
public String getFullInformation() {
// this string is getting displayed in the textarea were the algorithms
// are selected
return "This algorithm simply places all lipids\n"
+ "at random position";
}
public String getName() {
// the chosen name for this algorithm. It has to return a unique name in
// order to get accepted
return "My Algorithm";
}
public Component getRuntimeControlPanel() {
// we don't provide any runtime controls for this simple algorithm
return null;
}
public String getShortInformation() {
// you can leave out some information if you want
return null;
}
public String getStringRepresentationOfSetupParameters() {
// returning a String that describes the users setup
return "Desired Lipids: " + this.desiredNumberOfLipids + "\n"
+ "Rotate Lipids: " + this.rotateLipids;
}
public boolean overrideExistingLipids() {
// existing lipids may remain in this case
return false;
}
public void stopAlgorithm() {
// setting the stop flag on true, forcing the algorithm to stop at the
// next loop
this.stop = true;
}
public boolean supportsMicrodomains() {
// this algorithm provides a full microdomain support
return true;
}
}
- Details
-
Written by bjoern
-
Category: Cm2dev
-
Published: 14 September 2013
-
Hits: 8396