Search in sources :

Example 11 with Tree

use of ini.trakem2.display.Tree in project TrakEM2 by trakem2.

the class Compare method appendAndFork.

/**
 * Recursive.
 */
private static void appendAndFork(final ProjectThing parent, Chain chain, HashSet<ProjectThing> hs_c_done, final ArrayList<Chain> chains, final LayerSet ls, final Pattern exclude) throws Exception {
    if (null != exclude && exclude.matcher(parent.getTitle()).matches()) {
        Utils.logAll("Excluding node " + parent + " with title " + parent.getTitle() + ", and all its children nodes.");
        return;
    }
    final ArrayList<ProjectThing> children = parent.getChildren();
    if (null == children)
        return;
    if (null == hs_c_done)
        hs_c_done = new HashSet<ProjectThing>();
    for (final ProjectThing child : children) {
        if (hs_c_done.contains(child))
            continue;
        if (null != exclude && exclude.matcher(child.getTitle()).matches()) {
            Utils.log2("Excluding child " + child + " with title " + child.getTitle());
            continue;
        }
        hs_c_done.add(child);
        if (child.getObject() instanceof Line3D) {
            final Line3D pipe = (Line3D) child.getObject();
            // not from the same LayerSet, maybe from a nested one.
            if (!pipe.getLayerSet().equals(ls) || pipe.length() < 2)
                continue;
            if (null == chain) {
                chain = new Chain(pipe);
                chains.add(chain);
            } else {
                chain.append(pipe);
            }
            // find other children in the parent who contain children with child pipes
            boolean first = true;
            final Chain base = chain.duplicate();
            for (final ProjectThing c : children) {
                // already visited
                if (hs_c_done.contains(c))
                    continue;
                // c is at the same tree level as child (which contains a pipe directly)
                final ArrayList<Line3D> child_pipes = c.findChildrenOfType(Line3D.class);
                if (child_pipes.size() > 0) {
                    Chain ca;
                    if (first) {
                        // just append
                        ca = chain;
                        first = false;
                    } else {
                        // otherwise make a copy to branch out
                        // can't duplicate from chain itself, because it would have the previous child added to it.
                        ca = base.duplicate();
                        chains.add(ca);
                    }
                    appendAndFork(c, ca, hs_c_done, chains, ls, exclude);
                }
            }
            // pipe wrapping ProjectThing objects cannot have any children
            continue;
        }
        // if it does not have direct pipe children, cut chain - but keep inspecting
        if (0 == child.findChildrenOfType(Line3D.class).size()) {
            chain = null;
        }
        // inspect others down the unvisited tree nodes
        appendAndFork(child, chain, hs_c_done, chains, ls, exclude);
    }
}
Also used : ProjectThing(ini.trakem2.tree.ProjectThing) Line3D(ini.trakem2.display.Line3D) HashSet(java.util.HashSet)

Example 12 with Tree

use of ini.trakem2.display.Tree in project TrakEM2 by trakem2.

the class Project method createNewProject.

private static Project createNewProject(Loader loader, boolean ask_for_template, TemplateThing template_root, boolean clone_ids) {
    Project project = new Project(loader);
    // Utils.log2("ask_for_template: " + ask_for_template);
    if (ask_for_template)
        template_root = project.loader.askForXMLTemplate(project);
    if (null == template_root) {
        template_root = new TemplateThing("anything");
    } else if (clone_ids) {
        // the given template_root belongs to another project from which we are cloning
        template_root = template_root.clone(project, true);
    }
    // else, use the given template_root as is.
    // create tree
    project.template_tree = new TemplateTree(project, template_root);
    project.root_tt = template_root;
    // collect unique TemplateThing instances
    synchronized (project.ht_unique_tt) {
        project.ht_unique_tt.clear();
        project.ht_unique_tt.putAll(template_root.getUniqueTypes(new HashMap<String, TemplateThing>()));
    }
    // add all TemplateThing objects to the database, recursively
    if (!clone_ids)
        template_root.addToDatabase(project);
    // else already done when cloning the root_tt
    // create a non-database bound template for the project Thing
    TemplateThing project_template = new TemplateThing("project");
    project.ht_unique_tt.put("project", project_template);
    project_template.addChild(template_root);
    // create the project Thing, to be root of the whole project thing tree
    try {
        project.root_pt = new ProjectThing(project_template, project, project);
    } catch (Exception e) {
        IJError.print(e);
    }
    // create the user objects tree
    project.project_tree = new ProjectTree(project, project.root_pt);
    // create the layer's tree
    project.createLayerTemplates();
    // initialized with default values, and null parent to signal 'root'
    project.layer_set = new LayerSet(project, "Top Level", 0, 0, null, 2048, 2048);
    try {
        project.root_lt = new LayerThing(Project.layer_set_template, project, project.layer_set);
        project.layer_tree = new LayerTree(project, project.root_lt);
    } catch (Exception e) {
        project.remove();
        IJError.print(e);
    }
    // create the project control window, containing the trees in a double JSplitPane
    // beware that this call is asynchronous, dispatched by the SwingUtilities.invokeLater to avoid havok with Swing components.
    ControlWindow.add(project, project.template_tree, project.project_tree, project.layer_tree);
    // register
    al_open_projects.add(project);
    return project;
}
Also used : ProjectTree(ini.trakem2.tree.ProjectTree) LayerTree(ini.trakem2.tree.LayerTree) HashMap(java.util.HashMap) LayerSet(ini.trakem2.display.LayerSet) LayerThing(ini.trakem2.tree.LayerThing) TemplateThing(ini.trakem2.tree.TemplateThing) TemplateTree(ini.trakem2.tree.TemplateTree) ProjectThing(ini.trakem2.tree.ProjectThing)

Example 13 with Tree

use of ini.trakem2.display.Tree in project TrakEM2 by trakem2.

