{
}
-AnnotationColors::AnnotationColors(AnnotationColors &ac)
+AnnotationColors::AnnotationColors(const AnnotationColors &ac)
: root_map(ac.root_map)
{
}
+void AnnotationColors::clear()
+{
+ root_map.cm.clear();
+ root_map.defaultColor = Color(0.0, 0.0, 0.0);
+}
+
void AnnotationColors::setColor(Color &c)
{
root_map.defaultColor = c;
root_map.cm[type].cm.erase(instance);
}
-Color AnnotationColors::lookup(const annot &a)
+Color AnnotationColors::lookup(const annot &a) const
{
return lookup(a.type, a.name);
}
-Color AnnotationColors::lookup(const string &type, const string &instance)
+Color AnnotationColors::lookup(const string &type, const string &instance) const
{
// Yeah, there's probably a nicer looking recursive solution
// to this problem.
- DefaultColorMap::iterator type_map = root_map.cm.find(type);
+ DefaultColorMap::const_iterator type_map = root_map.cm.find(type);
if (type_map != root_map.cm.end() ) {
// found lookup instance
- DefaultColorMap::iterator instance_map = type_map->second.cm.find(instance);
+ DefaultColorMap::const_iterator instance_map = type_map->second.cm.find(instance);
if (instance_map != type_map->second.cm.end() ) {
return instance_map->second.defaultColor;
} else {
{
typedef std::map<std::string, DefaultColorMap> color_map_type;
typedef color_map_type::iterator iterator;
+ typedef color_map_type::const_iterator const_iterator;
DefaultColorMap();
//! initialize color map with a default color
DefaultColorMap(const Color &);
{
public:
AnnotationColors();
- AnnotationColors(AnnotationColors &);
+ AnnotationColors(const AnnotationColors &);
+ // clear all the contents of our mappers
+ void clear();
//! set default color
void setColor(Color &);
//! retreive default color
void erase(const std::string &type, const std::string& instance);
//! lookup an annotation color
- Color lookup(const annot &);
- Color lookup(const std::string &, const std::string &);
+ Color lookup(const annot &) const;
+ Color lookup(const std::string &, const std::string &) const;
private:
// nested maps, with default?
DefaultColorMap root_map;
#include <stdexcept>
using namespace std;
-GlSequence::GlSequence(const Sequence &s)
+GlSequence::GlSequence(const Sequence &s, AnnotationColors& cm)
: seq(s),
seq_x(0.0),
seq_y(0.0),
seq_z(1.0),
seq_height(12.0),
+ color_mapper(cm),
drawColor(0.0, 0.0, 0.0),
char_pix_per_world_unit(5.0)
{
}
-GlSequence::GlSequence(const GlSequence &s)
+GlSequence::GlSequence(const GlSequence &s)
: seq(s.seq),
seq_x(s.seq_x),
seq_y(s.seq_y),
seq_z(s.seq_z),
seq_height(s.seq_height),
+ color_mapper(s.color_mapper),
drawColor(s.drawColor),
char_pix_per_world_unit(s.char_pix_per_world_unit)
{
seq_y = s.seq_y;
seq_z = s.seq_z;
seq_height = s.seq_height;
+ color_mapper = s.color_mapper;
drawColor = s.drawColor;
assert(char_pix_per_world_unit == s.char_pix_per_world_unit);
}
// draw annotations
glLineWidth(seq_height);
GLfloat annotation_z = seq_z + 1.0;
- std::list<annot> annots = seq.annotations();
+ const std::list<annot>& annots = seq.annotations();
+ const std::list<motif>& motifs = seq.motifs();
for (std::list<annot>::const_iterator annot_itor = annots.begin();
annot_itor != annots.end();
++annot_itor, ++annotation_z)
draw_box(seq_x+annot_itor->start, seq_x+annot_itor->end,
seq_height, annotation_z);
}
+ // if motifs?
+ for (std::list<motif>::const_iterator motifs_itor = motifs.begin();
+ motifs_itor != motifs.end();
+ ++motifs_itor, ++annotation_z)
+ {
+ glColor3fv(color_mapper.lookup("motif", motifs_itor->sequence).get());
+ draw_box(seq_x+motifs_itor->start, seq_x+motifs_itor->end,
+ seq_height, annotation_z);
+ }
+
}
+
const int PT = 1;
const int STROKE = 2;
const int END =3;
#ifndef _GL_SEQUENCE_H_
#define _GL_SEQUENCE_H_
+#include "alg/annotation_colors.hpp"
#include "alg/sequence.hpp"
#include "alg/color.hpp"
#include <GL/gl.h>
class GlSequence
{
public:
- GlSequence(const Sequence & s);
+ GlSequence(const Sequence & s, AnnotationColors &cm);
GlSequence(const GlSequence & s);
GlSequence &operator=(const GlSequence &s);
GLfloat seq_y;
GLfloat seq_z;
GLfloat seq_height;
+ AnnotationColors& color_mapper;
Color drawColor;
const GLfloat char_pix_per_world_unit;
clear();
}
+Mussa::Mussa(const Mussa& m)
+ : analysis_name(m.analysis_name),
+ window(m.window),
+ threshold(m.threshold),
+ soft_thres(m.soft_thres),
+ ana_mode(m.ana_mode),
+ win_append(m.win_append),
+ thres_append(m.thres_append),
+ motif_sequences(m.motif_sequences),
+ color_mapper(m.color_mapper)
+{
+}
+
// set all parameters to null state
void
Mussa::clear()
soft_thres = 0;
win_append = false;
thres_append = false;
+ motif_sequences.clear();
+ color_mapper.clear();
}
// these 5 simple methods manually set the parameters for doing an analysis
//the_paths.save("tmp.save");
}
+
+// I mostly split the ifstream out so I can use a stringstream to test it.
+void Mussa::load_motifs(std::istream &in)
+{
+ string seq;
+ float red;
+ float green;
+ float blue;
+
+ while(in.good())
+ {
+ in >> seq >> red >> green >> blue;
+ // if we couldn't read this line 'cause we're like at the end of the file
+ // try to exit the loop
+ if (!in.good())
+ break;
+ try {
+ seq = Sequence::motif_normalize(seq);
+ } catch(motif_normalize_error e) {
+ clog << "unable to parse " << seq << " skipping" << endl;
+ clog << e.what() << endl;
+ continue;
+ }
+ if (red < 0.0 or red > 1.0) {
+ clog << "invalid red value " << red << ". must be in range [0..1]"
+ << endl;
+ continue;
+ }
+ if (green < 0.0 or green > 1.0) {
+ clog << "invalid green value " << green << ". must be in range [0..1]"
+ << endl;
+ continue;
+ }
+ if (blue < 0.0 or blue > 1.0) {
+ clog << "invalid blue value " << blue << ". must be in range [0..1]"
+ << endl;
+ continue;
+ }
+ if (motif_sequences.find(seq) == motif_sequences.end()) {
+ // sequence wasn't found
+ motif_sequences.insert(seq);
+ Color c(red, green, blue);
+ color_mapper.appendInstanceColor("motif", seq, c);
+ } else {
+ clog << "sequence " << seq << " was already defined skipping"
+ << endl;
+ continue;
+ }
+ }
+ // once we've loaded all the motifs from the file,
+ // lets attach them to the sequences
+ for(vector<Sequence>::iterator seq_i = the_seqs.begin();
+ seq_i != the_seqs.end();
+ ++seq_i)
+ {
+ // clear out old motifs
+ seq_i->clear_motifs();
+ // for all the motifs in our set, attach them to the current sequence
+ for(set<string>::iterator motif_i = motif_sequences.begin();
+ motif_i != motif_sequences.end();
+ ++motif_i)
+ {
+ seq_i->add_motif(*motif_i);
+ }
+ }
+}
+
+void Mussa::load_motifs(string filename)
+{
+ ifstream f;
+ f.open(filename.c_str(), ifstream::in);
+ load_motifs(f);
+}
+
+AnnotationColors& Mussa::colorMapper()
+{
+ return color_mapper;
+}
#include <list>
#include <string>
#include <vector>
+#include <set>
+#include <istream>
+#include "alg/annotation_colors.hpp"
#include "alg/nway_paths.hpp"
#include "alg/sequence.hpp"
enum analysis_modes { TransitiveNway, RadialNway, EntropyNway,
RecursiveNway };
- Mussa();
+ Mussa();
+ Mussa(const Mussa &);
void save();
void save_muway(std::string save_path);
void save_old();
void load_old(char * load_file_path, int s_num);
+ // manage motif lists
+ //! load motifs from an ifstream
+ /*! The file should look something like
+ * <sequence> <red> <green> <blue>
+ * where sequence is a string of IUPAC symbols
+ * and red,green,blue are a white space separated list of floats
+ * in the range [0.0, 1.0]
+ */
+ void load_motifs(std::istream &);
+ //! load a list of motifs from a file named filename
+ void load_motifs(std::string filename);
+
+ //! return color mapper
+ AnnotationColors& colorMapper();
+
private:
// Private variables
// parameters needed for a mussa analysis
//! N-way data, ie the mussa results
NwayPaths the_paths;
+ //! motif list
+ std::set<std::string> motif_sequences;
+ //! color manager
+ AnnotationColors color_mapper;
+
// Private methods
//! loads sequence and annotations from fasta and annotation file
void seqcomp();
}
string
-Sequence::motif_validate(string a_motif)
+Sequence::motif_normalize(string a_motif)
{
string valid_motif;
int seq_i, len;
// current nonIUPAC symbols are omitted, which is not reported atm
for(seq_i = 0; seq_i < len; seq_i++)
{
- if ((a_motif[seq_i] == 'a') || (a_motif[seq_i] == 'A'))
+ if ((a_motif[seq_i] == 'a') || (a_motif[seq_i] == 'A'))
valid_motif += 'A';
else if ((a_motif[seq_i] == 't') || (a_motif[seq_i] == 'T'))
valid_motif += 'T';
valid_motif += 'D';
else if ((a_motif[seq_i] == 'b') || (a_motif[seq_i] == 'B'))
valid_motif += 'B';
- }
-
+ else {
+ string msg = "Letter ";
+ msg += a_motif[seq_i];
+ msg += " is not a valid IUPAC symbol";
+ throw motif_normalize_error(msg);
+ }
+ }
//cout << "valid_motif is: " << valid_motif << endl;
-
return valid_motif;
}
{
vector<int> motif_starts = find_motif(a_motif);
-
for(vector<int>::iterator motif_start_i = motif_starts.begin();
motif_start_i != motif_starts.end();
++motif_start_i)
}
}
+void Sequence::clear_motifs()
+{
+ motif_list.clear();
+}
+
const list<motif>& Sequence::motifs() const
{
return motif_list;
motif_match_starts.clear();
//cout << "motif is: " << a_motif << endl;
- a_motif = motif_validate(a_motif);
+ a_motif = motif_normalize(a_motif);
//cout << "motif is: " << a_motif << endl;
-
if (a_motif != "")
{
//cout << "Sequence: none blank motif\n";
annot();
annot(int start, int end, std::string type, std::string name);
- int start, end;
- std::string name, type;
+ int start;
+ int end;
+ std::string type;
+ std::string name;
};
/* The way that motifs are found currently doesn't really
void motif_scan(std::string a_motif, std::vector<int> * motif_match_starts);
std::string rc_motif(std::string a_motif);
- std::string motif_validate(std::string a_motif);
public:
typedef std::string::iterator iterator;
typedef std::string::const_iterator const_iterator;
const std::string& get_header() const;
//! add a motif to our list of motifs
+ /*! \throws motif_normalize_error if there's something wrong with a_motif
+ */
void add_motif(std::string a_motif);
+ //! clear our list of found motifs
+ void clear_motifs();
+ //! search a sequence for a_motif
+ /*! \throws motif_normalize_error if there's something wrong with a_motif
+ */
std::vector<int> find_motif(std::string a_motif);
+ //! convert IUPAC symbols to upperase
+ /*! \throws motif_normalize_error if there is an invalid symbol
+ */
+ static std::string motif_normalize(std::string a_motif);
void save(std::fstream &save_file);
void load_museq(std::string load_file_path, int seq_num);
};
BOOST_CHECK_EQUAL( ac.lookup(a), black );
a.type = "venchent";
BOOST_CHECK_EQUAL( ac.lookup(a), white );
+
+ ac.clear();
+ BOOST_CHECK_EQUAL( ac.lookup("bleem", "a"), black);
}
#include <string>
+#include "alg/annotation_colors.hpp"
#include "alg/glsequence.hpp"
#include "alg/sequence.hpp"
BOOST_AUTO_TEST_CASE ( glsequence_operator_equal )
{
+ AnnotationColors cm;
// I don't trust my operator = hack so lets make sure it works.
string s0("AAGGCCTT");
string s1("TTGGCCAA");
Sequence seq0(s0);
Sequence seq1(s1);
- GlSequence glseq0(seq0);
+ GlSequence glseq0(seq0, cm);
BOOST_CHECK (glseq0.sequence().get_seq() == s0);
- GlSequence glseq1(seq1);
+ GlSequence glseq1(seq1, cm);
GlSequence glseq_copy0(glseq0);
BOOST_CHECK(glseq_copy0.sequence().get_seq() == glseq0.sequence().get_seq());
BOOST_AUTO_TEST_CASE( glsequence_color )
{
+ AnnotationColors cm;
Color black(0.0, 0.0, 0.0, 0.0);
Color c(0.1, 0.2, 0.3, 0.4);
Sequence seq("AAGGCCTT");
- GlSequence s(seq);
+ GlSequence s(seq, cm);
BOOST_CHECK_EQUAL(s.color(), black );
s.setColor( c );
BOOST_AUTO_TEST_CASE( glsequence_renderable )
{
+ AnnotationColors cm;
Sequence seq("AAGGCCTT");
- GlSequence s(seq);
+ GlSequence s(seq, cm);
// way more base pairs than viewport pixel width
BOOST_CHECK_EQUAL(s.is_sequence_renderable( 0, 1000, 500), false );
BOOST_AUTO_TEST_CASE( glsequence_sequence )
{
+ AnnotationColors cm;
string seq_string("AAGGCCTTNNAAGGCCTTNNAAGGCCTTNN");
string::size_type seqlen = seq_string.size();
Sequence seq(seq_string);
- GlSequence glseq(seq);
+ GlSequence glseq(seq, cm);
BOOST_CHECK( glseq.sequence_begin(0, 50) == seq.begin() );
// always make sure we return seq.end() regardless of how much extra
// make sure the computation of the leftmost and rightmost base is correct
BOOST_AUTO_TEST_CASE( glsequence_leftright_base )
{
+ AnnotationColors cm;
std::string seq_string = "AAGGCCTT";
Sequence seq(seq_string);
- GlSequence glseq(seq);
+ GlSequence glseq(seq, cm);
BOOST_CHECK_EQUAL( glseq.leftbase( -50.0 ), 0 );
BOOST_CHECK_EQUAL( glseq.leftbase( 0.5 ), 1 );
#include <boost/test/auto_unit_test.hpp>
#include <string>
+#include <sstream>
+#include <vector>
#include "alg/mussa.hpp"
+using namespace std;
+
//! can we initialize a mussa object?
BOOST_AUTO_TEST_CASE( mussa_simple )
{
BOOST_CHECK( m1.size() > 0);
}
+
+BOOST_AUTO_TEST_CASE( mussa_load_motif )
+{
+ string data = "AAGG 1.0 1.0 0.0\n"
+ "GGTT 0.0 0.1 1.0\n"
+ "ZXY 2 1.9 0\n";
+
+ istringstream test_istream(data);
+
+ Mussa m1;
+ m1.add_a_seq("AAAAGGGGTTTT");
+ m1.add_a_seq("GGGCCCCTTGGTT");
+ m1.load_motifs(test_istream);
+
+ for (vector<Sequence>::const_iterator seq_i = m1.sequences().begin();
+ seq_i != m1.sequences().end();
+ ++seq_i)
+ {
+ BOOST_CHECK( seq_i->motifs().size() > 0 );
+ }
+}
BOOST_CHECK_EQUAL( motif_i->sequence, m);
}
+ s1.clear_motifs();
+ BOOST_CHECK( s1.motifs().begin() == s1.motifs().end() );
}
BOOST_AUTO_TEST_CASE( annot_test )
--- /dev/null
+TATAAA 0.9 0 0.9
+GGCC 0.0 1 1
explicit mussa_analysis_error(const std::string& msg) :
std::runtime_error(msg) {};
};
+
+class motif_normalize_error : public std::runtime_error
+{
+public:
+ explicit motif_normalize_error(const std::string& msg) :
+ std::runtime_error(msg) {};
+};
#endif
#include <boost/python.hpp>
using namespace boost::python;
+#include "alg/annotation_colors.hpp"
#include "alg/glsequence.hpp"
#include "alg/sequence.hpp"
void export_glsequence()
{
- class_<GlSequence>("GlSequence", init<Sequence &>())
+ class_<GlSequence>("GlSequence", init<Sequence &, AnnotationColors &>())
.def(init<GlSequence &>())
.def("draw", &GlSequence::draw)
.def("sequence", &GlSequence::sequence,
}
}
+void PathScene::loadMotifList()
+{
+ QString caption("Load a motif list");
+ QString filter("Motif list(*.txt *.mtl)");
+ QString path = QFileDialog::getOpenFileName(this,
+ caption,
+ QDir::currentPath(),
+ filter);
+ // user hit cancel?
+ if (path.isNull())
+ return;
+ // try to load safely
+ try {
+ mussaAnalysis->load_motifs(path.toStdString());
+ updateScene();
+ } catch (runtime_error e) {
+ QString msg("Unable to load ");
+ msg += path;
+ msg += "\n";
+ msg += e.what();
+ QMessageBox::warning(this, "Load Motifs", msg);
+ }
+ assert (mussaAnalysis != 0);
+}
void PathScene::loadMupa()
{
QString caption("Load a mussa parameter file");
++seq_itor)
{
y = y - 100;
- gl_seq = new GlSequence(*seq_itor);
+ gl_seq = new GlSequence(*seq_itor, mussaAnalysis->colorMapper());
gl_seq->setX(0);
gl_seq->setY(y);
if (gl_seq->length() > max_base_pairs ) max_base_pairs = gl_seq->length();
void setViewportX(float x);
//! set our magnification level
void setZoom(int);
+ //! load motifs
+ void loadMotifList();
//! load a mussa parameter file (which specifies an analysis to run)
- void loadMupa( );
+ void loadMupa();
//! load a previously run analysis
void loadSavedAnalysis();
//! set the soft threshold used by the Nway_Path algorithm
loadMotifListAction = new QAction(tr("Load Motif List"), this);
connect(loadMotifListAction, SIGNAL(triggered()),
- this, SLOT(loadMotifList()));
+ scene, SLOT(loadMotifList()));
loadMupaAction = new QAction(tr("Load Mussa Parameters"), this);
connect(loadMupaAction, SIGNAL(triggered()),
NotImplementedBox();
}
-void PathWindow::loadMotifList()
-{
- NotImplementedBox();
-}
-
void PathWindow::saveMotifList()
{
NotImplementedBox();
//! \defgroup MotifHandling Handling of motif lists
//\@{
- void loadMotifList();
void saveMotifList();
void toggleMotifs();
//\@}