Skip to content

Commit c90d9f9

Browse files
committed
Made Interface search as a separate tab
1 parent 08fc046 commit c90d9f9

File tree

11 files changed

+714
-9
lines changed

11 files changed

+714
-9
lines changed

backend/alignment.go

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -562,6 +562,13 @@ func ComplexAlignments(id Id, entry []uint32, databases []string, jobsbase strin
562562
return ReadAlignments[ComplexAlignmentEntry, uint32](id, entry, databases, jobsbase)
563563
}
564564

565+
type InterfaceAlignmentEntry = ComplexAlignmentEntry
566+
567+
func InterfaceAlignments(id Id, entry []uint32, databases []string, jobsbase string) ([]SearchResult, error) {
568+
return ReadAlignments[InterfaceAlignmentEntry, uint32](id, entry, databases, jobsbase)
569+
}
570+
571+
565572
func FoldDiscoAlignments(id Id, databases []string, jobsbase string) ([]FoldDiscoResult, error) {
566573
return ReadFoldDisco(id, databases, jobsbase)
567574
}

backend/interfacesearchjob.go

Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
package main
2+
3+
import (
4+
"crypto/sha256"
5+
"encoding/base64"
6+
"errors"
7+
"os"
8+
"sort"
9+
"strings"
10+
)
11+
12+
type InterfaceSearchJob struct {
13+
Size int `json:"size" validate:"required"`
14+
Database []string `json:"database" validate:"required"`
15+
Mode string `json:"mode" validate:"oneof=3di tmalign 3diaa lolalign"`
16+
TaxFilter string `json:"taxfilter"`
17+
query string
18+
}
19+
20+
func (r InterfaceSearchJob) Hash() Id {
21+
h := sha256.New224()
22+
h.Write(([]byte)(JobInterfaceSearch))
23+
h.Write([]byte(r.query))
24+
h.Write([]byte(r.Mode))
25+
if r.TaxFilter != "" {
26+
h.Write([]byte(r.TaxFilter))
27+
}
28+
29+
sort.Strings(r.Database)
30+
31+
for _, value := range r.Database {
32+
h.Write([]byte(value))
33+
}
34+
35+
bs := h.Sum(nil)
36+
return Id(base64.URLEncoding.WithPadding(base64.NoPadding).EncodeToString(bs))
37+
}
38+
39+
func (r InterfaceSearchJob) Rank() float64 {
40+
return float64(r.Size * max(len(r.Database), 1))
41+
}
42+
43+
func (r InterfaceSearchJob) WritePDB(path string) error {
44+
err := os.WriteFile(path, []byte(r.query), 0644)
45+
if err != nil {
46+
return err
47+
}
48+
return nil
49+
}
50+
51+
func NewInterfaceSearchJobRequest(query string, dbs []string, validDbs []Params, mode string, resultPath string, email string, taxfilter string) (JobRequest, error) {
52+
job := InterfaceSearchJob{
53+
max(strings.Count(query, "HEADER"), 1),
54+
dbs,
55+
mode,
56+
taxfilter,
57+
query,
58+
}
59+
60+
request := JobRequest{
61+
job.Hash(),
62+
StatusPending,
63+
JobInterfaceSearch,
64+
job,
65+
email,
66+
}
67+
68+
ids := make([]string, 0)
69+
for _, item := range validDbs {
70+
if item.Interface {
71+
ids = append(ids, item.Path)
72+
}
73+
}
74+
75+
for _, item := range job.Database {
76+
idx := isIn(item, ids)
77+
if idx == -1 {
78+
return request, errors.New("selected databases are not valid")
79+
}
80+
}
81+
82+
if !validTaxonFilter(taxfilter) {
83+
return request, errors.New("invalid taxon filter")
84+
}
85+
86+
return request, nil
87+
}