the class Compare method reliabilityAnalysis.

public static final Bureaucrat reliabilityAnalysis(final String[] ignore, final boolean output_arff, final boolean weka_classify, final boolean show_dialog, final double delta, final double wi, final double wd, final double wm) {
    // gather all open projects
    final Project[] p = Project.getProjects().toArray(new Project[0]);
    final Worker worker = new Worker("Reliability by name") {

        @Override
        public void run() {
            startedWorking();
            try {
                final CATAParameters cp = new CATAParameters();
                cp.delta = delta;
                if (show_dialog && !cp.setup(false, null, false, false)) {
                    finishedWorking();
                    return;
                }
                Object[] ob = gatherChains(p, cp, ignore);
                final ArrayList<Chain> chains = (ArrayList<Chain>) ob[0];
                // to keep track of each project's chains
                final ArrayList[] p_chains = (ArrayList[]) ob[1];
                ob = null;
                if (null == chains) {
                    finishedWorking();
                    return;
                }
                // For each pipe in a brain:
                // - score against all other brains in which that pipe name exists,
                // - record the score position within that brain.
                // 
                final ExecutorService exec = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors());
                // for each individual lineage:
                final TreeMap<String, ArrayList<Integer>> indices = new TreeMap<String, ArrayList<Integer>>();
                final ArrayList<CITuple> cin = new ArrayList<CITuple>();
                // for each family:
                final TreeMap<String, ArrayList<Integer>> indices_f = new TreeMap<String, ArrayList<Integer>>();
                final ArrayList<CITuple> cin_f = new ArrayList<CITuple>();
                final ArrayList<Future> fus = new ArrayList<Future>();
                // For neural network analysis:
                final StringBuilder arff = output_arff ? new StringBuilder("@RELATION Lineages\n\n") : null;
                if (output_arff) {
                    arff.append("@ATTRIBUTE APD NUMERIC\n");
                    arff.append("@ATTRIBUTE CPD NUMERIC\n");
                    arff.append("@ATTRIBUTE STD NUMERIC\n");
                    arff.append("@ATTRIBUTE MPD NUMERIC\n");
                    arff.append("@ATTRIBUTE PM NUMERIC\n");
                    arff.append("@ATTRIBUTE LEV NUMERIC\n");
                    arff.append("@ATTRIBUTE SIM NUMERIC\n");
                    arff.append("@ATTRIBUTE PRX NUMERIC\n");
                    arff.append("@ATTRIBUTE PRM NUMERIC\n");
                    // length ratio: len(query) / len(ref)
                    arff.append("@ATTRIBUTE LR NUMERIC\n");
                    arff.append("@ATTRIBUTE TR NUMERIC\n");
                    arff.append("@ATTRIBUTE CLASS {false,true}\n");
                    arff.append("\n@DATA\n");
                }
                // Count number of times when decision tree says it's good, versus number of times when it should be good
                // observed
                final AtomicInteger obs_good = new AtomicInteger(0);
                // observed wrong
                final AtomicInteger obs_wrong = new AtomicInteger(0);
                // expected
                final AtomicInteger exp_good = new AtomicInteger(0);
                final AtomicInteger exp_bad = new AtomicInteger(0);
                final AtomicInteger obs_bad_classified_good_ones = new AtomicInteger(0);
                final AtomicInteger obs_well_classified_bad_ones = new AtomicInteger(0);
                // inc by one when a lineage to compare is not found at all in the brain that works as reference
                final AtomicInteger not_found = new AtomicInteger(0);
                final AtomicInteger already_classified = new AtomicInteger(0);
                Method classify_ = null;
                if (weka_classify) {
                    try {
                        classify_ = Class.forName("lineage.LineageClassifier").getDeclaredMethod("classify", new Class[] { double[].class });
                    } catch (final Exception e) {
                        IJError.print(e);
                    }
                }
                final Method classify = classify_;
                // All possible pairs of projects, with repetition (it's not the same, although the pipe pairwise comparison itself will be.)
                for (int _i = 0; _i < p_chains.length; _i++) {
                    final int i = _i;
                    Utils.log2("Project " + p[i] + " has " + p_chains[i].size() + " chains.");
                    for (int _j = 0; _j < p_chains.length; _j++) {
                        final int j = _j;
                        // skip same project (would have a score of zero, identical.)
                        if (i == j)
                            continue;
                        final String[] titles_j = new String[p_chains[j].size()];
                        int next = 0;
                        for (final Chain cj : (ArrayList<Chain>) p_chains[j]) {
                            final String t = cj.getCellTitle();
                            titles_j[next++] = t.substring(0, t.indexOf(' '));
                        }
                        // families:
                        final TreeSet<String> ts_families = new TreeSet<String>();
                        for (int f = 0; f < titles_j.length; f++) {
                            // extract family name from title: read the first continuous string of capital letters
                            final String title = titles_j[f];
                            int u = 0;
                            for (; u < title.length(); u++) {
                                if (!Character.isUpperCase(title.charAt(u)))
                                    break;
                            }
                            ts_families.add(title.substring(0, u));
                        }
                        final ArrayList<String> families = new ArrayList<String>(ts_families);
                        fus.add(exec.submit(new Callable() {

                            @Override
                            public Object call() {
                                // All chains of one project to all chains of the other:
                                for (final Chain chain : (ArrayList<Chain>) p_chains[i]) {
                                    final VectorString3D vs1 = chain.vs;
                                    // Prepare title
                                    String title = chain.getCellTitle();
                                    title = title.substring(0, title.indexOf(' '));
                                    // check if the other project j contains a chain of name chain.getCellTitle() up to the space.
                                    int title_index = -1;
                                    for (int k = 0; k < titles_j.length; k++) {
                                        if (title.equals(titles_j[k])) {
                                            title_index = k;
                                            break;
                                        }
                                    }
                                    if (-1 == title_index) {
                                        Utils.log2(title + " not found in project " + p[j]);
                                        if (weka_classify)
                                            not_found.incrementAndGet();
                                        continue;
                                    }
                                    // should be there:
                                    if (weka_classify) {
                                        exp_good.incrementAndGet();
                                        exp_bad.addAndGet(titles_j.length - 1);
                                    }
                                    final ArrayList<ChainMatch> list = new ArrayList<ChainMatch>();
                                    // extract family name from title: read the first continuous string of capital letters
                                    int u = 0;
                                    for (; u < title.length(); u++) {
                                        if (!Character.isUpperCase(title.charAt(u)))
                                            break;
                                    }
                                    final String family_name = title.substring(0, u);
                                    String last_classify = null;
                                    int g = 0;
                                    for (final Chain cj : (ArrayList<Chain>) p_chains[j]) {
                                        final VectorString3D vs2 = cj.vs;
                                        final Object[] ob = findBestMatch(vs1, vs2, cp.delta, cp.skip_ends, cp.max_mut, cp.min_chunk, cp.distance_type, cp.direct, cp.substring_matching, wi, wd, wm);
                                        final Editions ed = (Editions) ob[0];
                                        final double[] stats = ed.getStatistics(cp.skip_ends, cp.max_mut, cp.min_chunk, cp.score_mut_only);
                                        final ChainMatch cm = new ChainMatch(cj, null, ed, stats, score(ed.getSimilarity(), ed.getDistance(), stats[3], Compare.W));
                                        cm.title = titles_j[g];
                                        list.add(cm);
                                        g++;
                                        if (weka_classify) {
                                            // from decision tree: is it good?
                                            final double[] param = new double[11];
                                            for (int p = 0; p < stats.length; p++) param[p] = stats[p];
                                            try {
                                                if (((Boolean) classify.invoke(null, param)).booleanValue()) {
                                                    if (null != last_classify) {
                                                        Utils.log2("ALREADY CLASSIFIED " + title + " as " + last_classify + "  (now: " + cm.title + " )");
                                                        already_classified.incrementAndGet();
                                                    }
                                                    last_classify = cm.title;
                                                    if (title.equals(cm.title)) {
                                                        obs_good.incrementAndGet();
                                                    } else {
                                                        Utils.log2("WRONG CLASSIFICATION of " + title + " as " + cm.title);
                                                        obs_wrong.incrementAndGet();
                                                    }
                                                } else {
                                                    if (title.equals(cm.title)) {
                                                        obs_bad_classified_good_ones.incrementAndGet();
                                                    } else {
                                                        obs_well_classified_bad_ones.incrementAndGet();
                                                    }
                                                }
                                            } catch (final Exception ee) {
                                                IJError.print(ee);
                                            }
                                        }
                                    }
                                    // sort scores:
                                    Compare.sortMatches(list, cp.distance_type, cp.distance_type_2, cp.min_matches);
                                    if (output_arff) {
                                        // Take top 8 and put them into training set for WEKA in arff format
                                        for (int h = 0; h < 8; h++) {
                                            final ChainMatch cm = list.get(h);
                                            final StringBuilder sb = new StringBuilder();
                                            sb.append(cm.phys_dist).append(',').append(cm.cum_phys_dist).append(',').append(cm.stdDev).append(',').append(cm.median).append(',').append(cm.prop_mut).append(',').append(cm.ed.getDistance()).append(',').append(cm.seq_sim).append(',').append(cm.proximity).append(',').append(cm.proximity_mut).append(',').append(cm.prop_len).append(',').append(cm.tortuosity_ratio).append(',').append(title.equals(cm.title)).append(// append('-').append(cm.title.startsWith(family_name)).append('\n');
                                            '\n');
                                            synchronized (arff) {
                                                arff.append(sb);
                                            }
                                        }
                                    }
                                    // record scoring index
                                    int f = 0;
                                    boolean found_specific = false;
                                    boolean found_family = false;
                                    for (final ChainMatch cm : list) {
                                        // Exact match: for each individual lineage
                                        if (!found_specific && title.equals(cm.title)) {
                                            synchronized (indices) {
                                                ArrayList<Integer> al = indices.get(title);
                                                if (null == al) {
                                                    al = new ArrayList<Integer>();
                                                    indices.put(title, al);
                                                    // so I can keep a list of chains sorted by name
                                                    cin.add(new CITuple(title, chain, al));
                                                }
                                                al.add(f);
                                            }
                                            found_specific = true;
                                        }
                                        if (!found_family && cm.title.startsWith(family_name)) {
                                            synchronized (indices_f) {
                                                ArrayList<Integer> al = indices_f.get(family_name);
                                                if (null == al) {
                                                    al = new ArrayList<Integer>();
                                                    indices_f.put(family_name, al);
                                                    cin_f.add(new CITuple(family_name, chain, al));
                                                }
                                                al.add(f);
                                            }
                                            found_family = true;
                                        }
                                        if (found_specific && found_family) {
                                            break;
                                        }
                                        // 
                                        f++;
                                    }
                                    if (!found_specific) {
                                        Utils.log2("NOT FOUND any match for " + title + " within a list of size " + list.size() + ", in project " + chain.getRoot().getProject());
                                    }
                                }
                                return null;
                            }
                        }));
                    }
                }
                for (final Future fu : fus) {
                    try {
                        fu.get();
                    } catch (final Exception e) {
                        IJError.print(e);
                    }
                }
                exec.shutdownNow();
                if (weka_classify) {
                    // so stateful ... it's a sin.
                    try {
                        Class.forName("lineage.LineageClassifier").getDeclaredMethod("flush", new Class[] {}).invoke(null, new Object[] {});
                    } catch (final Exception e) {
                        IJError.print(e);
                    }
                }
                // export ARFF for neural network training
                if (output_arff) {
                    Utils.saveToFile(new File(System.getProperty("user.dir") + "/lineages.arff"), arff.toString());
                }
                // Show the results from indices map
                final StringBuilder sb = new StringBuilder();
                // scoring index vs count of occurrences
                final TreeMap<Integer, Integer> sum = new TreeMap<Integer, Integer>();
                // best scoring index of best family member vs count of ocurrences
                final TreeMap<Integer, Integer> sum_f = new TreeMap<Integer, Integer>();
                // scoring index vs count of ocurrences, within each family
                final TreeMap<String, TreeMap<Integer, Integer>> sum_fw = new TreeMap<String, TreeMap<Integer, Integer>>();
                // From collected data, several kinds of results:
                // - a list of how well each chain scores: its index position in the sorted list of scores of one to many.
                // - a list of how well each chain scores relative to family: the lowest (best) index position of a lineage of the same family in the sorted list of scores.
                sb.append("List of scoring indices for each (starting at index 1, aka best possible score):\n");
                for (final CITuple ci : cin) {
                    // sort indices in place
                    Collections.sort(ci.list);
                    // count occurrences of each scoring index
                    // lowest possible index
                    int last = 0;
                    int count = 1;
                    for (final int i : ci.list) {
                        if (last == i)
                            count++;
                        else {
                            sb.append(ci.title).append(' ').append(last + 1).append(' ').append(count).append('\n');
                            // reset
                            last = i;
                            count = 1;
                        }
                        // global count of occurrences
                        final Integer oi = new Integer(i);
                        sum.put(oi, (sum.containsKey(oi) ? sum.get(oi) : 0) + 1);
                        // Same thing but not for all lineages, but only for lineages within a family:
                        // extract family name from title: read the first continuous string of capital letters
                        int u = 0;
                        for (; u < ci.title.length(); u++) {
                            if (!Character.isUpperCase(ci.title.charAt(u)))
                                break;
                        }
                        final String family_name = ci.title.substring(0, u);
                        TreeMap<Integer, Integer> sfw = sum_fw.get(family_name);
                        if (null == sfw) {
                            sfw = new TreeMap<Integer, Integer>();
                            sum_fw.put(family_name, sfw);
                        }
                        sfw.put(oi, (sfw.containsKey(oi) ? sfw.get(oi) : 0) + 1);
                    }
                    if (0 != count)
                        sb.append(ci.title).append(' ').append(last + 1).append(' ').append(count).append('\n');
                    // find the very-off ones:
                    if (last > 6) {
                        Utils.log2("BAD index " + last + " for chain " + ci.title + " " + ci.chain.getRoot() + " of project " + ci.chain.getRoot().getProject());
                    }
                }
                sb.append("===============================\n");
                // / family score:
                for (final CITuple ci : cin_f) {
                    // sort indices in place
                    Collections.sort(ci.list);
                    // count occurrences of each scoring index
                    // lowest possible index
                    int last = 0;
                    int count = 1;
                    for (final int i : ci.list) {
                        if (last == i)
                            count++;
                        else {
                            // reset
                            last = i;
                            count = 1;
                        }
                        // global count of occurrences
                        final Integer oi = new Integer(i);
                        sum_f.put(oi, (sum_f.containsKey(oi) ? sum_f.get(oi) : 0) + 1);
                    }
                }
                sb.append("===============================\n");
                // - a summarizing histogram that collects how many 1st, how many 2nd, etc. in total, normalized to total number of one-to-many matches performed (i.e. the number of scoring indices recorded.)
                // 
                {
                    sb.append("Global count of index ocurrences:\n");
                    int total = 0;
                    int top2 = 0;
                    int top5 = 0;
                    for (final Map.Entry<Integer, Integer> e : sum.entrySet()) {
                        sb.append(e.getKey()).append(' ').append(e.getValue()).append('\n');
                        total += e.getValue();
                        if (e.getKey() < 2)
                            top2 += e.getValue();
                        if (e.getKey() < 5)
                            top5 += e.getValue();
                    }
                    sb.append("total: ").append(total).append('\n');
                    sb.append("top1: ").append(sum.get(sum.firstKey()) / (float) total).append('\n');
                    sb.append("top2: ").append(top2 / (float) total).append('\n');
                    sb.append("top5: ").append(top5 / (float) total).append('\n');
                    sb.append("===============================\n");
                }
                sb.append("Family-wise count of index ocurrences:\n");
                for (final Map.Entry<String, TreeMap<Integer, Integer>> fe : sum_fw.entrySet()) {
                    int total = 0;
                    int top5 = 0;
                    for (final Map.Entry<Integer, Integer> e : fe.getValue().entrySet()) {
                        sb.append(fe.getKey()).append(' ').append(e.getKey()).append(' ').append(e.getValue()).append('\n');
                        total += e.getValue();
                        if (e.getKey() < 5)
                            top5 += e.getValue();
                    }
                    sb.append("total: ").append(total).append('\n');
                    sb.append("top1: ").append(fe.getValue().get(fe.getValue().firstKey()) / (float) total).append('\n');
                    sb.append("top5: ").append(top5 / (float) total).append('\n');
                }
                sb.append("===============================\n");
                // - the percent of first score being the correct one:
                double first = 0;
                double first_5 = 0;
                double all = 0;
                for (final Map.Entry<Integer, Integer> e : sum.entrySet()) {
                    final int k = e.getKey();
                    final int a = e.getValue();
                    all += a;
                    if (0 == k)
                        first = a;
                    if (k < 5)
                        first_5 += a;
                }
                // STORE
                this.result = new double[] { // Top one ratio
                first / all, // Top 5 ratio
                first_5 / all };
                sb.append("Global count of index occurrences family-wise:\n");
                for (final Map.Entry<Integer, Integer> e : sum_f.entrySet()) {
                    sb.append(e.getKey()).append(' ').append(e.getValue()).append('\n');
                }
                sb.append("===============================\n");
                // - a summarizing histogram of how well each chain scores (4/4, 3/4, 2/4, 1/4, 0/4 only for those that have 4 homologous members.)
                // Must consider that there are 5 projects taken in pairs with repetition.
                sb.append("A summarizing histogram of how well each chain scores, for those that have 4 homologous members. It's the number of 1st scores (zeroes) versus the total number of scores:\n");
                // First, classify them in having 4, 3, 2, 1
                // For 5 brains:  5! / (5-2)! = 5 * 4 = 20   --- 5 elements taken in groups of 2, where order matters
                // For 4 brains:  4! / (4-2)! = 4 * 3 = 12
                // For 3 brains:  3! / (3-2)! = 3 * 2 = 6;
                final TreeMap<Integer, ArrayList<String>> hsc = new TreeMap<Integer, ArrayList<String>>();
                for (final CITuple ci : cin) {
                    final int size = ci.list.size();
                    ArrayList<String> al = hsc.get(size);
                    if (null == al) {
                        al = new ArrayList<String>();
                        hsc.put(size, al);
                    }
                    // Count the number of 0s -- top scoring
                    int count = 0;
                    for (final Integer i : ci.list) {
                        if (0 == i)
                            count++;
                        else
                            break;
                    }
                    al.add(new StringBuffer(ci.title).append(" =").append(count).append('/').append(ci.list.size()).append('\n').toString());
                }
                // Then just print:
                for (final Map.Entry<Integer, ArrayList<String>> e : hsc.entrySet()) {
                    sb.append("For ").append(e.getKey()).append(" matches:\n");
                    for (final String s : e.getValue()) sb.append(s);
                }
                sb.append("=========================\n");
                // Family-wise, count the number of zeros per family:
                sb.append("Number of top scoring per family:\n");
                final TreeMap<String, String> family_scores = new TreeMap<String, String>();
                for (final CITuple ci : cin_f) {
                    int count = 0;
                    for (final Integer i : ci.list) {
                        if (0 == i)
                            count++;
                        else
                            // ci.list is sorted
                            break;
                    }
                    family_scores.put(ci.title, new StringBuilder().append(ci.title).append(" =").append(count).append('/').append(ci.list.size()).append('\n').toString());
                }
                // Now print sorted by family name:
                for (final String s : family_scores.values()) {
                    sb.append(s);
                }
                sb.append("=========================\n");
                if (weka_classify) {
                    sb.append("Decision tree:\n");
                    sb.append("Expected good matches: " + exp_good.get() + "\n");
                    sb.append("Expected bad matches: " + exp_bad.get() + "\n");
                    sb.append("Observed good matches: " + obs_good.get() + "\n");
                    sb.append("Observed bad matches: " + obs_wrong.get() + "\n");
                    sb.append("Observed well classified bad ones: " + obs_well_classified_bad_ones.get() + "\n");
                    sb.append("Observed bad classified good ones: " + obs_bad_classified_good_ones.get() + "\n");
                    sb.append("Not found, so skipped: " + not_found.get() + "\n");
                    sb.append("Already classified: " + already_classified.get() + "\n");
                    sb.append("=========================\n");
                }
                if (output_arff) {
                    Utils.log(sb.toString());
                } else {
                    Utils.log2(sb.toString());
                }
            } catch (final Exception e) {
                e.printStackTrace();
            } finally {
                finishedWorking();
            }
        }
    };
    return Bureaucrat.createAndStart(worker, p);
}
Also used : ArrayList(java.util.ArrayList) TreeSet(java.util.TreeSet) Method(java.lang.reflect.Method) Project(ini.trakem2.Project) AtomicInteger(java.util.concurrent.atomic.AtomicInteger) File(java.io.File) Map(java.util.Map) HashMap(java.util.HashMap) TreeMap(java.util.TreeMap) CATAParameters(ini.trakem2.analysis.Compare.CATAParameters) Callable(java.util.concurrent.Callable) Worker(ini.trakem2.utils.Worker) TreeMap(java.util.TreeMap) AtomicInteger(java.util.concurrent.atomic.AtomicInteger) Editions(ini.trakem2.vector.Editions) VectorString3D(ini.trakem2.vector.VectorString3D) ExecutorService(java.util.concurrent.ExecutorService) Future(java.util.concurrent.Future)

