1 module dparasail.alignment; 2 3 import std.utf; 4 import core.stdc.stdlib : exit; 5 6 import dparasail.result; 7 import dparasail.memory; 8 import dparasail.log; 9 import parasail; 10 11 12 /* 13 * Acts as a profile of settings for reusing 14 * alignment settings 15 */ 16 struct Parasail 17 { 18 /// alignment scoring matrix reference 19 private ParasailMatrix score_matrix; 20 21 /// using database query? 22 private bool databaseQuery; 23 24 /// gap open penalty (must be positive) 25 private int gapOpen; 26 27 /// gap extension penalty (must be positive) 28 private int gapExt; 29 30 /// parasail profile reference if doing 31 /// if doing database alignment 32 private ParasailProfile profile; 33 34 /// query sequence if doing database alignment 35 private string s1; 36 37 @disable this(); 38 39 /// use a prebuilt parasail scoring matrix 40 /// or an alphabet matrix 41 /// and a gap and ext penalty 42 this(string matrix, int open, int ext, int match = -1, int mismatch = 1) 43 { 44 this(matrix, "", open, ext, match, mismatch); 45 } 46 47 /// use a prebuilt parasail scoring matrix 48 /// or an alphabet matrix 49 /// with a database sequence 50 /// and a gap and ext penalty 51 this(string matrix, string databaseSequence, int open, int ext, int match = -1, int mismatch = 1){ 52 auto m = parasail_matrix_lookup(toUTFz!(char*)(matrix)); 53 54 if(m != null){ 55 auto mCopy = parasail_matrix_copy(m); 56 this(mCopy, open, ext); 57 }else{ 58 logWarning(__FUNCTION__, "Couldn't load matrix named " ~matrix ~", assuming alphabet"); 59 if(m == null && (match == -1 || mismatch == 1)){ 60 logError(__FUNCTION__, "Couldn't load matrix and match and mismatch penalties are unset (-1, 1)"); 61 exit(-1); 62 } 63 auto alphabet = matrix; 64 logWarning(__FUNCTION__, "Attempting to create matrix from alphabet " ~alphabet); 65 66 assert(match > 0, "match score must be > 0"); 67 assert(mismatch < 0, "mismatch penalty/score must be < 0"); 68 69 auto mCreate = parasail_matrix_create(toUTFz!(char*)(alphabet), match, mismatch); 70 if(mCreate == null) 71 { 72 logError(__FUNCTION__, "Couldn't create matrix from alphabet " ~alphabet); 73 exit(-1); 74 } 75 this(mCreate, databaseSequence, open, ext); 76 } 77 } 78 79 /// use a parasail_matrix_t directly 80 /// with a database sequence 81 /// and a gap and ext penalty 82 this(parasail_matrix_t * matrix, string databaseSequence, int open, int ext) 83 { 84 if(databaseSequence != "") 85 { 86 this.s1 = databaseSequence; 87 auto prof = parasail_profile_create_sat(toUTFz!(char*)(s1), cast(int) s1.length, matrix); 88 if(prof == null) 89 { 90 logError(__FUNCTION__, "Couldn't create database profile from " ~databaseSequence); 91 } 92 this.profile = ParasailProfile(prof); 93 } 94 this.score_matrix = ParasailMatrix(matrix); 95 assert(open > 0, "gap open penalty must be greater than 0"); 96 assert(ext > 0, "gap extension penalty must be greater than 0"); 97 this.gapOpen = open; 98 this.gapExt = ext; 99 } 100 101 /// use a parasail_matrix_t directly 102 /// and a gap and ext penalty 103 this(parasail_matrix_t * matrix, int open, int ext) 104 { 105 this.profile = ParasailProfile(cast(parasail_profile_t *) null); 106 this.score_matrix = ParasailMatrix(matrix); 107 assert(open > 0, "gap open penalty must be greater than 0"); 108 assert(ext > 0, "gap extension penalty must be greater than 0"); 109 this.gapOpen = open; 110 this.gapExt = ext; 111 } 112 113 this(this){ 114 this.score_matrix = score_matrix; 115 this.databaseQuery = databaseQuery; 116 this.gapOpen = gapOpen; 117 this.gapExt = gapExt; 118 this.profile = profile; 119 this.s1 = s1; 120 } 121 122 /// get scoring matrix 123 auto scoreMatrix() 124 { 125 return this.score_matrix; 126 } 127 128 /// run sw alignment 129 ParasailResult sw_striped(string s1, string s2) 130 { 131 if(!(this.profile is null)) 132 logWarning(__FUNCTION__, "You are using sw align but a database profile is set"); 133 134 auto seq1 = toUTFz!(const char*)(s1); 135 auto seq2 = toUTFz!(const char*)(s2); 136 auto seq1Len = cast(const int) s1.length; 137 auto seq2Len = cast(const int) s2.length; 138 auto res = parasail_sw_trace_striped_16(seq1, seq1Len, seq2, 139 seq2Len, this.gapOpen, this.gapExt, this.score_matrix); 140 return ParasailResult(&this, res, s1, s2); 141 } 142 143 ParasailResult nw_scan(string s1, string s2) 144 { 145 if(!(this.profile is null)) 146 logWarning(__FUNCTION__, "You are using nw align but a database profile is set"); 147 148 auto seq1 = toUTFz!(const char*)(s1); 149 auto seq2 = toUTFz!(const char*)(s2); 150 auto seq1Len = cast(const int) s1.length; 151 auto seq2Len = cast(const int) s2.length; 152 auto res = parasail_nw_trace_scan_16(seq1, seq1Len, seq2, 153 seq2Len, this.gapOpen, this.gapExt, this.score_matrix); 154 return ParasailResult(&this, res, s1, s2); 155 } 156 157 158 ParasailResult aligner(string alg, string output_option = "trace", 159 string impl_option = "striped", string sol_width = "sat")(string s1, string s2) 160 { 161 if(!(this.profile is null)) 162 logWarning(__FUNCTION__, "You are using aligner but a database profile is set"); 163 164 auto seq1 = toUTFz!(const char*)(s1); 165 auto seq2 = toUTFz!(const char*)(s2); 166 auto seq1Len = cast(const int) s1.length; 167 auto seq2Len = cast(const int) s2.length; 168 mixin("auto res = parasail_" ~ alg ~ "_" ~ output_option ~ "_" ~ impl_option ~ "_" 169 ~ sol_width ~ "(seq1, seq1Len, seq2, seq2Len, this.gapOpen, this.gapExt, this.score_matrix);"); 170 return ParasailResult(&this, res, s1, s2); 171 } 172 173 ParasailResult databaseAligner(string alg, string impl_option = "striped")(string s2) 174 { 175 auto seq2 = toUTFz!(const char*)(s2); 176 auto seq2Len = cast(const int) s2.length; 177 if(this.profile is null){ 178 logError(__FUNCTION__, "Cannot use databaseAligner when profile is not set"); 179 exit(-1); 180 } 181 mixin("auto res = parasail_" ~ alg ~ "_" ~ impl_option 182 ~ "_profile_sat(this.profile, seq2, seq2Len, gapOpen, gapExt);"); 183 return ParasailResult(&this, res, this.s1, s2); 184 } 185 }