backend/jobsystem.go

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ const (
2525
JobPair JobType = "pair"
2626
JobStructureSearch JobType = "structuresearch"
2727
JobComplexSearch JobType = "complexsearch"
28+
JobInterfaceSearch JobType = "interfacesearch"
2829
JobFoldMasonMSA JobType = "foldmasoneasymsa"
2930
JobFoldDisco JobType = "folddisco"
3031
)
@@ -70,6 +71,13 @@ func (m *JobRequest) UnmarshalJSON(b []byte) error {
7071
}
7172
(*m).Job = j
7273
return nil
74+
case JobInterfaceSearch:
75+
var j InterfaceSearchJob
76+
if err := json.Unmarshal(msg, &j); err != nil {
77+
return err
78+
}
79+
(*m).Job = j
80+
return nil
7381
case JobIndex:
7482
var j IndexJob
7583
if err := json.Unmarshal(msg, &j); err != nil {
@@ -127,6 +135,11 @@ func (m *JobRequest) WriteSupportFiles(base string) error {
127135
return j.WritePDB(filepath.Join(base, "job.pdb"))
128136
}
129137
return errors.New("invalid job type")
138+
case JobInterfaceSearch:
139+
if j, ok := m.Job.(InterfaceSearchJob); ok {
140+
return j.WritePDB(filepath.Join(base, "job.pdb"))
141+
}
142+
return errors.New("invalid job type")
130143
case JobMsa:
131144
if j, ok := m.Job.(MsaJob); ok {
132145
return j.WriteFasta(filepath.Join(base, "job.fasta"))

backend/server.go

Lines changed: 38 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -326,8 +326,12 @@ func server(jobsystem JobSystem, config ConfigRoot) {
326326
request, err = NewSearchJobRequest(query, dbs, databases, mode, config.Paths.Results, email, taxfilter)
327327
} else if config.App == AppFoldseek {
328328
modes := strings.Split(mode, "-")
329+
interfaceIdx := isIn("interface", modes)
329330
modeIdx := isIn("complex", modes)
330-
if modeIdx != -1 {
331+
if interfaceIdx != -1 {
332+
modeWithoutInterface := strings.Join(append(modes[:interfaceIdx], modes[interfaceIdx+1:]...), "-")
333+
request, err = NewInterfaceSearchJobRequest(query, dbs, databases, modeWithoutInterface, config.Paths.Results, email, taxfilter)
334+
} else if modeIdx != -1 {
331335
modeWithoutComplex := strings.Join(append(modes[:modeIdx], modes[modeIdx+1:]...), "-")
332336
request, err = NewComplexSearchJobRequest(query, dbs, databases, modeWithoutComplex, config.Paths.Results, email, taxfilter)
333337
} else {
@@ -1092,6 +1096,38 @@ func server(jobsystem JobSystem, config ConfigRoot) {
10921096
http.Error(w, err.Error(), http.StatusBadRequest)
10931097
return
10941098
}
1099+
case InterfaceSearchJob:
1100+
mode = job.Mode
1101+
result, err := Lookup(ticket.Id, 0, math.MaxInt32, config.Paths.Results, false)
1102+
if err != nil {
1103+
http.Error(w, err.Error(), http.StatusBadRequest)
1104+
return
1105+
}
1106+
keys := make([]uint32, 0)
1107+
for _, lookup := range result.Lookup {
1108+
if lookup.Set == uint32(id) {
1109+
keys = append(keys, uint32(lookup.Id))
1110+
}
1111+
}
1112+
isFoldseek = true
1113+
databases := job.Database
1114+
if database != "" {
1115+
if isIn(database, job.Database) == -1 {
1116+
http.Error(w, "Database not found", http.StatusBadRequest)
1117+
return
1118+
}
1119+
databases = []string{database}
1120+
}
1121+
results, err = InterfaceAlignments(ticket.Id, keys, databases, config.Paths.Results)
1122+
if err != nil {
1123+
http.Error(w, err.Error(), http.StatusBadRequest)
1124+
return
1125+
}
1126+
fasta, err = ReadQueryByKeys(ticket.Id, keys, config.Paths.Results)
1127+
if err != nil {
1128+
http.Error(w, err.Error(), http.StatusBadRequest)
1129+
return
1130+
}
10951131
default:
10961132
http.Error(w, "Invalid job type", http.StatusBadRequest)
10971133
return
@@ -1135,7 +1171,7 @@ func server(jobsystem JobSystem, config ConfigRoot) {
11351171
cnt++
11361172
}
11371173
}
1138-
case [][]ComplexAlignmentEntry:
1174+
case [][]ComplexAlignmentEntry: // Handle both ComplexSearchJob and InterfaceSearchJob
11391175
if resIndex == -1 {
11401176
for _, inner := range conv {
11411177
for i := range inner {

0 commit comments

Comments
 (0)