Example 14 with Tree

use of ini.trakem2.display.Tree in project TrakEM2 by trakem2.

the class DisplayCanvas method keyPressed.

@Override
public void keyPressed(final KeyEvent ke) {
    final Displayable active = display.getActive();
    if (null != freehandProfile && ProjectToolbar.getToolId() == ProjectToolbar.PENCIL && ke.getKeyCode() == KeyEvent.VK_ESCAPE && null != freehandProfile) {
        freehandProfile.abort();
        ke.consume();
        return;
    }
    final int keyCode = ke.getKeyCode();
    try {
        // Enable tagging system for any alphanumeric key:
        if (!input_disabled && null != active && active instanceof Tree<?> && ProjectToolbar.isDataEditTool(ProjectToolbar.getToolId())) {
            if (tagging) {
                if (KeyEvent.VK_0 == keyCode && KeyEvent.VK_0 != last_keyCode) {
                // do nothing: keep tagging as true
                } else {
                    // last step of tagging: a char after t or after t and a number (and the char itself can be a number)
                    tagging = false;
                }
                active.keyPressed(ke);
                return;
            } else if (KeyEvent.VK_T == keyCode) {
                tagging = true;
                active.keyPressed(ke);
                return;
            }
        }
    } finally {
        last_keyCode = keyCode;
    }
    tagging = false;
    if (ke.isConsumed())
        return;
    if (!zoom_and_pan) {
        if (KeyEvent.VK_ESCAPE == keyCode) {
            cancelAnimations();
        }
        return;
    }
    final int keyChar = ke.getKeyChar();
    boolean used = false;
    switch(keyChar) {
        case '+':
        case '=':
            zoomIn();
            used = true;
            break;
        case '-':
        case '_':
            zoomOut();
            used = true;
            break;
        default:
            break;
    }
    if (used) {
        // otherwise ImageJ would use it!
        ke.consume();
        return;
    }
    if (input_disabled) {
        if (KeyEvent.VK_ESCAPE == keyCode) {
            // cancel last job if any
            if (Utils.checkYN("Really cancel job?")) {
                display.getProject().getLoader().quitJob(null);
                display.repairGUI();
            }
        }
        ke.consume();
        // only zoom is enabled, above
        return;
    }
    if (KeyEvent.VK_S == keyCode && 0 == ke.getModifiers() && display.getProject().getLoader().isAsynchronous()) {
        display.getProject().getLoader().saveTask(display.getProject(), "Save");
        ke.consume();
        return;
    } else if (KeyEvent.VK_F == keyCode && Utils.isControlDown(ke)) {
        Search.showWindow();
        ke.consume();
        return;
    }
    // if display is not read-only, check for other keys:
    switch(keyChar) {
        case '<':
        case // select next Layer up
        ',':
            // repaints as well
            display.previousLayer(ke.getModifiers());
            ke.consume();
            return;
        case '>':
        case // select next Layer down
        '.':
            display.nextLayer(ke.getModifiers());
            ke.consume();
            return;
    }
    if (null == active && null != imp.getRoi() && KeyEvent.VK_A != keyCode) {
        // control+a and a roi should select under roi
        IJ.getInstance().keyPressed(ke);
        return;
    }
    // end here if display is read-only
    if (display.isReadOnly()) {
        ke.consume();
        display.repaintAll();
        return;
    }
    if (KeyEvent.VK_ENTER == keyCode) {
        if (isTransforming()) {
            applyTransform();
            ke.consume();
            return;
        } else {
            IJ.getInstance().toFront();
            ke.consume();
            return;
        }
    }
    // check preconditions (or the keys are meaningless). Allow 'enter' to
    // bring forward the ImageJ window, and 'v' to paste a patch.
    /*if (null == active && KeyEvent.VK_ENTER != keyCode && KeyEvent.VK_V != keyCode && KeyEvent) {
			return;
		}*/
    final Layer layer = display.getLayer();
    final int mod = ke.getModifiers();
    switch(keyCode) {
        case KeyEvent.VK_COMMA:
        case // select next Layer up
        0xbc:
            display.nextLayer(ke.getModifiers());
            break;
        case KeyEvent.VK_PERIOD:
        case // select next Layer down
        0xbe:
            display.previousLayer(ke.getModifiers());
            break;
        case KeyEvent.VK_Z:
            // UNDO: shift+z or ctrl+z
            if (0 == (mod ^ Event.SHIFT_MASK) || 0 == (mod ^ Utils.getControlModifier())) {
                Bureaucrat.createAndStart(new Worker.Task("Undo") {

                    @Override
                    public void exec() {
                        if (isTransforming())
                            display.getMode().undoOneStep();
                        else
                            display.getLayerSet().undoOneStep();
                        Display.repaint(display.getLayerSet());
                    }
                }, display.getProject());
                ke.consume();
            // REDO: alt+z or ctrl+shift+z
            } else if (0 == (mod ^ Event.ALT_MASK) || 0 == (mod ^ (Event.SHIFT_MASK | Utils.getControlModifier()))) {
                Bureaucrat.createAndStart(new Worker.Task("Redo") {

                    @Override
                    public void exec() {
                        if (isTransforming())
                            display.getMode().redoOneStep();
                        else
                            display.getLayerSet().redoOneStep();
                        Display.repaint(display.getLayerSet());
                    }
                }, display.getProject());
                ke.consume();
            }
            // else, the 'z' command restores the image using ImageJ internal undo
            break;
        case KeyEvent.VK_T:
            // Enable with any tool to the left of the PENCIL
            if (null != active && !isTransforming() && ProjectToolbar.getToolId() < ProjectToolbar.PENCIL) {
                ProjectToolbar.setTool(ProjectToolbar.SELECT);
                if (0 == ke.getModifiers()) {
                    display.setMode(new AffineTransformMode(display));
                } else if (Event.SHIFT_MASK == ke.getModifiers()) {
                    for (final Displayable d : display.getSelection().getSelected()) {
                        if (d.isLinked()) {
                            Utils.showMessage("Can't enter manual non-linear transformation mode:\nat least one image is linked.");
                            return;
                        }
                    }
                    display.setMode(new NonLinearTransformMode(display));
                }
                ke.consume();
            }
            // else, let ImageJ grab the ROI into the Manager, if any
            break;
        case KeyEvent.VK_A:
            if (0 == (ke.getModifiers() ^ Utils.getControlModifier())) {
                final Roi roi = getFakeImagePlus().getRoi();
                if (null != roi)
                    display.getSelection().selectAll(roi, true);
                else
                    display.getSelection().selectAllVisible();
                Display.repaint(display.getLayer(), display.getSelection().getBox(), 0);
                ke.consume();
                // INSIDE the 'if' block, so that it can bleed to the default block which forwards to active!
                break;
            } else if (null != active) {
                active.keyPressed(ke);
                if (ke.isConsumed())
                    break;
            // TODO this is just a hack really. Should just fall back to default switch option.
            // The whole keyPressed method needs revision: should not break from it when not using the key.
            }
            break;
        case // cancel transformation
        KeyEvent.VK_ESCAPE:
            if (isTransforming())
                cancelTransform();
            else {
                // deselect
                display.select(null);
                // repaint out the brush if present
                if (ProjectToolbar.BRUSH == ProjectToolbar.getToolId()) {
                    repaint(old_brush_box, 0);
                }
            }
            ke.consume();
            break;
        case KeyEvent.VK_SPACE:
            if (0 == ke.getModifiers()) {
                if (null != active) {
                    invalidateVolatile();
                    if (Math.abs(active.getAlpha() - 0.5f) > 0.001f)
                        active.setAlpha(0.5f);
                    else
                        active.setAlpha(1.0f);
                    display.setTransparencySlider(active.getAlpha());
                    Display.repaint();
                    ke.consume();
                }
            } else {
                // ;)
                final int kem = ke.getModifiers();
                if (0 != (kem & KeyEvent.SHIFT_MASK) && 0 != (kem & KeyEvent.ALT_MASK) && 0 != (kem & KeyEvent.CTRL_MASK)) {
                    Utils.showMessage("A mathematician, like a painter or poet,\nis a maker of patterns.\nIf his patterns are more permanent than theirs,\nit is because they are made with ideas\n \nG. H. Hardy.");
                    ke.consume();
                }
            }
            break;
        case KeyEvent.VK_S:
            if (ke.isAltDown()) {
                snapping = true;
                ke.consume();
            } else if (dragging) {
                // ignore improper 's' that open ImageJ's save dialog (linux problem ... in macosx, a single dialog opens with lots of 'ssss...' in the text field)
                ke.consume();
            }
            break;
        case KeyEvent.VK_H:
            handleHide(ke);
            ke.consume();
            break;
        case KeyEvent.VK_J:
            if (!display.getSelection().isEmpty()) {
                display.adjustMinAndMaxGUI();
                ke.consume();
            }
            break;
        case KeyEvent.VK_F1:
        case KeyEvent.VK_F2:
        case KeyEvent.VK_F3:
        case KeyEvent.VK_F4:
        case KeyEvent.VK_F5:
        case KeyEvent.VK_F6:
        case KeyEvent.VK_F7:
        case KeyEvent.VK_F8:
        case KeyEvent.VK_F9:
        case KeyEvent.VK_F10:
        case KeyEvent.VK_F11:
        case KeyEvent.VK_F12:
            ProjectToolbar.keyPressed(ke);
            ke.consume();
            break;
        case KeyEvent.VK_M:
            if (0 == ke.getModifiers() && ProjectToolbar.getToolId() == ProjectToolbar.SELECT) {
                display.getSelection().measure();
                ke.consume();
            }
            break;
    }
    switch(keyChar) {
        case ':':
        case ';':
            if (null != active && active instanceof ZDisplayable) {
                if (null != display.getProject().getProjectTree().tryAddNewConnector(active, true)) {
                    ProjectToolbar.setTool(ProjectToolbar.PEN);
                }
                ke.consume();
            }
            break;
    }
    if (ke.isConsumed())
        return;
    if (null != active) {
        if (display.getMode().getClass() == DefaultMode.class) {
            active.keyPressed(ke);
        }
        if (ke.isConsumed())
            return;
    }
    // Else:
    switch(keyCode) {
        case KeyEvent.VK_G:
            if (browseToNodeLayer(ke.isShiftDown())) {
                ke.consume();
            }
            break;
        case KeyEvent.VK_I:
            if (ke.isAltDown()) {
                if (ke.isShiftDown())
                    display.importImage();
                else
                    display.importNextImage();
                ke.consume();
            }
            break;
        case // as in Inkscape
        KeyEvent.VK_PAGE_UP:
            if (null != active) {
                update_graphics = true;
                layer.getParent().addUndoMoveStep(active);
                layer.getParent().move(LayerSet.UP, active);
                layer.getParent().addUndoMoveStep(active);
                Display.repaint(layer, active, 5);
                Display.updatePanelIndex(layer, active);
                ke.consume();
            }
            break;
        case // as in Inkscape
        KeyEvent.VK_PAGE_DOWN:
            if (null != active) {
                update_graphics = true;
                layer.getParent().addUndoMoveStep(active);
                layer.getParent().move(LayerSet.DOWN, active);
                layer.getParent().addUndoMoveStep(active);
                Display.repaint(layer, active, 5);
                Display.updatePanelIndex(layer, active);
                ke.consume();
            }
            break;
        case // as in Inkscape
        KeyEvent.VK_HOME:
            if (null != active) {
                update_graphics = true;
                layer.getParent().addUndoMoveStep(active);
                layer.getParent().move(LayerSet.TOP, active);
                layer.getParent().addUndoMoveStep(active);
                Display.repaint(layer, active, 5);
                Display.updatePanelIndex(layer, active);
                ke.consume();
            }
            break;
        case // as in Inkscape
        KeyEvent.VK_END:
            if (null != active) {
                update_graphics = true;
                layer.getParent().addUndoMoveStep(active);
                layer.getParent().move(LayerSet.BOTTOM, active);
                layer.getParent().addUndoMoveStep(active);
                Display.repaint(layer, active, 5);
                Display.updatePanelIndex(layer, active);
                ke.consume();
            }
            break;
        case KeyEvent.VK_V:
            if (0 == ke.getModifiers()) {
                if (null == active || active.getClass() == Patch.class) {
                    // paste a new image
                    final ImagePlus clipboard = ImagePlus.getClipboard();
                    if (null != clipboard) {
                        final ImagePlus imp = new ImagePlus(clipboard.getTitle() + "_" + System.currentTimeMillis(), clipboard.getProcessor().crop());
                        final Object info = clipboard.getProperty("Info");
                        if (null != info)
                            imp.setProperty("Info", (String) info);
                        final double x = srcRect.x + srcRect.width / 2 - imp.getWidth() / 2;
                        final double y = srcRect.y + srcRect.height / 2 - imp.getHeight() / 2;
                        // save the image somewhere:
                        final Patch pa = display.getProject().getLoader().addNewImage(imp, x, y);
                        display.getLayer().add(pa);
                        ke.consume();
                    }
                // TODO there isn't much ImageJ integration in the pasting. Can't paste to a selected image, for example.
                } else {
                    // Each type may know how to paste data from the copy buffer into itself:
                    active.keyPressed(ke);
                    ke.consume();
                }
            }
            break;
        case KeyEvent.VK_P:
            if (0 == ke.getModifiers()) {
                display.getLayerSet().color_cues = !display.getLayerSet().color_cues;
                Display.repaint(display.getLayerSet());
                ke.consume();
            }
            break;
        case KeyEvent.VK_F:
            if (0 == (ke.getModifiers() ^ KeyEvent.SHIFT_MASK)) {
                // toggle visibility of tags
                display.getLayerSet().paint_tags = !display.getLayerSet().paint_tags;
                Display.repaint();
                ke.consume();
            } else if (0 == (ke.getModifiers() ^ KeyEvent.ALT_MASK)) {
                // toggle visibility of edge arrows
                display.getLayerSet().paint_arrows = !display.getLayerSet().paint_arrows;
                Display.repaint();
                ke.consume();
            } else if (0 == ke.getModifiers()) {
                // toggle visibility of edge confidence boxes
                display.getLayerSet().paint_edge_confidence_boxes = !display.getLayerSet().paint_edge_confidence_boxes;
                Display.repaint();
                ke.consume();
            }
            break;
        case KeyEvent.VK_DELETE:
            if (0 == ke.getModifiers()) {
                display.getSelection().deleteAll();
            }
            break;
        case KeyEvent.VK_B:
            if (0 == ke.getModifiers() && null != active && active.getClass() == Profile.class) {
                display.duplicateLinkAndSendTo(active, 0, active.getLayer().getParent().previous(layer));
                ke.consume();
            }
            break;
        case KeyEvent.VK_N:
            if (0 == ke.getModifiers() && null != active && active.getClass() == Profile.class) {
                display.duplicateLinkAndSendTo(active, 1, active.getLayer().getParent().next(layer));
                ke.consume();
            }
            break;
        case KeyEvent.VK_1:
        case KeyEvent.VK_2:
        case KeyEvent.VK_3:
        case KeyEvent.VK_4:
        case KeyEvent.VK_5:
        case KeyEvent.VK_6:
        case KeyEvent.VK_7:
        case KeyEvent.VK_8:
        case KeyEvent.VK_9:
            // run a plugin, if any
            if (null != Utils.launchTPlugIn(ke, "Display", display.getProject(), display.getActive())) {
                ke.consume();
                break;
            }
    }
    if (!(keyCode == KeyEvent.VK_UNDEFINED || keyChar == KeyEvent.CHAR_UNDEFINED) && !ke.isConsumed() && null != active && active instanceof Patch) {
        // TODO should allow forwarding for all, not just Patch
        // forward to ImageJ for a final try
        IJ.getInstance().keyPressed(ke);
        repaint(active, 5);
        ke.consume();
    }
// Utils.log2("keyCode, keyChar: " + keyCode + ", " + keyChar + " ref: " + KeyEvent.VK_UNDEFINED + ", " + KeyEvent.CHAR_UNDEFINED);
}
Also used : Roi(ij.gui.Roi) ImagePlus(ij.ImagePlus) Point(java.awt.Point) Worker(ini.trakem2.utils.Worker)

