001/*
002 * Copyright (c) 2004-2010 The Regents of the University of California.
003 * All rights reserved.
004 *
005 * '$Author: welker $'
006 * '$Date: 2010-05-06 05:21:26 +0000 (Thu, 06 May 2010) $' 
007 * '$Revision: 24234 $'
008 * 
009 * Permission is hereby granted, without written agreement and without
010 * license or royalty fees, to use, copy, modify, and distribute this
011 * software and its documentation for any purpose, provided that the above
012 * copyright notice and the following two paragraphs appear in all copies
013 * of this software.
014 *
015 * IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY
016 * FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
017 * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF
018 * THE UNIVERSITY OF CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF
019 * SUCH DAMAGE.
020 *
021 * THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
022 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
023 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE
024 * PROVIDED HEREUNDER IS ON AN "AS IS" BASIS, AND THE UNIVERSITY OF
025 * CALIFORNIA HAS NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES,
026 * ENHANCEMENTS, OR MODIFICATIONS.
027 *
028 */
029
030package org.cipres.kepler;
031
032// Ptolemy package
033import org.cipres.CipresIDL.api1.Tree;
034import org.cipres.CipresIDL.api1.TreeDecompose;
035import org.cipres.CipresIDL.api1.TreeScore;
036import org.cipres.helpers.CipresRegistry;
037import org.cipres.helpers.RegistryEntryWrapper;
038import org.cipres.util.tree.TreePruner;
039
040import ptolemy.actor.TypedAtomicActor;
041import ptolemy.actor.TypedIOPort;
042import ptolemy.data.ObjectToken;
043import ptolemy.data.type.BaseType;
044import ptolemy.kernel.CompositeEntity;
045import ptolemy.kernel.util.IllegalActionException;
046import ptolemy.kernel.util.NameDuplicationException;
047
048//////////////////////////////////////////////////////////////////////////
049//// TreeDecomposer
050/**
051 * The TreeDecomposer actor decomposes a tree into subtrees. This actor uses the
052 * TreeDecompose service provided by CIPRes CORBA registry.
053 * 
054 * @author Zhijie Guan
055 * @version $Id: TreeDecomposer.java 24234 2010-05-06 05:21:26Z welker $
056 */
057
058public class TreeDecomposer extends TypedAtomicActor {
059
060        /**
061         * Construct a TreeDecomposer actor with the given container and name.
062         * 
063         * @param container
064         *            The container.
065         * @param name
066         *            The name of this actor.
067         * @exception IllegalActionException
068         *                If the entity cannot be contained by the proposed
069         *                container.
070         * @exception NameDuplicationException
071         *                If the container already has an actor with this name.
072         */
073
074        public TreeDecomposer(CompositeEntity container, String name)
075                        throws NameDuplicationException, IllegalActionException {
076                super(container, name);
077
078                // construct the input port inputTree
079                inputTree = new TypedIOPort(this, "inputTree", true, false);
080                inputTree.setDisplayName("Tree");
081                inputTree.setTypeEquals(BaseType.GENERAL);
082
083                // construct the output port outputTrees
084                outputTrees = new TypedIOPort(this, "outputTrees", false, true);
085                outputTrees.setDisplayName("Decomposed Subtrees");
086                // Set the type constraint.
087                outputTrees.setTypeEquals(BaseType.GENERAL);
088
089                _attachText("_iconDescription", "<svg>\n" + "<rect x=\"0\" y=\"0\" "
090                                + "width=\"60\" height=\"20\" " + "style=\"fill:white\"/>\n"
091                                + "</svg>\n");
092
093        }
094
095        // /////////////////////////////////////////////////////////////////
096        // // ports and parameters ////
097
098        /**
099         * A tree in CIPRes tree data structure is passed to the TreeDecomposer
100         * actor through this input port. This port is an input port of type
101         * GENERAL.
102         */
103        public TypedIOPort inputTree = null;
104
105        /**
106         * The decomposed trees are sent out through this output port. All the trees
107         * are wrapped in a single token to facilitate the transportation. This port
108         * is an output port of type GENERAL.
109         */
110        public TypedIOPort outputTrees = null;
111
112        // /////////////////////////////////////////////////////////////////
113        // // functional variables ////
114
115        // /////////////////////////////////////////////////////////////////
116        // // public methods ////
117
118        /**
119         * Decompose the input tree and send the subtrees to the output port.
120         * 
121         * @exception IllegalActionException
122         *                If it is thrown by the send() method sending out the
123         *                token.
124         */
125        public void fire() throws IllegalActionException {
126                super.fire();
127                if (inputTree.hasToken(0)) {
128
129                        RegistryEntryWrapper treeDecomposerWrapper = null;
130                        // subtrees after the decomposition
131                        Tree[] resultTrees = null;
132                        // tokens to wrap each subtree
133                        ObjectToken[] treeTokens = null;
134
135                        try {
136                                TreePruner treePruner = new TreePruner(); // tree pruner
137
138                                // get the TreeDecompose service wrapper
139                                treeDecomposerWrapper = CipresRegistry.getCipresServiceWrapper(
140                                                TreeDecompose.class, null, null);
141                                // get the TreeDecompose service
142                                TreeDecompose decomposer = (TreeDecompose) treeDecomposerWrapper
143                                                .getService();
144                                // get the input tree
145                                Tree wholeTree = (Tree) ((ObjectToken) inputTree.get(0))
146                                                .getValue();
147                                treePruner.setTree(wholeTree.m_newick); // set the treePruner
148
149                                // decompose process
150                                int[][] decompositions = decomposer.leafSetDecompose(wholeTree);
151                                resultTrees = new Tree[decompositions.length];
152                                treeTokens = new ObjectToken[decompositions.length];
153                                for (int i = 0; i < decompositions.length; i++) {
154                                        // create each subtree based on the leaf set decomposition
155                                        Tree tempTree = new Tree();
156                                        tempTree.m_newick = treePruner.pruneTree(decompositions[i]);
157                                        tempTree.m_leafSet = decompositions[i];
158
159                                        // fix_tree service, currently it is not available for
160                                        // public access
161                                        // resultTrees[i] = RecIDcm3Impl.fix_tree( tempTree );
162
163                                        // fix the tempTree. This section should be replaced once
164                                        // the fix_tree is open to public access
165                                        tempTree.m_newick = tempTree.m_newick.trim();
166                                        if (tempTree.m_newick.lastIndexOf(';') == -1) {
167                                                tempTree.m_newick += ";";
168                                        }
169                                        if (tempTree.m_score == null) {
170                                                tempTree.m_score = new TreeScore();
171                                                tempTree.m_score.noScore(0);
172                                        }
173
174                                        resultTrees[i] = tempTree;
175                                        resultTrees[i].m_name = "subset " + i;
176
177                                        // wrap the subtree as a token
178                                        treeTokens[i] = new ObjectToken(resultTrees[i]);
179
180                                        // for debug
181                                        // System.out.println("TreeDecomposer: resultTrees[" + i +
182                                        // "] = " + resultTrees[i].m_newick);
183                                }
184                        } catch (Exception e) {
185                                e.printStackTrace();
186                        } finally {
187                                if (treeDecomposerWrapper != null) {
188                                        // release the TreeDecompose service
189                                        treeDecomposerWrapper.releaseService();
190                                }
191                        }
192
193                        outputTrees.send(0, new ObjectToken(resultTrees));
194                }
195        }
196}