package moduls.frm.Panels;
import genomeObjects.AnnotatedGenome;
import genomeObjects.CSDisplayData;
import genomeObjects.ContextSetDataFromJpanBtn;
import genomeObjects.ContextSetDescription;
import genomeObjects.ExtendedCRON;
import genomeObjects.GenomicElement;
import genomeObjects.GenomicElementAndQueryMatch;
import genomeObjects.OrganismSet;
import importExport.DadesExternes;
import importExport.FitxerDades;
import inicial.Language;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.Cursor;
import java.awt.Dimension;
import java.awt.FileDialog;
import java.awt.Font;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.io.IOException;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.LinkedList;
import java.util.Set;
import java.util.Map.Entry;
import javax.swing.AbstractAction;
import javax.swing.BorderFactory;
import javax.swing.ButtonGroup;
import javax.swing.JButton;
import javax.swing.JComboBox;
import javax.swing.JFrame;
import javax.swing.JInternalFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JProgressBar;
import javax.swing.JRadioButton;
import javax.swing.JScrollPane;
import javax.swing.JTextField;
import javax.swing.SwingWorker;
import javax.swing.event.InternalFrameEvent;
import javax.swing.event.InternalFrameListener;
import org.biojava3.core.sequence.Strand;
import methods.Reagrupa;
import moduls.frm.ContextLeaf;
import moduls.frm.FrmInternalFrame;
import moduls.frm.FrmPrincipalDesk;
import moduls.frm.InternalFrameData;
import moduls.frm.PostSearchAnalyses;
import moduls.frm.QueryData;
import moduls.frm.Panels.Jpan_btn.MDComputation;
import moduls.frm.children.FrmGraph;
import moduls.frm.children.FrmPhylo;
import moduls.frm.children.FrmPiz;
import moduls.frm.children.FrmSearchResults;
import moduls.frm.children.FrmTabbed;
import moduls.frm.children.manageContextSetsv2;
import parser.EscalaFigures;
import parser.Fig_Pizarra;
import parser.figures.Marge;
import tipus.Orientation;
import tipus.metodo;
import tipus.tipusDades;
import definicions.CfgPanelMenu;
import definicions.Cluster;
import definicions.Config;
import definicions.MatriuDistancies;
public class Jpan_btn_NEW extends JPanel implements ActionListener,
InternalFrameListener, PropertyChangeListener {
// ----- Fields -----------------------------------------------//
private static final long serialVersionUID = 1L;
// Desktop where the dendrogram is to be shown
private final FrmPrincipalDesk fr;
//this button
protected Jpan_btn_NEW jb;
// Text to show in the buttons
private String strSubmit, strAnnsearch, strClusearch;
private String strManageCS = "Add/Remove";
private String strCancel = "Cancel";
// radio buttons for search type
private ButtonGroup searchType;
private JRadioButton annotationSearch, clusterSearch;
// Load and update buttons
public static JButton btnManage, btnSubmit, btnUpdate;
private JButton btnCancel;
// Indicates if the buttons Load or Update are being clicked
public static boolean buttonClicked = false;
// Internal frame currently active
private FrmInternalFrame currentInternalFrame = null;
public FrmInternalFrame getCurrentInternalFrame() {
return currentInternalFrame;
}
// File with the input data
private static FitxerDades fitx = null; //path to file
public DadesExternes de; //determined by annotation search / clustering
private static JTextField txtFileName, contextSetHeader, searchField;
private final Dimension searchFieldSize;
// MultiDendrogram
private MatriuDistancies multiDendro = null;
// Progress bar for MultiDendrogram computation
private JProgressBar progressBar;
// Menu to select current context set
private JComboBox<String> contextSetMenu;
//private LinkedList<String> ContextList = new LinkedList<String>();
// Indicate if the text fields have correct values
public static boolean precisionCorrect = false;
public static boolean axisMinCorrect = false;
public static boolean axisMaxCorrect = false;
public static boolean axisSeparationCorrect = false;
public static boolean axisEveryCorrect = false;
public static boolean axisDecimalsCorrect = false;
private boolean ProceedWithSearch = false;
//Standard font + big font
private Font fontStandard = new Font("Dialog", Font.BOLD, 10);
private Font bigFont = new Font("Dialog", Font.BOLD, 14);
//Section labels
private JLabel ContextSetSelect, SearchGenomes;
// ----- New Fields (1.0) --------------------------------------------//
//These fields modify the new scrollable tree
public static int HorizontalScrollBuffer = 30;
private int VerticalScrollValue = 1500;
private String currentQuery;
// ----- New Fields (1.1) --------------------------------------------//
//searches are handled by a single Swing Worker
private SearchWorker CurrentSearch = null;
private String strUpdate = "Update";
//display search results
private FrmSearchResults SearchResultsFrame = new FrmSearchResults();
//parameters associated with phylo tree
private double PhyloTreeLength;
private int PhyloTreeLeaves;
// ----- New Fields (1.2) --------------------------------------------//
public static int ScrollInc = 30;
// ----- Methods -----------------------------------------------//
// ---- Thread Workers for Searches ------------------------//
//Unified SwingWorker for searches + multidendrogram computations
public class SearchWorker extends SwingWorker<Void, Void>{
//fields
//search-related
private String[] Queries;
private int[] ClusterNumber;
private String ContextSetName;
private String DissimilarityMethod;
private String Name;
private boolean AnnotationSearch;
private DadesExternes ProcessedDE;
private QueryData WorkerQD;
//options-related
private PostSearchAnalyses AnalysesList;
//dendrogram-related
private final String action;
private final tipusDades typeData;
private final metodo method;
private final int precision;
private int nbElements;
private double minBase;
//display /process related
private boolean DisplayOutput;
private boolean ExceptionThrown = false;
//final
public Cluster RootCluster = null;
public boolean ProcessCompleted = false;
public boolean RenderOutput = false;
//constructor
public SearchWorker(final QueryData QD, final String action,
final tipusDades typeData, final metodo method,
final int precision, boolean DisplayOutput){
//Query Data (QD)
this.WorkerQD = QD;
this.Queries = QD.getQueries();
this.ClusterNumber = QD.getClusters();
this.ContextSetName = QD.getContextSetName();
this.DissimilarityMethod = QD.getDissimilarityType();
this.Name = QD.getName();
this.AnnotationSearch = QD.isAnnotationSearch();
//Analyses options
this.AnalysesList = QD.getAnalysesList();
//multidendrogram-related parameters
this.action = action;
this.typeData = typeData;
this.method = method;
this.precision = precision;
//display-related
this.DisplayOutput = DisplayOutput;
}
@Override
protected Void doInBackground() throws Exception {
try {
if (DisplayOutput){
//visualization-related things
fr.setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
progressBar.setBorderPainted(true);
progressBar.setString(null);
multiDendro = null;
de = null;
}
//Search organisms
if (AnnotationSearch){
SearchOrganismsbyAnnotation();
} else {
SearchOrganismsbyCluster();
}
//only display output if the thread was no interrupted.
if (!Thread.currentThread().isInterrupted()){
if (DisplayOutput){
if (this.WorkerQD.getCSD().getEC().getNumberOfEntries() == 1){
System.out.println("Search Completed. " + this.WorkerQD.getCSD().getEC().getNumberOfEntries() + " Gene Grouping Recovered.");
} else {
System.out.println("Search Completed. " + this.WorkerQD.getCSD().getEC().getNumberOfEntries() + " Gene Groupings Recovered.");
}
}
//adjust analyses options based on number of matches.
if (this.WorkerQD.getCSD().getEC().getNumberOfEntries() < 2){
this.WorkerQD.getAnalysesList().setOptionComputeDendrogram(false);
this.WorkerQD.getAnalysesList().setOptionComputeContextGraph(false);
if (this.WorkerQD.getCSD().getEC().getNumberOfEntries() == 0){
String errMsg = "There were no matches to the query (or queries).";
SearchResultsFrame = new FrmSearchResults();
if (DisplayOutput){
showError(errMsg);
}
ExceptionThrown = true;
RootCluster = null;
}
}
}
//Analyses options
//=================================//
//check to ensure that this search worker has not been cancelled.
//if (!fr.isSearchWorkerCancelled()){
if (!ExceptionThrown){
//(1) Construct search pane
if (!Thread.currentThread().isInterrupted()){
if (AnalysesList.isOptionDisplaySearches()){
CreateSearchPanel();
}
} else {
//re-set cursor, progress bar
fr.setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
setProgress(0);
progressBar.setString("");
progressBar.setBorderPainted(false);
//set cancellation parameter for EDT
fr.setSearchWorkerCancelled(true);
}
//(2) Compute dendrogram
if (!Thread.currentThread().isInterrupted()){
if (AnalysesList.isOptionComputeDendrogram()){
//testing
//System.out.println("Entries: " + this.WorkerQD.getCSD().getEC().getNumberOfEntries());
ComputeDendrogram();
}
//if the process has been cancelled, restore defaults.
} else {
//re-set cursor, progress bar
fr.setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
setProgress(0);
progressBar.setString("");
progressBar.setBorderPainted(false);
//set cancellation parameter for EDT
fr.setSearchWorkerCancelled(true);
}
}
//very last step - rendering int output is a go!
RenderOutput = true;
} catch (Exception ex) {
if (DisplayOutput){
showError("There were no matches to the query (or queries).");
}
ExceptionThrown = true;
ex.printStackTrace();
}
//exit background thread
return null;
}
//Required Operations
//(A) Perform Search [Required]
//============================================//
//by annotation
protected Void SearchOrganismsbyAnnotation(){
//re-set progress value
int progress = 0;
//cassette versus non-cassette context sets
boolean isCassette = false;
//recover the context set description
ContextSetDescription CurrentCSD = null;
for (ContextSetDescription csd : fr.getOS().getCSDs()){
if (csd.getName().contentEquals(this.ContextSetName)){
CurrentCSD = csd;
break;
}
}
//System.out.println("CSD: " + CurrentCSD.getName());
//set context set name
String ContextSetName = this.ContextSetName;
//Cassette Option - Switch to the cassette type
if (CurrentCSD.isCassette()){
isCassette = true;
ContextSetName = CurrentCSD.getCassetteOf();
//recover the context set description of the cassette
for (ContextSetDescription csd : fr.getOS().getCSDs()){
if (csd.getName().contentEquals(ContextSetName)){
CurrentCSD = csd;
break;
}
}
}
//initialize output
ExtendedCRON EC = new ExtendedCRON();
//set name and type of CRON.
EC.setName(this.Name);
EC.setContextSetName(this.ContextSetName);
EC.setSearchType("annotation");
EC.setQueries(this.Queries);
//initialize output
//actual context mapping
LinkedHashMap<String, LinkedList<GenomicElementAndQueryMatch>> ContextSetList =
new LinkedHashMap<String, LinkedList<GenomicElementAndQueryMatch>>();
//species names
LinkedHashMap<String, String> SourceNames =
new LinkedHashMap<String, String>();
//contig names
LinkedHashMap<String, HashSet<String>> ContigNames =
new LinkedHashMap<String, HashSet<String>>();
//initialize a counter variable
int Counter = 0;
int SpeciesCounter = 0;
//Initialize a hash map to use for the case of cassette contexts.
HashSet<String> GenesForCassettes = new HashSet<String>();
//Initialize a hash map for the use of RetainFraction-type analysis.
//Annotation Counts
LinkedHashMap<String, Integer> AnnCounts = new LinkedHashMap<String, Integer>();
//increment number of genomic groupings
int GGCounter = 0;
//iterate through species.
for (Entry<String, AnnotatedGenome> entry : fr.getOS().getSpecies().entrySet()) {
//initialize output
HashSet<LinkedList<GenomicElementAndQueryMatch>> Matches = null;
if (CurrentCSD.isPreprocessed()){
//pre-processed cases
Matches = entry.getValue().AnnotationMatches(this.Queries, ContextSetName);
} else {
//on-the-fly
if (CurrentCSD.getType().contentEquals("GenesBetween") && Queries.length != 2) {
JOptionPane.showMessageDialog(null, "This gene grouping requires exactly two search queries.",
"Inappropriate Number of Queries",JOptionPane.ERROR_MESSAGE);
} else {
Matches = entry.getValue().MatchesOnTheFly(this.Queries, null, CurrentCSD);
}
}
//option: condense into single list + update matches
if (CurrentCSD.isSingleOrganismAmalgamation()){
Matches = Amalgamate(CurrentCSD.isSingleOrganismAmalgamation(),
CurrentCSD.isSingleOrganismAmalgamationKeepEmpty(), Matches);
}
//take note of AND statements
if (!this.WorkerQD.ANDStatementsParsed){
this.WorkerQD.BuildANDStatements("annotation");
}
Matches = ANDStatementFilter("annotation",Matches);
//consider the iff and only iff clause
if (WorkerQD.ifAndOnlyif){
Matches = IfAndOnlyIfFilter(Matches);
}
//filter matches in operon expansion case
if (CurrentCSD.isOperonExpansion && Matches.size() > 0){
Matches = RemoveOverlappingSubsets(Matches);
}
//create an iterator for the HashSet
Iterator<LinkedList<GenomicElementAndQueryMatch>> it = Matches.iterator();
//iterate through HashSet, with string-based keys
int OperonCounter = 0; //reset operon counter
while(it.hasNext()){
//increment counter
GGCounter++;
//context unit object
LinkedList<GenomicElementAndQueryMatch> ContextSegment = it.next();
//Counts for retain fraction
if (CurrentCSD.isRetainFractionEnabled()){
//multiple copies of a single cluster num don't score better
HashSet<String> ClusterAnns = new HashSet<String>();
for (GenomicElementAndQueryMatch GandE : ContextSegment){
String Ann = GandE.getE().getAnnotation().trim().toUpperCase();
ClusterAnns.add(Ann);
}
Iterator<String> CS_it = ClusterAnns.iterator();
while (CS_it.hasNext()){
String ClusterAnn = CS_it.next();
//add to hash map
if (AnnCounts.get(ClusterAnn) == null){
AnnCounts.put(ClusterAnn, 1);
} else {
int Count = AnnCounts.get(ClusterAnn);
Count++;
AnnCounts.put(ClusterAnn,Count);
}
}
}
//increment counters
OperonCounter++;
Counter++;
//define key
String Key = entry.getKey() + "-" + Integer.toString(OperonCounter);
//put elements into hashmap
ContextSetList.put(Key, ContextSegment);
//record other info
SourceNames.put(Key, entry.getValue().getSpecies());
HashSet<String> HSContigNames = new HashSet<String>();
for (GenomicElementAndQueryMatch GandE : ContextSegment){
HSContigNames.add(GandE.getE().getContig());
}
ContigNames.put(Key, HSContigNames);
}
//Retain Fraction
if (CurrentCSD.isRetainFractionEnabled()){
//New Data Objects
//initialize output
LinkedHashMap<String, LinkedList<GenomicElementAndQueryMatch>> ContextSetList_N =
new LinkedHashMap<String, LinkedList<GenomicElementAndQueryMatch>>();
//contig names
LinkedHashMap<String, HashSet<String>> ContigNames_N =
new LinkedHashMap<String, HashSet<String>>();
for (String s : ContextSetList.keySet()){
//old
LinkedList<GenomicElementAndQueryMatch> CS = ContextSetList.get(s);
//new
LinkedList<GenomicElementAndQueryMatch> CS_N = new LinkedList<GenomicElementAndQueryMatch>();
HashSet<String> HSContigNames = new HashSet<String>();
for (GenomicElementAndQueryMatch GandE : CS){
//cluster ID
String Annotation = GandE.getE().getAnnotation().trim().toUpperCase();
//determine fraction
Double Frac = (double) AnnCounts.get(Annotation) / (double) GGCounter;
if (Frac >= CurrentCSD.getRetainFraction()){
CS_N.add(GandE);
HSContigNames.add(GandE.getE().getContig());
}
}
//add new to set
if (CS_N.size() > 0){
ContextSetList_N.put(s,CS_N);
ContigNames_N.put(s, HSContigNames);
}
}
//update data - new contigs + genes
ContextSetList = ContextSetList_N;
ContigNames = ContigNames_N;
}
//Cassette cases: add genes
if (isCassette){
for (LinkedList<GenomicElementAndQueryMatch> MatchList : Matches){
for (GenomicElementAndQueryMatch GandE : MatchList){
GenesForCassettes.add(GandE.getE().getAnnotation());
}
}
}
SpeciesCounter++;
progress = (int) (50*((double)SpeciesCounter/(double)fr.getOS().getSpecies().size()));
//update progress
setProgress(progress);
//check for cancellations
if (0 == progress%2){
if (Thread.currentThread().isInterrupted()){
setProgress(0);
break;
}
}
}
//only proceed if the thread has not been cancelled.
if (!Thread.currentThread().isInterrupted()){
//filter matches based on same homologs requirement
if (CurrentCSD.RequireSameSizeHomologs){
ContextSetDataFromJpanBtn CSDFJB= FilterbySameSizeHomologs(ContextSetList,"cluster");
ContextSetList = CSDFJB.ContextSetList;
SourceNames = CSDFJB.SourceNames;
ContigNames = CSDFJB.ContigNames;
Counter = CSDFJB.Counter;
}
//re-computation
if (CurrentCSD.getType().equals("GenesAround")){
//attempt to standardize
if (CurrentCSD.isRelativeBeforeAfter()){
//first, retrieve an alternative list
LinkedHashMap<String, LinkedList<GenomicElementAndQueryMatch>> AlternativeContextSetList =
new LinkedHashMap<String, LinkedList<GenomicElementAndQueryMatch>>();
//adjust values for alternative list
int GenesBefore = CurrentCSD.getGenesBefore();
int GenesAfter = CurrentCSD.getGenesAfter();
CurrentCSD.setGenesBefore(GenesAfter);
CurrentCSD.setGenesAfter(GenesBefore);
//retrieve alternative set of hits
for (Entry<String, AnnotatedGenome> entry : fr.getOS().getSpecies().entrySet()) {
//Retrieve matches
HashSet<LinkedList<GenomicElementAndQueryMatch>> Matches =
entry.getValue().MatchesOnTheFly(Queries, null, CurrentCSD);
//create an iterator for the HashSet
Iterator<LinkedList<GenomicElementAndQueryMatch>> it = Matches.iterator();
int AlternativeOperonCounter = 0; //reset operon counter
while(it.hasNext()){
//context unit object
LinkedList<GenomicElementAndQueryMatch> ContextSegment = it.next();
//increment counters
AlternativeOperonCounter++;
//define key
String Key = entry.getKey() + "-" + Integer.toString(AlternativeOperonCounter);
//put elements into hashmap
AlternativeContextSetList.put(Key, ContextSegment);
}
}
LinkedHashMap<String, Strand> QueryHash = new LinkedHashMap<String, Strand>();
//determine 'proper' orientation, based on number
int StrandForward = 0;
int StrandReverse = 0;
for (String s : ContextSetList.keySet()){
LinkedList<GenomicElementAndQueryMatch> LL = ContextSetList.get(s);
for (GenomicElementAndQueryMatch GandE : LL){
if (GandE.isQueryMatch()){
if (GandE.getE().getStrand().equals(Strand.POSITIVE)){
StrandForward++;
QueryHash.put(s, Strand.POSITIVE);
} else {
StrandReverse++;
QueryHash.put(s, Strand.NEGATIVE);
}
}
}
}
//initialize a final list
LinkedHashMap<String, LinkedList<GenomicElementAndQueryMatch>> FinalContextSetList =
new LinkedHashMap<String, LinkedList<GenomicElementAndQueryMatch>>();
//write entries to the final list, if appropriate
for (String s : ContextSetList.keySet()){
LinkedList<GenomicElementAndQueryMatch> FwdLL = ContextSetList.get(s);
LinkedList<GenomicElementAndQueryMatch> RevLL = AlternativeContextSetList.get(s);
//don't flip Fwd
if (StrandForward >= StrandReverse){
if (QueryHash.get(s).equals(Strand.POSITIVE)){
FinalContextSetList.put(s, FwdLL);
} else {
FinalContextSetList.put(s, RevLL);
}
//don't flip reverse
} else {
if (QueryHash.get(s).equals(Strand.POSITIVE)){
FinalContextSetList.put(s, RevLL);
} else {
FinalContextSetList.put(s, FwdLL);
}
}
}
//update EC + return CSD to original
ContextSetList = FinalContextSetList;
CurrentCSD.setGenesBefore(GenesBefore);
CurrentCSD.setGenesAfter(GenesAfter);
}
}
//adjust values, if necessary, if context set type is a cassette
if (isCassette){
int CassetteCounter = 0;
//create a new context list
LinkedHashMap<String, LinkedList<GenomicElementAndQueryMatch>> CassetteContextSetList =
new LinkedHashMap<String, LinkedList<GenomicElementAndQueryMatch>>();
//species names
LinkedHashMap<String, String> CassetteSourceNames =
new LinkedHashMap<String, String>();
//contig names
LinkedHashMap<String, HashSet<String>> CassetteContigNames =
new LinkedHashMap<String, HashSet<String>>();
//parameters for each
String SpeciesKey;
LinkedList<GenomicElementAndQueryMatch> SpeciesGenes;
for (AnnotatedGenome AG : fr.getOS().getSpecies().values()){
//Species Name
SpeciesKey = AG.getSpecies() + "-1";
SpeciesGenes = new LinkedList<GenomicElementAndQueryMatch>();
//Contigs
HashSet<String> Contigs = new HashSet<String>();
for (GenomicElement E : AG.getElements()){
if (GenesForCassettes.contains(E.getAnnotation())){
//create appropriate GenomicElementAndQueryMatch
GenomicElementAndQueryMatch GandE = new GenomicElementAndQueryMatch();
GandE.setQueryMatch(true);
GandE.setE(E);
Contigs.add(E.getContig());
//add to list
SpeciesGenes.add(GandE);
}
}
//add, if not empty
if (!SpeciesGenes.isEmpty()){
//update information
CassetteContextSetList.put(SpeciesKey,SpeciesGenes);
CassetteSourceNames.put(SpeciesKey, AG.getSpecies());
CassetteContigNames.put(SpeciesKey, Contigs);
CassetteCounter++;
}
}
//When complete, add completed structures
EC.setContexts(CassetteContextSetList);
EC.setNumberOfEntries(CassetteCounter);
//add source info
EC.setSourceSpeciesNames(CassetteSourceNames);
EC.setSourceContigNames(CassetteContigNames);
} else {
//add hash map to extended CRON
EC.setContexts(ContextSetList);
EC.setNumberOfEntries(Counter);
//add source info
EC.setSourceSpeciesNames(SourceNames);
EC.setSourceContigNames(ContigNames);
}
// //debugging
// System.out.println("Jpanbtn");
// for (String s : EC.getContexts().keySet()){
// HashSet<String> HSContigNames = EC.getSourceContigNames().get(s);
// Iterator<String> it = HSContigNames.iterator();
// while (it.hasNext()){
// System.out.println(s + "-" + it.next());
// }
// }
//Update the query data with all changes.
CSDisplayData CSD = new CSDisplayData();
CSD.setECandInitializeTreeLeaves(EC);
WorkerQD.setCSD(CSD);
}
return null;
}
//by cluster
protected Void SearchOrganismsbyCluster(){
//re-set progress value
int progress = 0;
//cassette versus non-cassette context sets
boolean isCassette = false;
//recover the context set description
ContextSetDescription CurrentCSD = null;
for (ContextSetDescription csd : fr.getOS().getCSDs()){
if (csd.getName().contentEquals(this.ContextSetName)){
CurrentCSD = csd;
break;
}
}
//set context set name
String ContextSetName = this.ContextSetName;
//Cassette Option - Switch to the cassette type
if (CurrentCSD.isCassette()){
isCassette = true;
ContextSetName = CurrentCSD.getCassetteOf();
//note critical information
boolean isNearbyOnly = CurrentCSD.isNearbyOnly();
int NearbyOnlyVal = CurrentCSD.getNearbyLimit();
//recover the context set description of the cassette
for (ContextSetDescription csd : fr.getOS().getCSDs()){
if (csd.getName().contentEquals(ContextSetName)){
CurrentCSD = csd;
break;
}
}
CurrentCSD.setNearbyOnly(isNearbyOnly);
CurrentCSD.setNearbyLimit(NearbyOnlyVal);
}
//initialize output
ExtendedCRON EC = new ExtendedCRON();
//set name and type of CRON.
EC.setName(this.Name);
EC.setContextSetName(this.ContextSetName);
EC.setSearchType("cluster");
EC.setClusterNumbers(this.ClusterNumber);
//initialize output
LinkedHashMap<String, LinkedList<GenomicElementAndQueryMatch>> ContextSetList =
new LinkedHashMap<String, LinkedList<GenomicElementAndQueryMatch>>();
//species names
LinkedHashMap<String, String> SourceNames =
new LinkedHashMap<String, String>();
//contig names
LinkedHashMap<String, HashSet<String>> ContigNames =
new LinkedHashMap<String, HashSet<String>>();
//initialize a counter variable
int Counter = 0;
int SpeciesCounter = 0;
//Initialize a hash map to use for the case of cassette contexts.
HashSet<Integer> GenesForCassettes = new HashSet<Integer>();
//Initialize a hash map for the use of Retain-Fraction-type analysis.
//Cluster Counts
LinkedHashMap<Integer, Integer> ClusterCounts
= new LinkedHashMap<Integer, Integer>();
//increment number of genomic groupings
int GGCounter = 0;
//iterate through species.
for (Entry<String, AnnotatedGenome> entry : fr.getOS().getSpecies().entrySet()) {
HashSet<LinkedList<GenomicElementAndQueryMatch>> Matches = null;
if (CurrentCSD.isPreprocessed()){
//pre-processed cases
Matches = entry.getValue().ClusterMatches(this.ClusterNumber, ContextSetName);
} else {
//on-the-fly
if (CurrentCSD.getType().contentEquals("GenesBetween") && ClusterNumber.length != 2) {
JOptionPane.showMessageDialog(null, "This gene grouping requires exactly two search queries.",
"Inappropriate Number of Queries",JOptionPane.ERROR_MESSAGE);
} else {
//debugging
// System.out.println("Breakpoint!");
//proceed
Matches = entry.getValue().MatchesOnTheFly(null, this.ClusterNumber, CurrentCSD);
}
}
//option: condense into single list + update matches
if (CurrentCSD.isSingleOrganismAmalgamation()){
Matches = Amalgamate(CurrentCSD.isSingleOrganismAmalgamation(),
CurrentCSD.isSingleOrganismAmalgamationKeepEmpty(),
Matches);
}
//take note of AND statements
if (!this.WorkerQD.ANDStatementsParsed){
this.WorkerQD.BuildANDStatements("cluster");
}
Matches = ANDStatementFilter("cluster",Matches);
//consider the iff and only iff clause
if (WorkerQD.ifAndOnlyif){
Matches = IfAndOnlyIfFilter(Matches);
}
//filter matches in operon expansion case
if (CurrentCSD.isOperonExpansion && Matches.size() > 0){
Matches = RemoveOverlappingSubsets(Matches);
}
//create an iterator for the HashSet
Iterator<LinkedList<GenomicElementAndQueryMatch>> it = Matches.iterator();
//iterate through HashSet, with string-based keys
int OperonCounter = 0; //reset operon counter
while(it.hasNext()){
//increment counter
GGCounter++;
//context unit object
LinkedList<GenomicElementAndQueryMatch> ContextSegment = it.next();
//Counts for retain fraction
if (CurrentCSD.isRetainFractionEnabled()){
//multiple copies of a single cluster num don't score better
HashSet<Integer> ClusterNums = new HashSet<Integer>();
for (GenomicElementAndQueryMatch GandE : ContextSegment){
ClusterNums.add(GandE.getE().getClusterID());
}
Iterator<Integer> CS_it = ClusterNums.iterator();
while (CS_it.hasNext()){
int ClusterNum = CS_it.next();
//add to hash map
if (ClusterCounts.get(ClusterNum) == null){
ClusterCounts.put(ClusterNum, 1);
} else {
int Count = ClusterCounts.get(ClusterNum);
Count++;
ClusterCounts.put(ClusterNum,Count);
}
}
}
//increment counters
OperonCounter++;
Counter++;
//define key
String Key = entry.getKey() + "-" + Integer.toString(OperonCounter);
//put elements into hashmap
ContextSetList.put(Key, ContextSegment);
//record other info
SourceNames.put(Key, entry.getValue().getSpecies());
HashSet<String> HSContigNames = new HashSet<String>();
for (GenomicElementAndQueryMatch GandE : ContextSegment){
HSContigNames.add(GandE.getE().getContig());
}
ContigNames.put(Key, HSContigNames);
}
//POST - FILTERING PART
//Retain Fraction
if (CurrentCSD.isRetainFractionEnabled()){
//New Data Objects
//initialize output
LinkedHashMap<String, LinkedList<GenomicElementAndQueryMatch>> ContextSetList_N =
new LinkedHashMap<String, LinkedList<GenomicElementAndQueryMatch>>();
//contig names
LinkedHashMap<String, HashSet<String>> ContigNames_N =
new LinkedHashMap<String, HashSet<String>>();
for (String s : ContextSetList.keySet()){
//old
LinkedList<GenomicElementAndQueryMatch> CS = ContextSetList.get(s);
//new
LinkedList<GenomicElementAndQueryMatch> CS_N = new LinkedList<GenomicElementAndQueryMatch>();
HashSet<String> HSContigNames = new HashSet<String>();
for (GenomicElementAndQueryMatch GandE : CS){
//cluster ID
int ClusterID = GandE.getE().getClusterID();
//determine fraction
Double Frac = (double) ClusterCounts.get(ClusterID) / (double) GGCounter;
if (Frac >= CurrentCSD.getRetainFraction() && ClusterID != 0){
CS_N.add(GandE);
HSContigNames.add(GandE.getE().getContig());
}
}
//add new to set
if (CS_N.size() > 0){
ContextSetList_N.put(s,CS_N);
ContigNames_N.put(s, HSContigNames);
}
}
//update data - new contigs + genes
ContextSetList = ContextSetList_N;
ContigNames = ContigNames_N;
}
//Cassette cases: add genes
if (isCassette){
for (LinkedList<GenomicElementAndQueryMatch> MatchList : Matches){
for (GenomicElementAndQueryMatch GandE : MatchList){
GenesForCassettes.add(GandE.getE().getClusterID());
}
}
}
//remove clusterID = 0 case
GenesForCassettes.remove(0);
SpeciesCounter++;
progress = (int) (50*((double)SpeciesCounter/(double)fr.getOS().getSpecies().size()));
//update progress
setProgress(progress);
//check for cancellations
if (0 == progress%2){
if (Thread.currentThread().isInterrupted()){
setProgress(0);
break;
}
}
}
//only proceed if the search has not already been cancelled.
if (!Thread.currentThread().isInterrupted()){
//filter matches based on same homologs requirement
if (CurrentCSD.RequireSameSizeHomologs){
ContextSetDataFromJpanBtn CSDFJB= FilterbySameSizeHomologs(ContextSetList,"cluster");
ContextSetList = CSDFJB.ContextSetList;
SourceNames = CSDFJB.SourceNames;
ContigNames = CSDFJB.ContigNames;
Counter = CSDFJB.Counter;
}
//re-computation
if (CurrentCSD.getType().equals("GenesAround")){
//attempt to standardize
if (CurrentCSD.isRelativeBeforeAfter()){
//first, retrieve an alternative list
LinkedHashMap<String, LinkedList<GenomicElementAndQueryMatch>> AlternativeContextSetList =
new LinkedHashMap<String, LinkedList<GenomicElementAndQueryMatch>>();
//adjust values for alternative list
int GenesBefore = CurrentCSD.getGenesBefore();
int GenesAfter = CurrentCSD.getGenesAfter();
CurrentCSD.setGenesBefore(GenesAfter);
CurrentCSD.setGenesAfter(GenesBefore);
//retrieve alternative set of hits
for (Entry<String, AnnotatedGenome> entry : fr.getOS().getSpecies().entrySet()) {
//Retrieve matches
HashSet<LinkedList<GenomicElementAndQueryMatch>> Matches =
entry.getValue().MatchesOnTheFly(null, this.ClusterNumber, CurrentCSD);
//create an iterator for the HashSet
Iterator<LinkedList<GenomicElementAndQueryMatch>> it = Matches.iterator();
int AlternativeOperonCounter = 0; //reset operon counter
while(it.hasNext()){
//context unit object
LinkedList<GenomicElementAndQueryMatch> ContextSegment = it.next();
//increment counters
AlternativeOperonCounter++;
//define key
String Key = entry.getKey() + "-" + Integer.toString(AlternativeOperonCounter);
//put elements into hashmap
AlternativeContextSetList.put(Key, ContextSegment);
}
}
LinkedHashMap<String, Strand> QueryHash = new LinkedHashMap<String, Strand>();
//determine 'proper' orientation, based on number
int StrandForward = 0;
int StrandReverse = 0;
for (String s : ContextSetList.keySet()){
LinkedList<GenomicElementAndQueryMatch> LL = ContextSetList.get(s);
for (GenomicElementAndQueryMatch GandE : LL){
if (GandE.isQueryMatch()){
if (GandE.getE().getStrand().equals(Strand.POSITIVE)){
StrandForward++;
QueryHash.put(s, Strand.POSITIVE);
} else {
StrandReverse++;
QueryHash.put(s, Strand.NEGATIVE);
}
}
}
}
//initialize a final list
LinkedHashMap<String, LinkedList<GenomicElementAndQueryMatch>> FinalContextSetList =
new LinkedHashMap<String, LinkedList<GenomicElementAndQueryMatch>>();
//write entries to the final list, if appropriate
for (String s : ContextSetList.keySet()){
LinkedList<GenomicElementAndQueryMatch> FwdLL = ContextSetList.get(s);
LinkedList<GenomicElementAndQueryMatch> RevLL = AlternativeContextSetList.get(s);
//don't flip Fwd
if (StrandForward >= StrandReverse){
if (QueryHash.get(s).equals(Strand.POSITIVE)){
FinalContextSetList.put(s, FwdLL);
} else {
FinalContextSetList.put(s, RevLL);
}
//don't flip reverse
} else {
if (QueryHash.get(s).equals(Strand.POSITIVE)){
FinalContextSetList.put(s, RevLL);
} else {
FinalContextSetList.put(s, FwdLL);
}
}
}
//update EC + return CSD to original
ContextSetList = FinalContextSetList;
CurrentCSD.setGenesBefore(GenesBefore);
CurrentCSD.setGenesAfter(GenesAfter);
}
}
//adjust values, if necessary, if context set type is a cassette
if (isCassette){
int CassetteCounter = 0;
//create a new context list
LinkedHashMap<String, LinkedList<GenomicElementAndQueryMatch>> CassetteContextSetList =
new LinkedHashMap<String, LinkedList<GenomicElementAndQueryMatch>>();
//species names
LinkedHashMap<String, String> CassetteSourceNames =
new LinkedHashMap<String, String>();
//contig names
LinkedHashMap<String, HashSet<String>> CassetteContigNames =
new LinkedHashMap<String, HashSet<String>>();
//parameters for each
String SpeciesKey;
LinkedList<GenomicElementAndQueryMatch> SpeciesGenes;
//nearby only: merge all into a single set
if (!CurrentCSD.isNearbyOnly()){
for (AnnotatedGenome AG : fr.getOS().getSpecies().values()){
//Species Name
SpeciesKey = AG.getSpecies() + "-1";
SpeciesGenes = new LinkedList<GenomicElementAndQueryMatch>();
//Contigs
HashSet<String> Contigs = new HashSet<String>();
for (GenomicElement E : AG.getElements()){
//candidate new values, to add
if (GenesForCassettes.contains(E.getClusterID())){
//create appropriate GenomicElementAndQueryMatch
GenomicElementAndQueryMatch GandE = new GenomicElementAndQueryMatch();
GandE.setQueryMatch(true);
GandE.setE(E);
Contigs.add(E.getContig());
//add to list
SpeciesGenes.add(GandE);
}
}
//add, if not empty
if (!SpeciesGenes.isEmpty()){
//update information
CassetteContextSetList.put(SpeciesKey,SpeciesGenes);
CassetteSourceNames.put(SpeciesKey, AG.getSpecies());
CassetteContigNames.put(SpeciesKey, Contigs);
CassetteCounter++;
}
}
} else {
//iterate through all old sets, and adjust
for (String s : ContextSetList.keySet()){
//implement counter
CassetteCounter++;
//Retrieve Original
LinkedList<GenomicElementAndQueryMatch> LL = ContextSetList.get(s);
//new list to merge
LinkedList<GenomicElementAndQueryMatch> Additions = new LinkedList<GenomicElementAndQueryMatch>();
//Retrieve appropriate organisms
String OrgName[] = s.split("-");
String WholeName = "";
for (int i = 0; i < OrgName.length-1; i++){
WholeName = WholeName + OrgName[i] + "-";
}
WholeName = (String) WholeName.subSequence(0, WholeName.length()-1);
AnnotatedGenome AG = fr.getOS().getSpecies().get(WholeName);
//debugging
//System.out.println(WholeName);
//System.out.println(AG.getSpecies());
//iterate through elements, find elements to add.
for (GenomicElement E : AG.getElements()){
//gene has appropriate ID
if (GenesForCassettes.contains(E.getClusterID())){
boolean AddThisGene = false;
for (GenomicElementAndQueryMatch GandE : LL){
GenomicElement E2 = GandE.getE();
// //debugging
// if (E.getStart() == 382735 && E.getStop() == 383745){
// System.out.println(CurrentCSD.getNearbyLimit());
// System.out.println(Math.abs(E2.getStart() - E.getStop()));
// System.out.println(Math.abs(E.getStart() - E2.getStop()));
// }
//Add a gene, or not
if (E.getContig().equals(E2.getContig())){
if (Math.abs(E2.getStart() - E.getStop()) <= CurrentCSD.getNearbyLimit() ||
Math.abs(E.getStart() - E2.getStop()) <= CurrentCSD.getNearbyLimit()){
AddThisGene = true;
break;
}
}
}
//add the new gene
if (AddThisGene){
GenomicElementAndQueryMatch GandE_n = new GenomicElementAndQueryMatch();
GandE_n.setE(E);
GandE_n.setQueryMatch(false);
Additions.add(GandE_n);
}
}
}
//debugging
//System.out.println(s + ": " + Additions.size());
//Add the list, and sort it.
LL.addAll(Additions);
Collections.sort(LL, new AnnotatedGenome.SortGandEByElements());
//write this list into the new hash map
CassetteContextSetList.put(s,LL);
}
//update variables that didn't change
CassetteSourceNames = SourceNames;
CassetteContigNames = ContigNames;
}
//When complete, add completed structures
EC.setContexts(CassetteContextSetList);
EC.setNumberOfEntries(CassetteCounter);
//add source info
EC.setSourceSpeciesNames(CassetteSourceNames);
EC.setSourceContigNames(CassetteContigNames);
} else {
//add hash map to extended CRON
EC.setContexts(ContextSetList);
EC.setNumberOfEntries(Counter);
//add source info
EC.setSourceSpeciesNames(SourceNames);
EC.setSourceContigNames(ContigNames);
}
//Update the query data with all changes.
CSDisplayData CSD = new CSDisplayData();
CSD.setECandInitializeTreeLeaves(EC);
WorkerQD.setCSD(CSD);
}
return null;
}
//generalized search - to do?
protected Void SearchOrganisms(){
return null;
}
//filters / modifiers
//amalgamate
protected HashSet<LinkedList<GenomicElementAndQueryMatch>> Amalgamate(boolean Amalgamate, boolean KeepEmpty, HashSet<LinkedList<GenomicElementAndQueryMatch>> Matches){
//option: condense into single list + update matches
if (Amalgamate){
//Initialize holding cell
LinkedList<GenomicElementAndQueryMatch> CondensedList = new LinkedList<GenomicElementAndQueryMatch>();
//create an iterator
Iterator<LinkedList<GenomicElementAndQueryMatch>> itp = Matches.iterator();
//create hash map to store these values
LinkedHashMap<GenomicElement, Boolean> ElementHash
= new LinkedHashMap<GenomicElement, Boolean>();
//march through entries, write to hash
while (itp.hasNext()){
//if an element is every a query match, it scores as a query match here.
LinkedList<GenomicElementAndQueryMatch> LL = itp.next();
for (GenomicElementAndQueryMatch GandE : LL){
GenomicElement E = GandE.getE();
if (ElementHash.get(E) != null){
if (ElementHash.get(E) == false){
ElementHash.put(E, GandE.isQueryMatch());
}
} else{
ElementHash.put(E,GandE.isQueryMatch());
}
}
//CondensedList.addAll(LL);
}
//building holding cell from hash map
for (GenomicElement E : ElementHash.keySet()){
GenomicElementAndQueryMatch GandE = new GenomicElementAndQueryMatch();
GandE.setE(E);
GandE.setQueryMatch(ElementHash.get(E));
CondensedList.add(GandE);
}
//sort list
Collections.sort(CondensedList, new GandEListSorter());
//Initialize new output + write condensed
HashSet<LinkedList<GenomicElementAndQueryMatch>> UpdatedMatches =
new HashSet<LinkedList<GenomicElementAndQueryMatch>>();
//add to set, treating empty sets appropriately
if (CondensedList.size() != 0 || (CondensedList.size() == 0 && KeepEmpty)){
UpdatedMatches.add(CondensedList);
}
//reset
return UpdatedMatches;
} else {
//just return original value
return Matches;
}
}
//account for AND statements
protected HashSet<LinkedList<GenomicElementAndQueryMatch>> ANDStatementFilter(String Type, HashSet<LinkedList<GenomicElementAndQueryMatch>> Matches){
if ((Type.equals("cluster") && this.WorkerQD.ANDClustersHash.size() != 0) ||
(Type.equals("annotation") && this.WorkerQD.ANDAnnotationsHash.size() != 0)){
//create a filtered list, abiding by all supplied OR statements
HashSet<LinkedList<GenomicElementAndQueryMatch>> FilteredList = new
HashSet<LinkedList<GenomicElementAndQueryMatch>>();
//create an iterator
Iterator<LinkedList<GenomicElementAndQueryMatch>> itp = Matches.iterator();
while (itp.hasNext()){
//next in list
LinkedList<GenomicElementAndQueryMatch> LL = itp.next();
//initializations
// LinkedList<Integer> ClusterNums = new LinkedList<Integer>();
// LinkedList<String> AnnQueries = new LinkedList<String>();
// LinkedList<Object> Queries = new LinkedList<Object>();
//add counts
LinkedHashMap<Integer,Integer> ClustersHash = new LinkedHashMap<Integer,Integer>();
LinkedHashMap<String,Integer> AnnotationsHash = new LinkedHashMap<String,Integer>();
//values from the list, as appropriate by type.
for (GenomicElementAndQueryMatch GandE : LL){
if (Type.equals("cluster")){
//check hash + initialize count
int Key = GandE.getE().getClusterID();
int Count = 1;
//determine appropriate count + increment counter
if (ClustersHash.get(Key) != null){
Count = ClustersHash.get(Key);
Count++;
}
ClustersHash.put(Key,Count);
// ClusterNums.add(GandE.getE().getClusterID());
// Queries.add((Object) GandE.getE().getClusterID());
} else {
String Key = GandE.getE().getAnnotation().trim().toUpperCase();
int Count = 1;
//determine appropriate count + increment counter
if (AnnotationsHash.get(Key) != null){
Count = AnnotationsHash.get(Key);
Count++;
}
AnnotationsHash.put(Key,Count);
// AnnQueries.add(GandE.getE().getAnnotation().trim().toUpperCase());
// Queries.add((Object) GandE.getE().getAnnotation().trim().toUpperCase());
}
}
//default: retain this set
boolean RetainMatch = true;
//check all of the and statement requirements
// for (LinkedList L : ParsedANDStatements){
// HashSet<Object> IntersectionHash = new HashSet<Object>(L);
// IntersectionHash.removeAll(Queries);
//
// //if not all were removed, do not retain this set
// if (IntersectionHash.size() != 0){
// RetainMatch = false;
// break;
// }
// }
if (Type.equals("cluster")){
for (Integer x : this.WorkerQD.ANDClustersHash.keySet()){
if (ClustersHash.get(x) != null){
int MatchCount = ClustersHash.get(x);
//did not reach minimal number of AND statements
if (MatchCount < WorkerQD.ANDClustersHash.get(x)){
RetainMatch = false;
break;
}
//null: violation of an AND statement
} else{
RetainMatch = false;
break;
}
}
} else {
for (String x : this.WorkerQD.ANDAnnotationsHash.keySet()){
if (AnnotationsHash.get(x) != null){
int MatchCount = AnnotationsHash.get(x);
//did not reach minimal number of AND statements
if (MatchCount < WorkerQD.ANDAnnotationsHash.get(x)){
RetainMatch = false;
break;
}
//null: violation of an AND statement
} else{
RetainMatch = false;
break;
}
}
}
//only if this should be retained, continue
if (RetainMatch){
FilteredList.add(LL);
}
}
//return Matches;
return FilteredList;
} else {
return Matches;
}
}
//filter by if and only if
protected HashSet<LinkedList<GenomicElementAndQueryMatch>> IfAndOnlyIfFilter(HashSet<LinkedList<GenomicElementAndQueryMatch>> Matches){
if (WorkerQD.ifAndOnlyif){
//create a filtered list, abiding by all supplied OR statements
HashSet<LinkedList<GenomicElementAndQueryMatch>> FilteredList = new
HashSet<LinkedList<GenomicElementAndQueryMatch>>();
//create an iterator
Iterator<LinkedList<GenomicElementAndQueryMatch>> itp = Matches.iterator();
while (itp.hasNext()){
//next in list
LinkedList<GenomicElementAndQueryMatch> LL = itp.next();
//default: retain this set
boolean RetainMatch = true;
//check the lists for elements that are not included in the provided set.
if (!WorkerQD.isAnnotationSearch()){
for (GenomicElementAndQueryMatch GandE : LL){
if (!WorkerQD.ClustersAsList.contains(GandE.getE().getClusterID())){
RetainMatch = false;
break;
}
}
} else {
for (GenomicElementAndQueryMatch GandE : LL){
if (!WorkerQD.QueriesAsList.contains(GandE.getE().getAnnotation().trim().toUpperCase())){
RetainMatch = false;
break;
}
}
}
//also require size matching - for multiple copy issues
if (!WorkerQD.isAnnotationSearch()){
if (LL.size() != WorkerQD.ClustersAsList.size()){
RetainMatch = false;
}
} else {
if (LL.size() != WorkerQD.QueriesAsList.size()){
RetainMatch = false;
}
}
//retain set, if appropriate.
if (RetainMatch){
FilteredList.add(LL);
}
}
return FilteredList;
} else {
return Matches;
}
}
//filter for operon expansion option (remove subsets)
protected HashSet<LinkedList<GenomicElementAndQueryMatch>> RemoveOverlappingSubsets(HashSet<LinkedList<GenomicElementAndQueryMatch>> Matches){
//create an iterator
Iterator<LinkedList<GenomicElementAndQueryMatch>> itp = Matches.iterator();
//re-cast sets as list
LinkedList<LinkedList<GenomicElementAndQueryMatch>> ListList
= new LinkedList<LinkedList<GenomicElementAndQueryMatch>>();
while (itp.hasNext()){
ListList.add(itp.next());
}
//sort the list by increasing size
Collections.sort(ListList, new ListListSorter());
//first create the filtered set as a list of lists
LinkedList<LinkedList<GenomicElementAndQueryMatch>> FilteredListofLists
= new LinkedList<LinkedList<GenomicElementAndQueryMatch>>();
//build the filtered set, adding whenever possible
for (LinkedList<GenomicElementAndQueryMatch> L : ListList){
boolean AddToFilteredSet = true;
//create list of elements
LinkedList<GenomicElement> LE = new LinkedList<GenomicElement>();
for (GenomicElementAndQueryMatch GandE : L){
LE.add(GandE.getE());
}
for (LinkedList<GenomicElementAndQueryMatch> LF : FilteredListofLists){
//create list of elements
LinkedList<GenomicElement> LFE = new LinkedList<GenomicElement>();
for (GenomicElementAndQueryMatch GandE : LF){
LFE.add(GandE.getE());
}
//create mod lists
LinkedList<GenomicElement> LE_Mod = new LinkedList<GenomicElement>(LE);
LinkedList<GenomicElement> LFE_Mod = new LinkedList<GenomicElement>(LFE);
LE_Mod.retainAll(LFE_Mod);
//no need to add
if (LE_Mod.equals(LE)){
AddToFilteredSet = false;
break;
}
}
//pass through filter - add
if (AddToFilteredSet){
FilteredListofLists.add(L);
}
}
//filtered set 2 return
HashSet<LinkedList<GenomicElementAndQueryMatch>> FilteredSet
= new HashSet<LinkedList<GenomicElementAndQueryMatch>>(FilteredListofLists);
//return filtered
return FilteredSet;
}
//filter by strict limits on homolog size
protected ContextSetDataFromJpanBtn FilterbySameSizeHomologs(LinkedHashMap<String, LinkedList<GenomicElementAndQueryMatch>> Matches, String Type){
//Initialize output
ContextSetDataFromJpanBtn CSDFJB = new ContextSetDataFromJpanBtn();
//hash
LinkedHashMap<String, LinkedList<GenomicElementAndQueryMatch>> FilteredMatches
= new LinkedHashMap<String, LinkedList<GenomicElementAndQueryMatch>>();
//sources
LinkedHashMap<String, String> SourceNames
= new LinkedHashMap<String, String>();
//contigs
LinkedHashMap<String, HashSet<String>> ContigNames
= new LinkedHashMap<String, HashSet<String>>();
//hash map storing homolog appearance counts
LinkedHashMap<Object, LinkedHashMap<Integer,Integer>> HomologHash
= new LinkedHashMap<Object, LinkedHashMap<Integer,Integer>>();
for (String s : Matches.keySet()){
//retrieve data
LinkedList<GenomicElementAndQueryMatch> LL = Matches.get(s);
//iterate through
for (GenomicElementAndQueryMatch GandE : LL){
//retrieve data
GenomicElement E = GandE.getE();
int Size = E.getStop()-E.getStart()+1;
Object Key;
if (Type.equals("cluster")){
Key = (Object) E.getClusterID();
} else{
Key = (Object) E.getAnnotation().toUpperCase();
}
//check for existance in hash
if (HomologHash.get(Key) != null){
//retrieve existing hash map
LinkedHashMap<Integer,Integer> SizeHash = HomologHash.get(Key);
//check this map
if (SizeHash.get(Size) != null){
int CurVal = SizeHash.get(Size);
CurVal++;
SizeHash.put(Size, CurVal);
} else{
SizeHash.put(Size, 1);
}
//update homolog hash.
HomologHash.put(Key, SizeHash);
} else{
//first appearance
LinkedHashMap<Integer, Integer> SizeHash
= new LinkedHashMap<Integer, Integer>();
SizeHash.put(Size, 1);
//update homolog hash
HomologHash.put(Key, SizeHash);
}
}
}
//build final counts hash
LinkedHashMap<Object, Integer> ValueCounts = new LinkedHashMap<Object, Integer>();
for (Object o : HomologHash.keySet()){
//retrieve data
LinkedHashMap<Integer,Integer> H = HomologHash.get(o);
//determine max for each object
int Max = -1;
int MaxSize = -1;
for (Integer x : H.keySet()){
if (H.get(x) > Max){
Max = H.get(x);
MaxSize = x;
//in the case of a tie, take the longer element
} else if (H.get(x) == Max) {
if (x > MaxSize){
Max = H.get(x);
MaxSize = x;
}
}
}
//write to mapping
ValueCounts.put(o,MaxSize);
}
//filter the set
for (String s : Matches.keySet()){
//retrieve data
boolean RetainThisSet = true;
LinkedList<GenomicElementAndQueryMatch> LL = Matches.get(s);
HashSet<String> HSContigNames = new HashSet<String>();
for (GenomicElementAndQueryMatch GandE : LL){
//retrieve data
GenomicElement E = GandE.getE();
int Size = E.getStop()-E.getStart()+1;
//create key
Object Key;
if (Type.equals("cluster")){
Key = (Object) E.getClusterID();
} else{
Key = (Object) E.getAnnotation().toUpperCase();
}
//check value
int AllottedSizeValue = ValueCounts.get(Key);
if (AllottedSizeValue != Size){
RetainThisSet = false;
break;
} else{
HSContigNames.add(E.getContig());
}
}
//update filtered set w/ all essential info
if (RetainThisSet){
FilteredMatches.put(s,LL);
ContigNames.put(s,HSContigNames);
String OrgName[] = s.split("-");
String WholeName = "";
for (int i = 0; i < OrgName.length-1; i++){
WholeName = WholeName + OrgName[i] + "-";
}
WholeName = (String) WholeName.subSequence(0, WholeName.length()-1);
SourceNames.put(s,WholeName);
}
}
//add data to output structure
CSDFJB.ContextSetList = FilteredMatches;
CSDFJB.ContigNames = ContigNames;
CSDFJB.SourceNames = SourceNames;
CSDFJB.Counter = FilteredMatches.keySet().size();
//return
return CSDFJB;
}
//Optional Operations
//(1) Create a tree panel of search results
//============================================//
protected Void CreateSearchPanel(){
//update search results frame
SearchResultsFrame = new FrmSearchResults(fr,WorkerQD.getCSD());
WorkerQD.setCSD(SearchResultsFrame.getCSD());
WorkerQD.setSRF(SearchResultsFrame);
return null;
}
//(2) Compute Dendrogram, render tree
//============================================//
protected Void ComputeDendrogram(){
//debugging
// if (this.WorkerQD.getCSD().getEC().getNumberOfEntries() == 2){
// System.out.println("Breakpoint!");
// }
//Create DE
try {
//retrieve EC, + modify
ExtendedCRON EC = this.WorkerQD.getCSD().getEC();
EC.setCustomDissimilarities(fr.getOS().getCustomDissimilarities());
EC.computePairwiseDistances(DissimilarityMethod);
EC.exportDistancesToField();
//create a DE out of the deal
this.ProcessedDE = new DadesExternes(EC);
de = this.ProcessedDE;
//replace EC
this.WorkerQD.getCSD().setEC(EC);
this.WorkerQD.setDe(de);
} catch (Exception e1) {
e1.printStackTrace();
}
//get distances, compute dendrogram
multiDendro = ProcessedDE.getMatriuDistancies();
minBase = Double.MAX_VALUE;
nbElements = multiDendro.getCardinalitat();
Reagrupa rg;
MatriuDistancies mdNew;
double b;
int progress;
while (multiDendro.getCardinalitat() > 1) {
//check for cancellations
if (Thread.currentThread().isInterrupted()){
break;
}
try {
//CLUSTERING FROM DISTANCES DATA
rg = new Reagrupa(multiDendro, typeData, method, precision);
mdNew = rg.Recalcula();
//SET THE CURRENT MULTIDENDROGRAM TO THE RESULT FROM RG.RECALCULA()
multiDendro = mdNew;
this.WorkerQD.setMultiDendro(mdNew);
b = multiDendro.getArrel().getBase();
if ((b < minBase) && (b != 0)) {
minBase = b;
}
//if (DisplayOutput){
progress = 50 + 50
* (nbElements - multiDendro.getCardinalitat())
/ (nbElements - 1);
setProgress(progress);
//}
} catch (final Exception e) {
//showError(e.getMessage());
if (!fr.isSearchWorkerCancelled()){
showError("problems in calculating dendrogram.");
} else {
//re-set cursor, progress bar
fr.setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
setProgress(0);
progressBar.setString("");
progressBar.setBorderPainted(false);
}
}
}
//check for cancellations
if (!Thread.currentThread().isInterrupted()){
//set field
this.RootCluster = multiDendro.getArrel();
}
//debugging
//System.out.println("Root cluster determined to be " + this.RootCluster);
return null;
}
//(3) Compute Context Graph
//============================================//
protected Void ComputeContextGraph(){
return null;
}
//(4) Render Phylogeny
//============================================//
protected Void RenderPhylogeny(){
return null;
}
//following search + dendrogram computation
public void done(){
//System.out.println("done fr.isSearchWorkerCancelled(): " + fr.isSearchWorkerCancelled());
//re-set cursor, progress bar
fr.setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
setProgress(0);
progressBar.setString("");
progressBar.setBorderPainted(false);
//only do these things if the searchworker is not recognized as cancelled.
if (RenderOutput){
//if (!Thread.currentThread().isInterrupted()){
//proceed if exception thrown
if (!ExceptionThrown){
//process completed!
ProcessCompleted = true;
fr.setTmpCluster(RootCluster);
if (DisplayOutput){
//try to update values
try {
//update values for display
if (AnalysesList.isOptionComputeDendrogram()){
multiDendro.getArrel().setBase(minBase);
}
showCalls(action, this.WorkerQD); //pass on the QD + display options
} catch (Exception ex) {
}
}
}
} else {
//System.out.println("Search process cancelled (done)");
//default: search worker is not cancelled.
fr.setSearchWorkerCancelled(false);
}
//no search worker is running, any more
//fr.setSearchWorkerRunning(false);
}
}
public Jpan_btn_NEW(final FrmPrincipalDesk fr) {
super();
this.fr = fr;
this.jb = this;
this.getPanel();
this.searchFieldSize = searchField.getPreferredSize();
this.setVisible(true);
//DATA SOURCE - initialize
fitx = new FitxerDades();
fitx.setNom("");
fitx.setPath("");
}
private void getPanel() {
//initialize panel
this.setLayout(new GridBagLayout());
this.setBorder(BorderFactory.createTitledBorder("Gene Context Search")); // File
final GridBagConstraints c = new GridBagConstraints();
int gridy = 0;
//initial GridBagLayout parameters
c.anchor = GridBagConstraints.FIRST_LINE_START;
c.weightx = 1;
c.insets = new Insets(1,1,1,1);
//Total grid width: 4
//Total grid height: 9
//Search genomes section heading
c.gridx = 0;
c.gridy = gridy;
c.gridheight = 1;
c.fill = GridBagConstraints.HORIZONTAL;
c.gridwidth = 4;
SearchGenomes = new JLabel(" SEARCH GENOMES");
SearchGenomes.setBackground(Color.GRAY);
SearchGenomes.setOpaque(true);
SearchGenomes.setFont(fontStandard);
add(SearchGenomes,c);
gridy++;
//search type button group definition
strAnnsearch = "Annotation Search";
strClusearch = "Cluster Number";
annotationSearch = new JRadioButton(strAnnsearch);
clusterSearch = new JRadioButton(strClusearch);
annotationSearch.setFont(fontStandard);
clusterSearch.setFont(fontStandard);
searchType = new ButtonGroup();
searchType.add(annotationSearch);
searchType.add(clusterSearch);
//set default state
searchType.setSelected(annotationSearch.getModel(), true);
// if (fr.getOS().isGeneClustersLoaded() == true){
// searchType.setSelected(clusterSearch.getModel(), true);
// } else {
// searchType.setSelected(annotationSearch.getModel(), true);
// }
// display on panel
c.gridx = 0;
c.gridy = gridy;
c.gridwidth = 2;
c.gridheight = 1;
c.fill = GridBagConstraints.HORIZONTAL;
add(annotationSearch, c);
c.gridx = 2;
c.gridwidth = 2;
c.gridy = gridy;
add(clusterSearch, c);
gridy++;
// Searchable text
c.ipady = 5;
c.gridx = 0;
c.gridy = gridy;
c.gridwidth = 4;
c.gridheight = 1;
c.fill = GridBagConstraints.HORIZONTAL;
c.insets = new Insets(1, 1, 1, 1);
searchField = new JTextField();
searchField.setText(""); // Enter search bar
searchField.addActionListener(this);
searchField.setEditable(true);
searchField.setColumns(20); // this value may wind up changing, depending on the system.
add(searchField, c);
gridy++;
//Submit search
c.ipady = 0;
c.gridx = 0;
c.gridy = gridy;
c.gridwidth = 2;
c.gridheight = 1;
c.fill = GridBagConstraints.HORIZONTAL;
c.insets = new Insets(1, 1, 1, 1);
strSubmit = "Submit Search";
btnSubmit = new JButton(strSubmit);
btnSubmit.addActionListener(this);
btnSubmit.setFont(fontStandard);
add(btnSubmit, c);
//cancel button
c.ipady = 0;
c.gridx = 2;
c.gridy = gridy;
c.gridwidth = 2;
c.gridheight = 1;
c.fill = GridBagConstraints.HORIZONTAL;
c.insets = new Insets(1, 1, 1, 1);
btnCancel = new JButton(strCancel);
btnCancel.addActionListener(this);
btnCancel.setFont(fontStandard);
add(btnCancel, c);
gridy++;
// progress bar
c.gridx = 0;
c.gridy = gridy;
c.gridwidth = 4;
c.gridheight = 1;
c.fill = GridBagConstraints.HORIZONTAL;
c.insets = new Insets(1, 1, 1, 1);
progressBar = new JProgressBar(0, 100);
progressBar.setBorderPainted(false);
progressBar.setStringPainted(false);
progressBar.setFont(fontStandard);
progressBar.setForeground(Color.BLUE);
progressBar.setValue(0);
add(progressBar, c);
gridy++;
//Genome section heading
c.gridx = 0;
c.gridy = gridy;
c.gridheight = 1;
c.fill = GridBagConstraints.HORIZONTAL;
c.gridwidth = 4;
ContextSetSelect = new JLabel(" SELECT CONTEXT SET");
ContextSetSelect.setBackground(Color.GRAY);
ContextSetSelect.setOpaque(true);
ContextSetSelect.setFont(fontStandard);
add(ContextSetSelect,c);
gridy++;
// Context Set Text label
c.ipady = 5;
c.gridx = 0;
c.gridy = gridy;
c.gridwidth = 1;
c.gridheight = 1;
c.fill = GridBagConstraints.HORIZONTAL;
//c.fill = GridBagConstraints.NONE;
c.insets = new Insets(1, 1, 1, 1);
contextSetHeader = new JTextField();
contextSetHeader.setText("Context Set:"); // context set currently loaded
contextSetHeader.addActionListener(this);
contextSetHeader.setEditable(false);
contextSetHeader.setFont(fontStandard);
add(contextSetHeader, c);
// drop-down menu for Context Sets
c.ipady = 0;
c.gridx = 1;
c.gridy = gridy;
c.gridwidth = 3;
c.gridheight = 1;
c.fill = GridBagConstraints.HORIZONTAL;
c.insets = new Insets(1, 1, 1, 1);
strUpdate = Language.getLabel(110); // Update
String[] ContextArray;
//String[]
if (fr.getOS() == null){
ContextArray = new String[1];
ContextArray[0] = "<none>";
} else {
ContextArray = convertContextSets(fr.getOS().getCSDs());
}
contextSetMenu = new JComboBox<String>(ContextArray);
contextSetMenu.addActionListener(this);
contextSetMenu.setEnabled(true);
contextSetMenu.setFont(fontStandard);
add(contextSetMenu, c);
gridy++;
//manage context sets button
c.gridx = 0;
c.gridy = gridy;
c.gridwidth = 1;
c.gridheight = 1;
c.fill = GridBagConstraints.NONE;
c.insets = new Insets(1, 1, 1, 1);
btnManage = new JButton(strManageCS);
btnManage.addActionListener(this);
btnManage.setEnabled(true);
btnManage.setFont(fontStandard);
add(btnManage, c);
gridy++;
// // btn update
// c.gridx = 2;
// c.gridy = gridy;
// c.gridwidth = 1;
// c.gridheight = 1;
// c.fill = GridBagConstraints.HORIZONTAL;
// c.insets = new Insets(1, 1, 1, 1);
// //strUpdate = Language.getLabel(110); // Update
// strUpdate = "Update Settings";
// btnUpdate = new JButton(strUpdate);
// btnUpdate.addActionListener(this);
// btnUpdate.setEnabled(true);
// btnUpdate.setFont(fontStandard);
// add(btnUpdate, c);
// gridy++;
// //New elements, version 2.0
// // Load sequence Motif label
// c.gridx = 0;
// c.gridy = gridy;
// c.gridheight = 1;
// c.fill = GridBagConstraints.HORIZONTAL;
// c.gridwidth = 4;
// AddRegMotif = new JLabel(" LOAD REGULATORY MOTIF(S)");
// AddRegMotif.setBackground(Color.GRAY);
// AddRegMotif.setOpaque(true);
// AddRegMotif.setFont(fontStandard);
// add(AddRegMotif,c);
// gridy++;
// empty space
c.gridx = 0;
c.gridy = gridy;
c.gridwidth = 4;
c.gridheight = 1;
c.fill = GridBagConstraints.HORIZONTAL;
c.insets = new Insets(1, 1, 1, 1);
JLabel spacer = new JLabel(" ");
spacer.setFont(fontStandard);
add(spacer, c);
gridy++;
// btn update
c.ipady = 10;
gridy++;
c.gridx = 0;
c.gridy = gridy;
c.gridwidth = 4;
c.gridheight = 1;
c.fill = GridBagConstraints.HORIZONTAL;
c.insets = new Insets(1, 1, 1, 1);
//strUpdate = Language.getLabel(110); // Update
//strUpdate = "Update Display Settings";
btnUpdate = new JButton(strUpdate);
btnUpdate.addActionListener(this);
btnUpdate.setEnabled(false);
//btnUpdate.setFont(fontStandard);
btnUpdate.setFont(bigFont);
add(btnUpdate, c);
gridy++;
// progressBar.setStringPainted(true);
// progressBar.setValue(100);
// progressBar.setBackground(Color.BLUE);
}
public static void enableUpdate() {
if (precisionCorrect && axisMinCorrect && axisMaxCorrect
&& axisSeparationCorrect && axisEveryCorrect
&& axisDecimalsCorrect) {
btnUpdate.setEnabled(true);
} else {
btnUpdate.setEnabled(false);
}
}
public static String getFileNameNoExt() {
String name = "";
if (fitx != null) {
name = fitx.getNomNoExt();
}
return name;
}
public static void setFileName(String name) {
txtFileName.setText(name);
}
public MatriuDistancies getMatriu() {
return de.getMatriuDistancies();
}
// BUTTONS PUSHED -> LOAD FILE OR UPDATE TREE
@Override
public void actionPerformed(final ActionEvent evt) {
//cancel button - always active
if (evt.getSource().equals(btnCancel)){
//cancellations!
CancelBtn();
//other features - only active when an active set has been loaded.
} else {
//conditionals
if (fr.getOS() != null){
String action = null;
FitxerDades fitxTmp;
boolean ambDades = false;
InternalFrameData ifd;
double minBase;
MDComputation mdComputation;
String query;
/*
* Available actions:
* (1) Load [Create a new Context Tree]
* (2) Reload [Update Context Tree - new matrix]
* (3) Redraw [Update Context Tree - old matrix]
* (4) cluster search [take place of Reload]
*/
//initialize a new 'querydata' object whenever an action is taken -
//represents current search parameter space
QueryData QD = new QueryData();
QD.setOSName(fr.getOS().getName()); //Important later for context viewing.
if (!evt.getSource().equals(contextSetMenu)){
if (searchType.getSelection().equals(annotationSearch.getModel())){
QD.setAnnotationSearch(true);
} else {
QD.setAnnotationSearch(false);
}
QD.setContextSetName(contextSetMenu.getSelectedItem().toString());
QD.setDissimilarityType(fr.getPanMenu().getCbDissimilarity().getSelectedItem().toString());
QD.setAnalysesList(new PostSearchAnalyses(
fr.getPanMenuTab().getJpo().getDrawSearchResults().isSelected(), //search results
fr.getPanMenuTab().getJpo().getDrawContextTree().isSelected(), //draw context tree
fr.getPanMenuTab().getJpo().getDrawContextGraph().isSelected(), //draw context graph
fr.getPanMenuTab().getJpo().getDrawPhylogeneticTree().isSelected() //phylogeny
));
}
//turn on search results, if nothing else turned on.
if (evt.getSource().equals(searchField) ||
evt.getSource().equals(btnSubmit) ||
evt.getSource().equals(btnUpdate)){
//check: if none selected, show search results only.
if (!fr.getPanMenuTab().getJpo().getDrawSearchResults().isSelected() &&
!fr.getPanMenuTab().getJpo().getDrawContextTree().isSelected() &&
!fr.getPanMenuTab().getJpo().getDrawContextGraph().isSelected() &&
!fr.getPanMenuTab().getJpo().getDrawPhylogeneticTree().isSelected()){
System.out.println("No analyses were specified. Switching 'Print Search Results' on.");
QD.getAnalysesList().setOptionDisplaySearches(true);
fr.getPanMenuTab().getJpo().getDrawSearchResults().setSelected(true);
}
}
//Search Query
if (evt.getSource().equals(searchField) || evt.getSource().equals(btnSubmit)){
//reset bad search flag
boolean BadSearch = false;
//all semicolon case
String txt = searchField.getText().trim();
for (int i = 0; i < txt.length(); i++){
if (txt.charAt(i) == ';'){
BadSearch = true;
} else {
BadSearch = false;
break;
}
}
//retrieve semicolons
String[] L = searchField.getText().trim().split(";");
for (String s : L){
if (s.trim().equals("")){
BadSearch = true;
break;
}
}
//Proceed with Query, if appropriate.
if (!BadSearch) {
//System.out.println("Search field invoked with query:" + searchField.getText());
if (searchType.getSelection().equals(annotationSearch.getModel())){
currentQuery = "Search Query: " + searchField.getText().trim();
} else {
currentQuery ="Search Query: Cluster(s) " + searchField.getText().trim();
}
action = "Load";
buttonClicked = true;
ambDades = true;
} else {
//showError("Please enter a query in the search bar.");
JOptionPane.showMessageDialog(null, "One or more queries are empty string searches.\nPlease remove all empty string searches.",
"Empty Search",JOptionPane.ERROR_MESSAGE);
}
} else if (evt.getSource().equals(btnUpdate)) {
//set wait cursor
fr.setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
// UPDATE
buttonClicked = true;
ifd = currentInternalFrame.getInternalFrameData();
if ((Jpan_Menu.getTypeData() == ifd.getTypeData())
&& (Jpan_Menu.getMethod() == ifd.getMethod())
&& (Jpan_Menu.getPrecision() == ifd.getPrecision())
&& (QD.getDissimilarityType().equals(ifd.getQD().getDissimilarityType()))
&& (QD.getContextSetName().equals(ifd.getQD().getContextSetName()))
/* TODO:
* Currently set so that any tab change will cause for re-computation. This should be changed, later,
* to account for re-computations of different kinds, for different analyses. (1-14-2013)
*/
&& (QD.getAnalysesList().isOptionDisplaySearches() == ifd.getQD().getAnalysesList().isOptionDisplaySearches())
&& (QD.getAnalysesList().isOptionComputeDendrogram() == ifd.getQD().getAnalysesList().isOptionComputeDendrogram())
&& (QD.getAnalysesList().isOptionComputeContextGraph() == ifd.getQD().getAnalysesList().isOptionComputeContextGraph())
&& (QD.getAnalysesList().isOptionRenderPhylogeny() == ifd.getQD().getAnalysesList().isOptionRenderPhylogeny())){
//&& (QD.getAnalysesList().equals(ifd.getQD().getAnalysesList()))){
action = "Redraw"; // no new matrix required
//System.out.println("Action = Redraw");
} else {
action = "Reload"; //a new matrix is required
//System.out.println("Action = Reloaded");
// System.out.println("Method:" + (Jpan_Menu.getMethod() == ifd.getMethod()));
// System.out.println("Precision: " + (Jpan_Menu.getPrecision() == ifd.getPrecision()));
// System.out.println("Dissimilarity Type: " + (QD.getDissimilarityType().equals(ifd.getQD().getDissimilarityType())));
// System.out.println("Context Set Name: " + (QD.getContextSetName().equals(ifd.getQD().getContextSetName())));
//the problem!
//System.out.println("Analyses List: " + (QD.getAnalysesList().equals(ifd.getQD().getAnalysesList())));
//
// System.out.println("QD List:" + QD.getAnalysesList().isOptionDisplaySearches()
// + " " + QD.getAnalysesList().isOptionComputeDendrogram()
// + " " + QD.getAnalysesList().isOptionComputeContextGraph()
// + " " + QD.getAnalysesList().isOptionRenderPhylogeny());
//
// System.out.println("ifd:" + ifd.getQD().getAnalysesList().isOptionDisplaySearches()
// + " " + ifd.getQD().getAnalysesList().isOptionComputeDendrogram()
// + " " + ifd.getQD().getAnalysesList().isOptionComputeContextGraph()
// + " " + ifd.getQD().getAnalysesList().isOptionRenderPhylogeny());
}
ambDades = true;
} else if (evt.getSource().equals(btnManage)){
action = "manage contexts";
buttonClicked = true;
//new manageContextSets(this.fr, fr.getOS().getCSDs(), this);
new manageContextSetsv2(this.fr, this);
}
//CARRY OUT ACTION
if (ambDades && (action.equals("Load"))) {
//retrieve text from window.
String startText = searchField.getText();
//name of the search.
String TheName = startText + " [" + contextSetMenu.getSelectedItem() + "]";
QD.setName(TheName);
boolean ifAndOnlyif = false;
//the very first step: check for and remove special "if and only if" character
if (startText.startsWith("&&only")){
ifAndOnlyif = true;
startText = startText.substring(6).trim();
}
try {
//parse into candidates
//and statements
String[] Queries = startText.trim().split(";");
//store updated list into linked list
LinkedList<String> AllParsedStatements = new LinkedList<String>();
//or statements, within and statements
for (String sq : Queries){
//one or more and statements within an or statement
if (sq.contains("$$")){
//note whole statement
QD.ANDStatements.add(sq.trim());
//record appropriately
String[] sqORQueries = sq.trim().split("\\$\\$");
for (int i = 0; i < sqORQueries.length; i++){
AllParsedStatements.add(sqORQueries[i].trim());
}
} else {
AllParsedStatements.add(sq.trim());
}
}
//rebuild the list appropriately
String[] UpdatedQueries = new String[AllParsedStatements.size()];
for (int i = 0; i < AllParsedStatements.size(); i++){
UpdatedQueries[i] = AllParsedStatements.get(i);
//System.out.println(UpdatedQueries[i]);
}
//restore values ... and continue as before
Queries = UpdatedQueries;
minBase = Double.MAX_VALUE;
if (searchType.getSelection().equals(annotationSearch.getModel())){
//before carrying out search, ask user about their search.
String Hypo = "hypothetical protein";
String Unk = "Unknown function";
if ((Hypo.contains(startText) || Unk.contains(startText) ||
startText.length() <= 3) && QD.getAnalysesList().isOptionComputeDendrogram()
&& fr.getPanDisplayOptions().getDrawContextTree().isSelected()){
String SureYouWantToSearch = "You have entered a search query that may return a large number of results." + "\n"
+ "Proceeding may cause this program to crash." + "\n"
+ "Are you sure you would like to proceed?" + "\n";
//ask question, and maybe proceed with search
int SearchCheck = JOptionPane.showConfirmDialog(null,SureYouWantToSearch,
"Proceed with search", JOptionPane.YES_NO_CANCEL_OPTION);
if (SearchCheck == JOptionPane.YES_OPTION){
this.ProceedWithSearch = true;
} else {
this.ProceedWithSearch = false;
de = null; //this will effectively fast-forward to the catch statement
}
} else {
this.ProceedWithSearch = true;
}
if (this.ProceedWithSearch == true){
QD.setQueriesAndList(Queries);
QD.ifAndOnlyif = ifAndOnlyif;
//single, interruptable Swing Worker
CurrentSearch = new SearchWorker(QD,action,
Jpan_Menu.getTypeData(), Jpan_Menu.getMethod(),
Jpan_Menu.getPrecision(), true);
CurrentSearch.addPropertyChangeListener(this);
//default: the search worker is not cancelled.
fr.setSearchWorkerCancelled(false);
CurrentSearch.execute();
}
} else {
LinkedList<Integer> NumQueriesList = new LinkedList<Integer>();
for (int i = 0; i < Queries.length; i++){
try {
if (Queries[i].contains("-")){
String Rng[] = Queries[i].split("-");
int Start = Integer.parseInt(Rng[0].trim());
int Stop = Integer.parseInt(Rng[1].trim());
for (int j = Start; j <= Stop; j++){
NumQueriesList.add(j);
}
}
NumQueriesList.add(Integer.parseInt(Queries[i].trim()));
} catch (Exception ex){}
}
int[] NumQueries = new int[NumQueriesList.size()];
for (int i = 0; i < NumQueriesList.size(); i++){
NumQueries[i] = NumQueriesList.get(i);
}
//store
QD.setClustersAndList(NumQueries);
QD.ifAndOnlyif = ifAndOnlyif;
//try: unified swingworker approach
CurrentSearch = new SearchWorker(QD,action,
Jpan_Menu.getTypeData(), Jpan_Menu.getMethod(),
Jpan_Menu.getPrecision(), true);//phylogeny
CurrentSearch.addPropertyChangeListener(this);
//default: the search worker is not cancelled.
fr.setSearchWorkerCancelled(false);
CurrentSearch.execute();
}
} catch (Exception e1) {
e1.printStackTrace();
fr.setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
buttonClicked = false;
//showError(e1.getMessage());
if (searchType.getSelection().equals(annotationSearch.getModel())){
if (this.ProceedWithSearch == true){
showError("There were no matches to the query (or queries).");
}
} else {
//String LastCluster = Integer.toString(OS.LargestCluster);
String errMsg = "There were no matches to the query (or queries).";
showError(errMsg);
}
e1.printStackTrace();
}
} else if (ambDades && action.equals("Reload")) {
//retrieve information from selected frame
QueryData SelectedFrame = currentInternalFrame.getInternalFrameData().getQD();
//update internal frame data
SelectedFrame.setDissimilarityType(QD.getDissimilarityType());
SelectedFrame.setContextSetName(QD.getContextSetName());
SelectedFrame.setAnalysesList(QD.getAnalysesList());
if (SelectedFrame.isAnnotationSearch()){
CurrentSearch = new SearchWorker(SelectedFrame,action,
Jpan_Menu.getTypeData(), Jpan_Menu.getMethod(),
Jpan_Menu.getPrecision(), true);//phylogeny
CurrentSearch.addPropertyChangeListener(this);
//default: the search worker is not cancelled.
fr.setSearchWorkerCancelled(false);
CurrentSearch.execute();
} else {
CurrentSearch = new SearchWorker(SelectedFrame,action,
Jpan_Menu.getTypeData(), Jpan_Menu.getMethod(),
Jpan_Menu.getPrecision(), true);//phylogeny
CurrentSearch.addPropertyChangeListener(this);
//default: the search worker is not cancelled.
fr.setSearchWorkerCancelled(false);
CurrentSearch.execute();
}
// in this case, no need to modify what's already in the internal frame.
} else if (ambDades && action.equals("Redraw")) {
//only GUI updates - no recomputations
showCalls(action, currentInternalFrame.getInternalFrameData().getQD());//phylogeny
fr.setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
} else {
buttonClicked = false;
}
}
}
}
//cancel button
public void CancelBtn(){
//Kill search worker
if (CurrentSearch != null){
CurrentSearch.cancel(true);
CurrentSearch = null;
de = null;
}
//kill popular set retrieval worker
if (fr.getCurrentLPW() != null){
fr.getCurrentLPW().SelectedItem.setSelected(false);
fr.getCurrentLPW().cancel(true);
fr.setCurrentLPW(null);
}
//close stream
if (fr.getPopularSetImportStream() != null){
try {
fr.getPopularSetImportStream().close();
} catch (IOException e) {
e.printStackTrace();
}
}
//kill export sequences worker
if (fr.getCurrentESW() != null) {
fr.getCurrentESW().cancel(true);
fr.setCurrentESW(null);
}
//kill display sequences worker
if (fr.getCurrentRGW() != null){
fr.getCurrentRGW().cancel(true);
fr.setCurrentRGW(null);
}
//After cancellation, need to modify some things in the main thread.
//Try to cut out ASAP - but there may be a better way.
//Output-associated resets
fr.setRenderGenomesWorkerCancelled(true); //Rendered Genome Worker
fr.setSearchWorkerCancelled(true); //Search Worker
fr.setImportPopularSetWorkerCancelled(true); //Import Popular set worker
//GUI-related resets
//progress bar back to defaults
fr.getPanBtn().getProgressBar().setValue(0);
fr.getPanBtn().getProgressBar().setIndeterminate(false);
//switch cursor back to normal
Component glassPane = fr.getRootPane().getGlassPane();
glassPane.setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
glassPane.setVisible(false);
//message to console
System.out.println("The process has been cancelled.");
}
public void showCalls(String action, QueryData qD) {
try {
fr.setCfgPhylo(null); //for re-drawing.
if (action.equals("Reload") || action.equals("Redraw")) {
currentInternalFrame.doDefaultCloseAction();
}
/*
* GHETTO FIX: artificial opening/closing
*/
//CHANGE: commented out these two lines needed for mass-selection.
//CHANGEBACK: this seems to help.
show(action, Jpan_Menu.getMethod(), Jpan_Menu.getPrecision(), qD);
currentInternalFrame.doDefaultCloseAction();
/*
* GHETTO FIX: artificial opening/closing
*/
//actual showing (somehow, settings have been appropriately updated)
show(action, Jpan_Menu.getMethod(), Jpan_Menu.getPrecision(), qD);
btnUpdate.setEnabled(true);
buttonClicked = false;
} catch (Exception ex) {
//showError("ShowCalls");
ex.printStackTrace();
}
}
public void show(String action, final metodo method, final int precision, QueryData qD) {
boolean isUpdate;
FrmInternalFrame pizarra;
Config cfg; //Configuration information for multidendrogram only
Config cfgp = null; //Configuration information for phylogenetic tree
InternalFrameData ifd;
Fig_Pizarra figPizarra;
Fig_Pizarra figPhylo;
//INTERNAL PANELS
FrmSearchResults fSearch = null;
FrmPiz fPiz = null;
FrmGraph fGraph = null;
FrmPhylo fPhylo = null;
JScrollPane fPizSP = null;
JScrollPane fSearchSP = null;
JScrollPane fGraphSP = null;
JScrollPane fPhyloSP = null;
//update or not
isUpdate = !action.equals("Load");
try {
//CREATE INTERNAL FRAME + ADD DATA
pizarra = fr.createInternalFrame(isUpdate, method.name());
pizarra.setTitle(qD.getName());
//PREPARE INTERNAL FRAME DATA
CSDisplayData CSD = qD.getCSD();
//UPDATE CONFIGURATION INFORMATION
cfg = fr.getConfig();
cfg.setPizarra(pizarra);
//OPTION: SEARCHES
if (qD.getAnalysesList().isOptionDisplaySearches()){
//create scroll panel from search results pane
fSearch = SearchResultsFrame;
fSearchSP = new JScrollPane(SearchResultsFrame);
//update CSD with tree nodes
CSD = fSearch.getCSD();
}
//OPTION: DENDROGRAM
if (qD.getAnalysesList().isOptionComputeDendrogram()){
//update configuration menu panel
cfg.setFitxerDades(fitx);
cfg.setMatriu(multiDendro);
cfg.setHtNoms(de.getTaulaNoms()); //table names
if (!cfg.isTipusDistancia()) {
if (cfg.getOrientacioDendo().equals(Orientation.NORTH)) {
cfg.setOrientacioDendo(Orientation.SOUTH);
} else if (cfg.getOrientacioDendo().equals(Orientation.SOUTH)) {
cfg.setOrientacioDendo(Orientation.NORTH);
} else if (cfg.getOrientacioDendo().equals(Orientation.EAST)) {
cfg.setOrientacioDendo(Orientation.WEST);
} else if (cfg.getOrientacioDendo().equals(Orientation.WEST)) {
cfg.setOrientacioDendo(Orientation.EAST);
}
}
//create a new context tree panel
fPiz = new FrmPiz(fr, CSD);
// Set sizes
fPiz.setSize(pizarra.getSize());
fPiz.setPreferredSize(pizarra.getSize());
//determine size of tree rendering based on number of elements
setVerticalScrollValue(de.getTaulaNoms().size());
Dimension d = new Dimension(pizarra.getWidth()-
HorizontalScrollBuffer, VerticalScrollValue);
fPiz.setPreferredSize(d);
// Call Jpan_Menu -> internalFrameActivated()
//pizarra.setVisible(true);
if (action.equals("Load") || action.equals("Reload")) {
Jpan_Menu.ajustaValors(cfg);
}
//
//System.out.println("Breakpoint!");
//These did not work. keep this in mind for later!
// cfg.getConfigMenu().setIncrement(0.1);
// cfg.getConfigMenu().setAxisDecimals(2);
// Convert tree into figures
figPizarra = new Fig_Pizarra(multiDendro.getArrel(), cfg);
// Pass figures to the window
fPiz.setFigures(figPizarra.getFigures());
fPiz.setConfig(cfg);
//scroll panel, with sizes
fPizSP = new JScrollPane(fPiz);
fPizSP.setSize(pizarra.getSize());
fPizSP.setPreferredSize(pizarra.getSize());
fPizSP.getVerticalScrollBar().setUnitIncrement(ScrollInc);
//update CSD with context tree rectangles
CSD = fPiz.getCSD();
//update cfg information
fr.setCfg(cfg);
}
//OPTION: GRAPH
if (qD.getAnalysesList().isOptionComputeContextGraph()){
fGraph = new FrmGraph(fr, CSD);
fGraphSP = new JScrollPane(fGraph);
//update CSD with context graph rectangles
CSD = fGraph.getCSD();
}
//OPTION: PHYLOGENY
if (qD.getAnalysesList().isOptionRenderPhylogeny()){
//tree must be loaded
if (fr.getPanPhyTreeMenu().getCurrentParsedTree() != null){
//initialize panel
fPhylo = new FrmPhylo(fr, CSD);
//update configuration information to be appropriate for the phylogenetic tree
if (fr.getCfgPhylo() != null){
cfgp = fr.getCfgPhylo();
} else {
cfgp = new Config(cfg.getConfigMenu());
}
// System.out.println("cfgp.getValorMaxim(): " + cfgp.getValorMaxim());
// System.out.println("cfgp.getConfigMenu().isEscalaVisible(): " + cfgp.getConfigMenu().isEscalaVisible());
// System.out.println("cfgp.getConfigMenu().isEtiquetaEscalaVisible(): " + cfgp.getConfigMenu().isEtiquetaEscalaVisible());
// System.out.println("cfgp.getConfigMenu().isFranjaVisible(): " + cfgp.getConfigMenu().isFranjaVisible());
// System.out.println("cfgp.getConfigMenu().isNomsVisibles(): "+ cfgp.getConfigMenu().isNomsVisibles());
//
//determine size of tree rendering based on number of elements
Dimension d = new Dimension(pizarra.getWidth()-
HorizontalScrollBuffer,CalculateVerticalScrollValue(PhyloTreeLeaves));
fPhylo.setPreferredSize(d);
//cfgp.getConfigMenu().setValMin(0.0);
//adjust values, if necessary.
// if (!qD.getAnalysesList().isOptionComputeDendrogram()) {
// Jpan_Menu.ajustaValors(cfgp);
// }
// Convert tree into figures
figPhylo = new Fig_Pizarra(fr.getPanPhyTreeMenu().getCurrentParsedTree(), cfgp);
//debugging
// LinkedList[] FigList = figPhylo.getFigures();
// LinkedList<Marge> Marges = FigList[2];
// for (Marge m : Marges){
// System.out.println("m, Jpan_btn_NEW: " + m.getPhyloWeight());
// }
//Update configuration information
CfgPanelMenu PhyloCfgPanel = cfgp.getConfigMenu();
PhyloCfgPanel.setTipusDades(tipusDades.DISTANCIA);
cfgp.setConfigMenu(PhyloCfgPanel);
cfgp.setHtNoms(figPhylo.getHtNoms());
//TEST - try changing this - it works
if (!isUpdate){
PhyloCfgPanel.setValMax(figPhylo.getLongestBranch());
}
PhyloCfgPanel.setValMin(0);
cfgp.setConfigMenu(PhyloCfgPanel);
//add fields
this.setPhyloTreeLength(figPhylo.getLongestBranch());
this.setPhyloTreeLeaves(figPhylo.getHtNoms().size());
//create a dummy 'MatriuDistancies' for this phylo tree.
MatriuDistancies md = new MatriuDistancies(0);
Cluster c = new Cluster();
c.setFills(PhyloTreeLeaves);
md.setArrel(c);
cfgp.setMatriu(md);
//adjust menu, if no context tree
if (!qD.getAnalysesList().isOptionComputeDendrogram()) {
Jpan_Menu.adjustValuesPhylo(cfgp);
}
//add figures + configuration information to frame
fPhylo.setFigures(figPhylo.getFigures());
fPhylo.setConfig(cfgp);
//scroll panel
fPhyloSP = new JScrollPane(fPhylo);
fPhyloSP.setSize(pizarra.getSize());
fPhyloSP.setPreferredSize(pizarra.getSize());
fPhyloSP.getVerticalScrollBar().setUnitIncrement(ScrollInc);
//update CSD with phylogenetic tree rectangles
CSD = fPhylo.getCSD();
//update config panel
fr.setCfgPhylo(cfgp);
} else {
qD.getAnalysesList().setOptionRenderPhylogeny(false);
}
}
//INTERNAL FRAME DATA
qD.setCSD(CSD);
//ifd = new InternalFrameData(de, multiDendro);
ifd = new InternalFrameData(qD.getDe(), qD.getMultiDendro());
ifd.setQD(qD);
ifd.setContextGraphPanel(fGraph);
ifd.setContextTreePanel(fPiz);
ifd.setSearchResultsFrame(fSearch);
ifd.setPhyloTreePanel(fPhylo);
ifd.setCfg(cfg);
ifd.setCfgp(cfgp);
pizarra.setInternalFrameData(ifd);
//CREATE FINAL FRAME
JPanel TabbedWrapper = new JPanel();
TabbedWrapper.setLayout(new BorderLayout());
//tabbed frame for internal frame
FrmTabbed AnalysisResults = new FrmTabbed(fPizSP,fGraphSP,fSearchSP,fPhyloSP,
qD.getAnalysesList(), fr);
TabbedWrapper.add(AnalysisResults, BorderLayout.CENTER);
fr.getPanGenome().setCSD(CSD);
//ADD TABBED PANEL TO FRAME
pizarra.add(TabbedWrapper); //Tabbed menu component with panel
//CONTAINER OWNERSHIP
pizarra.setInternalPanel(fPiz);
pizarra.setVisible(true);
//Mod Oct 22
if (action.equals("Load") || action.equals("Reload")) {
Jpan_Menu.ajustaValors(cfg);
}
//both Jpan_btn_NEW and fr
this.currentInternalFrame = pizarra;
fr.setCurrentFrame(pizarra);
// //debugging
// System.out.println("Breakpoint!");
} catch (final Exception e) {
e.printStackTrace();
}
}
private FitxerDades getFitxerDades() {
return this.getFitxerDades(System.getProperty("user.dir"));
}
//DATA FILE
private FitxerDades getFitxerDades(final String sPath) {
//use pre-existing 'FileDialog' GUI window to retrieve file
final FileDialog fd = new FileDialog(fr, Language.getLabel(9),
FileDialog.LOAD);
FitxerDades fitx; //Data file type is just a bunch of relevant strings
fitx = new FitxerDades();
fd.setDirectory(sPath);
fd.setVisible(true);
if (fd.getFile() == null) {
fitx = null;
} else {
fitx.setNom(fd.getFile());
fitx.setPath(fd.getDirectory());
}
return fitx; //A bunch of strings relating to the file information.
}
private void showError(final String msg) {
JOptionPane.showMessageDialog(null, msg, Language.getLabel(7),
JOptionPane.ERROR_MESSAGE);
}
//Interal Frame - related methods
@Override
public void internalFrameActivated(InternalFrameEvent e) {
InternalFrameData ifd;
currentInternalFrame = (FrmInternalFrame) e.getSource();
btnUpdate.setEnabled(true);
//this is necessary owing to confusion in what activates an internal frame.
if (!buttonClicked) {
fr.setCurrentFrame(currentInternalFrame);
ifd = currentInternalFrame.getInternalFrameData();
de = ifd.getDadesExternes();
//fitx = de.getFitxerDades();
multiDendro = ifd.getMultiDendrogram();
SearchResultsFrame = ifd.getSearchResultsFrame();
//this is not likely the point of contention.
//System.out.println("Jpan_btn_New.internalFrameActivated(): " + ifd.getValMax());
Jpan_Menu.setConfigPanel(ifd);
//also set current panel (if it exists)
//fr.setCurrentFpizpanel(currentInternalFrame.getInternalPanel());
}
}
@Override
public void internalFrameClosing(InternalFrameEvent e) {
FrmInternalFrame.decreaseOpenFrameCount();
btnUpdate.setEnabled(false);
// if (!buttonClicked) {
// Jpan_Menu.clearConfigPanel();
// }
}
@Override
public void internalFrameClosed(InternalFrameEvent e) {
}
@Override
public void internalFrameOpened(InternalFrameEvent e) {
//currentInternalFrame = (FrmInternalFrame) e.getSource();
}
@Override
public void internalFrameIconified(InternalFrameEvent e) {
}
@Override
public void internalFrameDeiconified(InternalFrameEvent e) {
// InternalFrameData ifd;
//
// currentInternalFrame = (FrmInternalFrame) e.getSource();
// btnUpdate.setEnabled(true);
// if (!buttonClicked) {
// fr.setCurrentFrame(currentInternalFrame);
// ifd = currentInternalFrame.getInternalFrameData();
// de = ifd.getDadesExternes();
// //fitx = de.getFitxerDades();
// multiDendro = ifd.getMultiDendrogram();
// Jpan_Menu.setConfigPanel(ifd);
// }
}
@Override
public void internalFrameDeactivated(InternalFrameEvent e) {
}
@Override
public void propertyChange(PropertyChangeEvent evt) {
if (evt.getPropertyName() == "progress") {
int progress = (Integer) evt.getNewValue();
progressBar.setValue(progress);
}
}
// generated methods - automatically detect scroll value
public int getVerticalScrollValue() {
return VerticalScrollValue;
}
public void setVerticalScrollValue(int numberOfEntries) {
//VerticalScrollValue = 15*numberOfEntries + 250;
VerticalScrollValue = CalculateVerticalScrollValue(numberOfEntries);
}
public int CalculateVerticalScrollValue(int numberOfEntries){
int CalculatedScrollValue = 15*numberOfEntries + 250;
return CalculatedScrollValue;
}
public boolean isInteger( String input ) {
try {
Integer.parseInt( input );
return true;
}
catch( Exception e ) {
return false;
}
}
public String[] convertContextSets(LinkedList<ContextSetDescription> ListOfContextSets){
//initialize output array
String[] ArrayOfContextSets = new String[ListOfContextSets.size()];
//iterate through array
for (int i = 0; i < ListOfContextSets.size(); i++){
ArrayOfContextSets[i] = ListOfContextSets.get(i).getName();
}
return ArrayOfContextSets;
}
public JComboBox getContextSetMenu() {
return contextSetMenu;
}
public void setContextSetMenu(JComboBox contextSetMenu) {
this.contextSetMenu = contextSetMenu;
}
public double getPhyloTreeLength() {
return PhyloTreeLength;
}
public void setPhyloTreeLength(double phyloTreeLength) {
PhyloTreeLength = phyloTreeLength;
}
public int getPhyloTreeLeaves() {
return PhyloTreeLeaves;
}
public void setPhyloTreeLeaves(int phyloTreeLeaves) {
PhyloTreeLeaves = phyloTreeLeaves;
}
public JProgressBar getProgressBar() {
return progressBar;
}
public void setProgressBar(JProgressBar progressBar) {
this.progressBar = progressBar;
}
public JRadioButton getAnnotationSearch() {
return annotationSearch;
}
public void setAnnotationSearch(JRadioButton annotationSearch) {
this.annotationSearch = annotationSearch;
}
public JRadioButton getClusterSearch() {
return clusterSearch;
}
public void setClusterSearch(JRadioButton clusterSearch) {
this.clusterSearch = clusterSearch;
}
public FrmSearchResults getSearchResultsFrame() {
return SearchResultsFrame;
}
public void setSearchResultsFrame(FrmSearchResults searchResultsFrame) {
SearchResultsFrame = searchResultsFrame;
}
public MatriuDistancies getMultiDendro() {
return multiDendro;
}
public void setMultiDendro(MatriuDistancies multiDendro) {
this.multiDendro = multiDendro;
}
public DadesExternes getDe() {
return de;
}
public void setDe(DadesExternes de) {
this.de = de;
}
public static class ListListSorter implements Comparator<LinkedList<GenomicElementAndQueryMatch>>{
@Override
public int compare(LinkedList<GenomicElementAndQueryMatch> L1, LinkedList<GenomicElementAndQueryMatch> L2) {
return -1* (L1.size() - L2.size());
}
}
public static class GandEListSorter implements Comparator<GenomicElementAndQueryMatch> {
@Override
public int compare(GenomicElementAndQueryMatch o1,
GenomicElementAndQueryMatch o2) {
//extract genomic elements
GenomicElement E1 = o1.getE();
GenomicElement E2 = o2.getE();
//sort as usual
int nameCompare = E1.getContig().compareToIgnoreCase(E2.getContig());
if (nameCompare != 0) {
return nameCompare;
} else {
return Integer.valueOf(E1.getCenter()).compareTo(Integer.valueOf(E2.getCenter()));
}
}
}
}