-
Notifications
You must be signed in to change notification settings - Fork 1
/
image-beam-location.go
140 lines (117 loc) · 4.2 KB
/
image-beam-location.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
package wsHandler
import (
"context"
"errors"
"fmt"
"github.com/pixlise/core/v4/api/dbCollections"
"github.com/pixlise/core/v4/api/ws/wsHelpers"
"github.com/pixlise/core/v4/core/errorwithstatus"
protos "github.com/pixlise/core/v4/generated-protos"
"go.mongodb.org/mongo-driver/bson"
"go.mongodb.org/mongo-driver/mongo"
"go.mongodb.org/mongo-driver/mongo/options"
)
func HandleImageBeamLocationsReq(req *protos.ImageBeamLocationsReq, hctx wsHelpers.HandlerContext) ([]*protos.ImageBeamLocationsResp, error) {
ctx := context.TODO()
var locs *protos.ImageLocations
// If we have generateForScanId set, we don't want to have an image name!
if len(req.GenerateForScanId) > 0 {
if len(req.ImageName) > 0 {
return nil, errorwithstatus.MakeBadRequestError(errors.New("Expected empty image name for request with GenerateForScanId set"))
}
// Check user has access to this scan
_, err := wsHelpers.CheckObjectAccess(false, req.GenerateForScanId, protos.ObjectType_OT_SCAN, hctx)
if err != nil {
return nil, err
}
// Read the scan item so we get the right instrument
coll := hctx.Svcs.MongoDB.Collection(dbCollections.ScansName)
scanResult := coll.FindOne(ctx, bson.M{"_id": req.GenerateForScanId}, options.FindOne())
if scanResult.Err() != nil {
return nil, errorwithstatus.MakeNotFoundError(req.GenerateForScanId)
}
scan := &protos.ScanItem{}
err = scanResult.Decode(scan)
if err != nil {
return nil, fmt.Errorf("Failed to decode scan: %v. Error: %v", req.GenerateForScanId, err)
}
// Generate away! NOTE: empty image name implies this won't write to DB
locs, err = generateIJs("", req.GenerateForScanId, scan.Instrument, hctx)
if err != nil {
return nil, err
}
} else {
// We MUST have an image name in this case
if err := wsHelpers.CheckStringField(&req.ImageName, "ImageName", 1, 255); err != nil {
return nil, err
}
coll := hctx.Svcs.MongoDB.Collection(dbCollections.ImageBeamLocationsName)
// Read the image and check that the user has access to all scans associated with it
result := coll.FindOne(ctx, bson.M{"_id": req.ImageName})
if result.Err() != nil {
if result.Err() == mongo.ErrNoDocuments {
return nil, errorwithstatus.MakeNotFoundError(req.ImageName)
}
return nil, result.Err()
}
err := result.Decode(&locs)
if err != nil {
return nil, err
}
if len(locs.LocationPerScan) <= 0 {
return nil, fmt.Errorf("No beams defined for image: %v", req.ImageName)
}
for _, scanLocs := range locs.LocationPerScan {
_, err := wsHelpers.CheckObjectAccess(false, scanLocs.ScanId, protos.ObjectType_OT_SCAN, hctx)
if err != nil {
return nil, err
}
}
}
// Return the coordinates from DB record
return []*protos.ImageBeamLocationsResp{&protos.ImageBeamLocationsResp{
Locations: locs,
}}, nil
}
func generateIJs(imageName string, scanId string, instrument protos.ScanInstrument, hctx wsHelpers.HandlerContext) (*protos.ImageLocations, error) {
hctx.Svcs.Log.Infof("Generating IJ's for image: %v, scan: %v...", imageName, scanId)
// Read the dataset file
exprPB, err := wsHelpers.ReadDatasetFile(scanId, hctx.Svcs)
if err != nil {
return nil, err
}
// Generate coordinates
scale := float32(1)
if len(imageName) > 0 {
scale = 100 // We scale XY up by this much to make them not be bunched up so much, so the image doesn't have to scale down too much (it's a bit arbitrary)
}
coords := []*protos.Coordinate2D{}
for _, loc := range exprPB.Locations {
if loc.Beam == nil {
coords = append(coords, nil)
} else {
coords = append(coords, &protos.Coordinate2D{I: loc.Beam.X * scale, J: loc.Beam.Y * scale})
}
}
locs := protos.ImageLocations{
ImageName: imageName,
LocationPerScan: []*protos.ImageLocationsForScan{{
ScanId: scanId,
//BeamVersion: 1,
Instrument: instrument,
Locations: coords,
}},
}
if len(imageName) > 0 {
ctx := context.TODO()
coll := hctx.Svcs.MongoDB.Collection(dbCollections.ImageBeamLocationsName)
result, err := coll.InsertOne(ctx, &locs, options.InsertOne())
if err != nil {
return nil, err
}
if result.InsertedID != imageName {
return nil, fmt.Errorf("Inserting generated beam IJs, expected id: %v, got: %v", imageName, result.InsertedID)
}
}
return &locs, nil
}