package circdesignagui.TripleSim;
import java.awt.Color;
import java.awt.Dimension;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.Scanner;
import javax.swing.JPanel;
import circdesigna.DomainDefinitions;
import circdesigna.DomainPolymerGraph;
import circdesigna.config.CircDesigNAConfig;
import circdesignagui.MoleculePreview;
import circdesignagui.ThemedApplet;
public class Animator extends MoleculePreview{
public static class Themer extends ThemedApplet{
public void addModalScale(Runnable runnable) {
}
public JPanel getModalPanel() {
return null;
}
public void removeAllModalScale() {
}
public boolean modalPanelIsOccupied() {
// TODO Auto-generated method stub
return false;
}
}
public static Animation readAnimation(CircDesigNAConfig cfg, String text, String domainDefs){
if (text.startsWith("Attach") || text.startsWith("Detach")){
return new AttachDetach(text, domainDefs);
}
if (text.startsWith("Branch Migration")){
return new BranchMigrationAnimation(cfg, text, domainDefs);
}
throw new RuntimeException("Unrecognized animation: "+text);
}
public static abstract class Animation{
public Animation(String text, String domainDefs){
this.text = text;
this.domainDefs = domainDefs;
molecule = "A "+text.substring(text.indexOf('['));
}
public String text;
public String molecule;
public String domainDefs;
public int frames;
public DnaDesignScreens$0_Screen.DnaSequencePreview renderer;
public abstract float progress();
public void work(DomainPolymerGraph dpg) {
}
}
public static class BranchMigrationAnimation extends Animation {
public BranchMigrationAnimation(CircDesigNAConfig cfg, String text, String domainDefs) {
super(text, domainDefs);
String[] parS = text.substring(0,text.indexOf('[')).trim().split("\\s+");
Scanner in = new Scanner(text);
in.next();
in.next();
int numDirection = in.nextInt();
String clockDirection = in.next();
ArrayList<int[]> bmPairs = new ArrayList(); //positions to displace
while(in.hasNext()){
String word = in.next();
if (word.equals("END")){
break;
}
bmPairs.add(new int[]{new Integer(word), in.nextInt(), in.nextInt()});
}
String mol = in.nextLine();
DomainDefinitions dd = new DomainDefinitions(cfg);
DomainDefinitions.readDomainDefs(domainDefs, dd);
DomainPolymerGraph dpg = new DomainPolymerGraph(dd);
DomainPolymerGraph.readStructure("A "+mol, dpg);
if (dpg.getDomain(dpg.length()-1) != -1){
throw new RuntimeException("I don't know how to animate molecules that don't end in a 5' end");
}
N = 0;
dispPairs = new ArrayList(); //domain indices of decrease, increase pairs.
//Sum over all bases being displaced
for(int i = 0; i < bmPairs.size(); i++){
int[] disp = bmPairs.get(i);
int id = dpg.getDomain(disp[0]);
int len = dd.getDomainLength(id);
N += len;
}
for(int i = 0; i <= 0; i++){
//Add decrease, increase pair
domainDefs += "dec"+i+" "+N+"\n";
domainDefs += "inc"+i+" "+0+"\n";
dispPairs.add(new String[]{"dec"+i,"inc"+i});
}
//Rewrite mol to actually use them
mol = "A [";
for(int i = 0; i < dpg.length(); i++){
int d = dpg.getDomain(i);
mol += dpg.getStyle(i).toString();
if (d >= 0){
boolean found = false;
int pair = dpg.getDomainPair(i);
String punct = (pair < i) ? ") " : "( ";
for(int j = 0; j < bmPairs.size(); j++){
int[] bm = bmPairs.get(j);
if (bm[0] == i){
if (j == 0){
if (clockDirection.equals("CCW")){
mol += "dec"+j+" inc"+j+punct;
} else {
mol += "inc"+j+punct+"dec"+j+" ";
}
}
found = true;
}
if (bm[1] == i){
String punct2 = (bm[1] < bm[2]) ? "( " : ") ";
if (j == 0){
if (clockDirection.equals("CCW")){
mol += "inc"+j+"*"+punct+"dec"+j+"*"+punct2;
} else {
mol += "dec"+j+"*"+punct2+"inc"+j+"*"+punct;
}
}
found = true;
}
if (bm[2] == i){
String punct2 = (bm[1] < bm[2]) ? ") " : "( ";
if (j == 0){
if (clockDirection.equals("CCW")){
mol += "dec"+j+punct2+"inc"+j+" ";
} else {
mol += "inc"+j+" "+"dec"+j+punct2;
}
}
found = true;
}
}
if (!found){
if (pair == -1){
mol += dd.getDomainName(d) + " ";
} else {
mol += dd.getDomainName(d) + punct;
}
}
} else {
mol+="}";
//5' end
if (i + 1 < dpg.length()){
mol+=" [ ";
}
}
}
//Override default assignment and domain definitions
molecule = mol;
this.domainDefs = domainDefs;
System.out.println(molecule);
System.out.println(domainDefs);
}
public float progress(){
float fast = frames / 2f / N;
if (viewLocal){
return fast/5;
}
return fast;
}
private ArrayList<String[]> dispPairs = new ArrayList();
//Size of migration domain
int N;
public String reduce, increase;
int lastPhase = -1;
public void work(DomainPolymerGraph dpg) {
DomainDefinitions ddef = dpg.getDomainDefs();
int phase = (int)(progress() * N * (N+1)/((float)N));
if (phase > lastPhase){
for(String[] q : dispPairs){
int q0 = ddef.getDomainFromName(q[0]);
int q1 = ddef.getDomainFromName(q[1]);
int currentLength = ddef.domainLengths[q0];
if (currentLength > 0){
ddef.domainLengths[q0]--;
ddef.domainLengths[q1]++;
break;
}
}
lastPhase = phase;
}
renderer.parseMolecule();
/*
for(DomainStructure s : dsg.listStructures()){
s.handleSubConformation(ddef.domainLengths, dsg.domains);
}
dsg.buildOuterCurve();
*/
}
}
public static class AttachDetach extends Animation{
public AttachDetach(String text, String domainDefs) {
super(text, domainDefs);
Scanner in = new Scanner(text);
in.next();
par = new ArrayList();
while(true){
String next = in.next();
if (next.equals("END")){
break;
}
par.add(new int[]{new Integer(next), in.nextInt()});
}
if (text.startsWith("Detach")){
detach = true;
}
}
public float progress(){
float fast = frames / 10f;
if (viewLocal){
return fast/5;
}
return fast;
}
boolean detach = false;
private float amplitude = 20;
private ArrayList<int[]> par;
public float phase(){
if (detach){
return 1-progress();
} else {
return progress();
}
}
/*
public boolean work_r(DomainStructure s){
boolean found = false;
int oneBreak = 0;
for(DomainStructure u : s.subStructure){
found |= work_r(u);
}
if (found){
for(DomainStructure u : s.subStructure){
if (u instanceof ThreePFivePOpenJunc){
ThreePFivePOpenJunc t = (ThreePFivePOpenJunc)u;
t.size = amplitude/(1+exp(phase()*5))+1.2f;
}
}
}
if (s instanceof HairpinStem){
HairpinStem hs = (HairpinStem)s;
if (s.sequencePartsInvolved[0]==par[0] && s.sequencePartsInvolved[1]==par[1]){
//hs.hydrogenBondStrength = phase();
//hs.openingSize = amplitude/(1+exp(phase()*5))+2;
for(DomainStructure q : hs.subStructure){
if (q instanceof ThreePFivePOpenJunc){
ThreePFivePOpenJunc t = (ThreePFivePOpenJunc)q;
t.size = amplitude/(1+exp(phase()*5))+1.2f;
}
}
return true;
}
}
return false;
}
*/
public void work(DomainPolymerGraph dpg) {
float phase = progress();
if (detach){
phase = 1-phase;
}
//for(DomainStructure s : dsg.listStructures()){
/*
boolean found = false;
for(DomainStructure s : dsg.structures){
found |= work_r(s);
}
if (found){
for(DomainStructure u : dsg.structures){
if (u instanceof ThreePFivePOpenJunc){
ThreePFivePOpenJunc t = (ThreePFivePOpenJunc)u;
t.size = amplitude/(1+exp(phase()*5))+1.2f;
}
}
}
//System.out.println(Arrays.toString(dsg.structures));
for(DomainStructure s : dsg.listStructures()){
s.handleSubConformation(ddef.domainLengths, dsg.domains);
}
dsg.buildOuterCurve();
*/
for(int[] p : par){
int loc = p[0];
//Extend all the way out until the end of the strand in both directions.
for(int dir : new int[]{-1,1}){
int nx = loc;
while(true){
if (nx < 0 || nx >= dpg.length()){
break;
}
Color old = dpg.getStyle(nx).color;
dpg.getStyle(nx).color = new Color(old.getRed(), old.getGreen(), old.getBlue(), (int)(phase * 255));
System.out.println(dpg.getStyle(nx).color.getAlpha());
if (dpg.getDomain(nx) == -1){
break; //Hit the end of a strand
}
nx += dir;
}
}
}
}
}
private LinkedList<Animation> toAnimate = new LinkedList();
public String snapshotDirectory = "";
private boolean firstAnimation = true;
public static boolean viewLocal = false; //set to true if viewing locally
public Animator() {
super(new Themer(), new CircDesigNAConfig());
setPreferredSize(new Dimension(1024,1024));
}
public void init(){
Scanner in;
if (getParameter("infile")!= null){
try {
in = new Scanner(new File(getParameter("infile")));
} catch (FileNotFoundException e) {
e.printStackTrace();
exit();
in = null;
}
} else {
in = new Scanner(System.in);
}
System.out.println("Please enter the directory in which to store the animation:");
snapshotDirectory = in.nextLine();
in.nextLine();
System.out.println("Please enter in the animation commands:");
String domainDefs = "";
while(in.hasNextLine()){
String line = in.nextLine();
if (line.equals("END")){
break;
}
domainDefs += line+"\n";
}
while(in.hasNextLine()){
String line = in.nextLine();
if (line.equals("END")){
break;
}
try {
Animation neu = readAnimation(getConfig(), line, domainDefs);
toAnimate.add(neu);
} catch (Throwable e){
e.printStackTrace();
}
}
super.init();
}
public void draw(){
String pdf = getLastSnapshotPath();
if (pdf != null){
pdf2png(pdf, snapshotDirectory+"/"+frameCount+".png");
System.out.println(frameCount);
}
DnaDesignScreens$0_Screen.DnaSequencePreview g = getRenderer();
g.drawGrid = false;
g.rotateToLongestHairpin = false;
g.dynamicWiggle = false;
g.drawDomainNames = false;
if (frameCount <= 1){
try {
setCurrentPreviewMolecule(0, 2, "A [A}", "A 150", true);
} catch (UpdateSuccessfulException e){
}
return;
}
Animation current = toAnimate.peek();
while (current != null && current.progress() >= 1){
System.out.println("Completed: "+current);
toAnimate.poll();
current = toAnimate.peek();
}
if (current==null){
noLoop();
return;
}
current.renderer = g;
if (current.frames==0){
try {
setCurrentPreviewMolecule(1, 2, current.molecule, current.domainDefs, firstAnimation);
} catch (UpdateSuccessfulException e){
}
firstAnimation = false;
}
current.work(g.dpg);
current.frames++;
snapShot(snapshotDirectory+"/"+frameCount+".pdf");
//viewLocal = true;
super.draw();
}
private void pdf2png(String pdf, String png) {
String[] cmd = {
/*
"cmd",
"/c",
"echo %PATH%"
*/
"gswin32c",
//"-q",
"-dSAFER -dBATCH -dNOPAUSE",
"-sDEVICE=png16m",
//"-r200",
"-dTextAlphaBits=4",
"-dGraphicsAlphaBits=4",
"-o",
png,
pdf,
};
try {
Process p = Runtime.getRuntime().exec(cmd);
if (false){
BufferedReader bri = new BufferedReader
(new InputStreamReader(p.getInputStream()));
BufferedReader bre = new BufferedReader
(new InputStreamReader(p.getErrorStream()));
String line;
while ( (line = bri.readLine ()) != null) {
System.out.println(line);
}
bri.close();
while ( (line = bre.readLine ()) != null) {
System.out.println(line);
}
bre.close();
p.waitFor();
exit();
}
}
catch (Throwable e) {
e.printStackTrace();
exit();
}
}
}