Example 15 with Tree

use of ini.trakem2.display.Tree in project TrakEM2 by trakem2.

the class Layer method exportXML.

@Override
public void exportXML(final StringBuilder sb_body, final String indent, final XMLOptions options) {
    final String in = indent + "\t";
    // 1 - open tag
    sb_body.append(indent).append("<t2_layer oid=\"").append(id).append("\"\n").append(in).append(" thickness=\"").append(thickness).append("\"\n").append(in).append(" z=\"").append(z).append("\"\n");
    // TODO this search is linear!
    final LayerThing lt = project.findLayerThing(this);
    String title;
    if (null == lt)
        title = null;
    else
        title = lt.getTitle();
    if (null == title)
        title = "";
    // TODO 'title' should be a property of the Layer, not the LayerThing. Also, the LayerThing should not exist: LayerSet and Layer should be directly presentable in a tree. They are not Things as in "objects of the sample", but rather, structural necessities such as Patch.
    sb_body.append(in).append(" title=\"").append(title).append("\"\n");
    sb_body.append(indent).append(">\n");
    // 2 - export children
    if (null != al_displayables) {
        for (final Displayable d : al_displayables) {
            d.exportXML(sb_body, in, options);
        }
    }
    // 3 - close tag
    sb_body.append(indent).append("</t2_layer>\n");
}
Also used : LayerThing(ini.trakem2.tree.LayerThing)

Aggregations

ArrayList (java.util.ArrayList)14 HashMap (java.util.HashMap)13 HashSet (java.util.HashSet)10 Displayable (ini.trakem2.display.Displayable)9 ZDisplayable (ini.trakem2.display.ZDisplayable)9 ProjectThing (ini.trakem2.tree.ProjectThing)9 Project (ini.trakem2.Project)8 DBObject (ini.trakem2.persistence.DBObject)8 LayerSet (ini.trakem2.display.LayerSet)7 TemplateThing (ini.trakem2.tree.TemplateThing)7 TreePath (javax.swing.tree.TreePath)7 GenericDialog (ij.gui.GenericDialog)6 Layer (ini.trakem2.display.Layer)6 LayerThing (ini.trakem2.tree.LayerThing)6 List (java.util.List)6 Map (java.util.Map)6 DefaultMutableTreeNode (javax.swing.tree.DefaultMutableTreeNode)6 ProjectTree (ini.trakem2.tree.ProjectTree)5 Worker (ini.trakem2.utils.Worker)5 ImagePlus (ij.ImagePlus)4