Skip to content

Commit 635df43

Browse files
- implements #1821
1 parent ba5925c commit 635df43

8 files changed

Lines changed: 531 additions & 232 deletions

File tree

docker-compose.dev.vector.yml

Lines changed: 46 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
11
---
2-
version: '3'
2+
version: "3"
33

44
services:
55
database:
66
# image: postgres:15.12-alpine3.21
7-
# image: postgres:12.2
8-
image: informaticsmatters/rdkit-cartridge-debian:Release_2024_03_6
7+
image: kaliif/pgvectorimage:latest
8+
# image: informaticsmatters/rdkit-cartridge-debian:Release_2024_03_6
99
volumes:
1010
- ../data/postgre/data:/var/lib/postgresql
1111
environment:
@@ -14,9 +14,13 @@ services:
1414
POSTGRES_DB: frag
1515
PGDATA: /var/lib/postgresql/data/pgdata
1616
ports:
17-
- '5432:5432'
17+
- "5432:5432"
1818
healthcheck:
19-
test: ["CMD-SHELL", "pg_isready -U $$POSTGRES_USER -d $$POSTGRES_DB -h localhost"]
19+
test:
20+
[
21+
"CMD-SHELL",
22+
"pg_isready -U $$POSTGRES_USER -d $$POSTGRES_DB -h localhost",
23+
]
2024
interval: 5s
2125
timeout: 5s
2226
retries: 20
@@ -25,7 +29,7 @@ services:
2529
image: redis:7.2.3-alpine3.18
2630
container_name: redis
2731
ports:
28-
- "6379:6379"
32+
- "6379:6379"
2933
healthcheck:
3034
test: redis-cli ping
3135
interval: 10s
@@ -37,8 +41,8 @@ services:
3741
image: informaticsmatters/fragnet-test:3.5.25-xchem-combi-sample-2021-02
3842
ports:
3943
# Comment these two out in produciton
40-
- '7474:7474'
41-
- '7687:7687'
44+
- "7474:7474"
45+
- "7687:7687"
4246
ulimits:
4347
nofile:
4448
soft: 40000
@@ -55,19 +59,19 @@ services:
5559
start_period: 10s
5660
web:
5761
container_name: web_dock
58-
image: xchem/fragalysis-stack:latest
62+
# image: xchem/fragalysis-stack:latest
5963
# image: xchem/fragalysis-backend:m2ms-1649-refresh-fix
6064
# image: boriskovarm2ms/fragalysis-stack:experiment2
6165
# image: kaliif/fragalysis-backend:download-task
62-
# image: kaliif/fragalysis-backend:screenshots
66+
image: kaliif/fragalysis-backend:coordinate-filter
6367
command: /bin/bash /code/launch-stack.sh
6468
volumes:
6569
- ../data/logs:/code/logs/
6670
- ../data/media:/code/media/
6771
- ../fragalysis-frontend:/code/frontend
6872
- ../data/target:/code/target
6973
ports:
70-
- '8080:80'
74+
- "8080:80"
7175
environment:
7276
POSTGRESQL_DATABASE: frag
7377
POSTGRESQL_USER: fragalysis
@@ -77,41 +81,41 @@ services:
7781
NEO4J_AUTH: neo4j/test123
7882
# DISCOURSE_API_KEY: ${DISCOURSE_API_KEY}
7983
FRAGALYSIS_BACKEND_SENTRY_DNS: https://27fa0675f555431aa02ca552e93d8cfb@o194333.ingest.sentry.io/1298290
80-
ISPYB_FLAG: 'False'
84+
ISPYB_FLAG: "False"
8185
# DISCOURSE_DEV_POST_SUFFIX: '-boris-local'
8286
# DISCOURSE_HOST: 'https://discourse.xchem-dev.diamond.ac.uk'
83-
SQUONK2_UI_URL: 'https://data-manager-ui.xchem-dev.diamond.ac.uk/data-manager-ui'
84-
SQUONK2_DMAPI_URL: 'https://data-manager.xchem-dev.diamond.ac.uk/data-manager-api'
85-
SQUONK2_ASAPI_URL: 'https://account-server.xchem-dev.diamond.ac.uk/account-server-api'
87+
SQUONK2_UI_URL: "https://data-manager-ui.xchem-dev.diamond.ac.uk/data-manager-ui"
88+
SQUONK2_DMAPI_URL: "https://data-manager.xchem-dev.diamond.ac.uk/data-manager-api"
89+
SQUONK2_ASAPI_URL: "https://account-server.xchem-dev.diamond.ac.uk/account-server-api"
8690
SQUONK2_ORG_OWNER: ${SQUONK2_ORG_OWNER}
8791
SQUONK2_ORG_OWNER_PASSWORD: ${SQUONK2_ORG_OWNER_PASSWORD}
8892
SQUONK2_ORG_UUID: ${SQUONK2_ORG_UUID}
89-
SQUONK2_PRODUCT_FLAVOUR: 'SILVER'
93+
SQUONK2_PRODUCT_FLAVOUR: "SILVER"
9094
SQUONK2_SLUG: ${SQUONK2_SLUG}
9195
SQUONK2_UNIT_BILLING_DAY: 3
92-
OIDC_AS_CLIENT_ID: 'account-server-api-dev'
93-
OIDC_DM_CLIENT_ID: 'data-manager-api-dev'
94-
OIDC_KEYCLOAK_REALM: 'https://keycloak.xchem-dev.diamond.ac.uk/auth/realms/xchem'
96+
OIDC_AS_CLIENT_ID: "account-server-api-dev"
97+
OIDC_DM_CLIENT_ID: "data-manager-api-dev"
98+
OIDC_KEYCLOAK_REALM: "https://keycloak.xchem-dev.diamond.ac.uk/auth/realms/xchem"
9599
OIDC_RP_CLIENT_SECRET: ${OIDC_RP_CLIENT_SECRET}
96-
OIDC_RP_CLIENT_ID: 'fragalysis-local'
100+
OIDC_RP_CLIENT_ID: "fragalysis-local"
97101
OIDC_RENEW_ID_TOKEN_EXPIRY_MINUTES: 210
98102
# ISPYB_HOST: ispybdbproxy.diamond.ac.uk
99103
ISPYB_PORT: 4306
100104
ISPYB_USER: ${ISPYB_USER}
101105
ISPYB_PASSWORD: ${ISPYB_PASSWORD}
102106
SECURITY_CONNECTOR: ssh_ispyb
103107
LOGGING_FRAMEWORK_ROOT_LEVEL: DEBUG
104-
AUTHENTICATE_UPLOAD: 'False'
105-
CELERY_TASK_ALWAYS_EAGER: 'False'
106-
DEBUG_FRAGALYSIS: 'True'
107-
PROXY_FORWARDED_PROTO_HEADER: 'http'
108-
LEGACY_URL: 'https://fragalysis.diamond.ac.uk'
109-
DEPLOYMENT_MODE: 'development'
110-
DISABLE_RESTRICT_PROPOSALS_TO_MEMBERSHIP: 'True'
111-
PUBLIC_TAS: 'lb18145-1,lb32633-1'
112-
RESTRICTED_TAS_USERS: 'spf57946:lb32627-261'
108+
AUTHENTICATE_UPLOAD: "False"
109+
CELERY_TASK_ALWAYS_EAGER: "False"
110+
DEBUG_FRAGALYSIS: "True"
111+
PROXY_FORWARDED_PROTO_HEADER: "http"
112+
LEGACY_URL: "https://fragalysis.diamond.ac.uk"
113+
DEPLOYMENT_MODE: "development"
114+
DISABLE_RESTRICT_PROPOSALS_TO_MEMBERSHIP: "True"
115+
PUBLIC_TAS: "lb18145-1,lb32633-1"
116+
RESTRICTED_TAS_USERS: "spf57946:lb32627-261"
113117
WEB_DJANGO_SUPERUSER_PASSWORD: ${WEB_DJANGO_SUPERUSER_PASSWORD}
114-
SQUONK2_REFRESH_SHOULD_RETRIEVE_RESULTS: 'Yes'
118+
SQUONK2_REFRESH_SHOULD_RETRIEVE_RESULTS: "Yes"
115119
# INFECTIONS: 'structure-download'
116120
healthcheck:
117121
test: python manage.py --help || exit 1
@@ -141,24 +145,24 @@ services:
141145
- .env
142146
# image: ${BE_NAMESPACE:-xchem}/fragalysis-backend:${BE_IMAGE_TAG:-latest}
143147
# image: kaliif/fragalysis-backend:download-task
144-
# image: kaliif/fragalysis-backend:screenshots
145-
image: xchem/fragalysis-stack:latest
148+
image: kaliif/fragalysis-backend:coordinate-filter
149+
# image: xchem/fragalysis-stack:latest
146150
restart: on-failure
147151
volumes:
148-
- ../data/logs:/code/logs/
149-
- ../data/media:/code/media/
152+
- ../data/logs:/code/logs/
153+
- ../data/media:/code/media/
150154
environment:
151-
AUTHENTICATE_UPLOAD: 'False'
152-
DEPLOYMENT_MODE: 'development'
155+
AUTHENTICATE_UPLOAD: "False"
156+
DEPLOYMENT_MODE: "development"
153157
POSTGRESQL_DATABASE: frag
154158
POSTGRESQL_USER: fragalysis
155159
POSTGRESQL_PASSWORD: fragalysis
156160
POSTGRESQL_HOST: database
157161
POSTGRESQL_PORT: 5432
158162
# Comma-separated dforced errors (infections?)
159-
INFECTIONS: ''
163+
INFECTIONS: ""
160164
# Celery tasks need to run synchronously
161-
CELERY_TASK_ALWAYS_EAGER: 'False'
165+
CELERY_TASK_ALWAYS_EAGER: "False"
162166
# Error reporting and default/root log-level
163167
FRAGALYSIS_BACKEND_SENTRY_DNS: ${FRAGALYSIS_BACKEND_SENTRY_DNS}
164168
LOGGING_FRAMEWORK_ROOT_LEVEL: ${LOGGING_FRAMEWORK_ROOT_LEVEL:-INFO}
@@ -168,12 +172,12 @@ services:
168172
OIDC_RP_CLIENT_SECRET: ${OIDC_RP_CLIENT_SECRET}
169173
OIDC_AS_CLIENT_ID: ${OIDC_AS_CLIENT_ID:-account-server-api}
170174
OIDC_DM_CLIENT_ID: ${OIDC_DM_CLIENT_ID:-data-manager-api}
171-
OIDC_RENEW_ID_TOKEN_EXPIRY_MINUTES: '210'
175+
OIDC_RENEW_ID_TOKEN_EXPIRY_MINUTES: "210"
172176
# Public target access strings?
173177
# A comma-separated list of Project titles.
174178
PUBLIC_TAS: ${PUBLIC_TAS:-lb18145-1}
175179
# Squonk configuration
176-
SQUONK2_VERIFY_CERTIFICATES: 'No'
180+
SQUONK2_VERIFY_CERTIFICATES: "No"
177181
SQUONK2_UNIT_BILLING_DAY: 3
178182
SQUONK2_PRODUCT_FLAVOUR: BRONZE
179183
SQUONK2_SLUG: fs-local
@@ -199,6 +203,6 @@ services:
199203
- .env
200204
# image: ${BE_NAMESPACE:-xchem}/fragalysis-backend:${BE_IMAGE_TAG:-latest}
201205
# image: kaliif/fragalysis-backend:download-task
202-
image: xchem/fragalysis-stack:latest
203-
# image: kaliif/fragalysis-backend:screenshots
206+
# image: xchem/fragalysis-stack:latest
207+
image: kaliif/fragalysis-backend:coordinate-filter
204208
restart: on-failure

js/components/nglView/nglView.js

Lines changed: 90 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44

55
import { Stage, Shape } from 'ngl';
66
import React, { memo, useEffect, useCallback, useContext, useState, useRef } from 'react';
7-
import { connect } from 'react-redux';
7+
import { connect, useDispatch, useSelector } from 'react-redux';
88
import * as nglActions from '../../reducers/ngl/actions';
99
import * as nglDispatchActions from '../../reducers/ngl/dispatchActions';
1010
import * as selectionActions from '../../reducers/selection/actions';
@@ -15,6 +15,8 @@ import { NGL_PARAMS } from './constants';
1515
import { makeStyles, Popover, TextField, Button, Typography } from '@material-ui/core';
1616
import { VIEWS } from '../../constants/constants';
1717
import { INITIAL_STATE as NGL_INITIAL } from '../../reducers/ngl/nglReducers';
18+
import { api } from '../../utils/api';
19+
import { base_url } from '../routes/constants';
1820

1921
const useStyles = makeStyles(theme => ({
2022
paper: {
@@ -40,6 +42,7 @@ const NglView = memo(
4042
defaultRadius = 5,
4143
apiEndpoint = '/api/radius-selection'
4244
}) => {
45+
const dispatch = useDispatch();
4346
// connect to NGL Stage object
4447
const { registerNglView, unregisterNglView, getNglView } = useContext(NglContext);
4548
const [stage, setStage] = useState();
@@ -54,6 +57,24 @@ const NglView = memo(
5457
const sphereCompRef = useRef(null);
5558
const lastOriginRef = useRef(null);
5659

60+
const targetId = useSelector(state => state.apiReducers.target_on);
61+
62+
const sphereCoordinates = useSelector(state => state.selectionReducers.sphereCoordinates);
63+
const coordinateRadius = useSelector(state => state.selectionReducers.coordinateRadius);
64+
const unifiedFilter = useSelector(state => state.selectionReducers.unifiedFilter);
65+
const isCoordinateFilterApplied = useSelector(state => state.selectionReducers.isCoordinateFilterApplied);
66+
const sphereRendered = useSelector(state => state.selectionReducers.sphereRendered);
67+
68+
const isCoordinateFilterPermitted = unifiedFilter?.detail?.coordinateSearch === true;
69+
const isCoordinateFilterPermittedRef = useRef(isCoordinateFilterPermitted);
70+
// Keep ref up to date
71+
useEffect(() => {
72+
isCoordinateFilterPermittedRef.current = isCoordinateFilterPermitted;
73+
}, [isCoordinateFilterPermitted]);
74+
// console.log('unifiedFilter?.detail?.coordinateSearch:', unifiedFilter?.detail?.coordinateSearch);
75+
const rendererDomElement = stage?.viewer?.renderer?.domElement;
76+
const mousePosition = stage?.mouseObserver?.position;
77+
5778
const parseRadius = useCallback(
5879
val => {
5980
const n = parseFloat(val);
@@ -91,16 +112,22 @@ const NglView = memo(
91112
const origin = lastOriginRef.current;
92113
if (!origin) return;
93114
const value = parseRadius(radius);
94-
const payload = { origin: [origin.x, origin.y, origin.z], radius: value };
95-
try {
96-
await fetch(apiEndpoint, {
97-
method: 'POST',
98-
headers: { 'Content-Type': 'application/json' },
99-
body: JSON.stringify(payload)
115+
api({
116+
url: `${base_url}/api/site_observation_ids/?target=${targetId}&xorigin=${origin.x}&yorigin=${origin.y}&zorigin=${origin.z}&radius=${value}`
117+
})
118+
.then(response => {
119+
if (response?.data?.results) {
120+
const ids = response.data.results.map(item => item.id);
121+
dispatch(selectionActions.setCoordinateFilterResults(ids));
122+
dispatch(selectionActions.setIsCoordinateFilterApplied(true));
123+
// console.log('Site Observation IDs within radius:', ids);
124+
}
125+
})
126+
.catch(err => {
127+
console.log(err);
100128
});
101-
} catch (e) {}
102129
setPopoverOpen(false);
103-
}, [apiEndpoint, radius, parseRadius]);
130+
}, [dispatch, parseRadius, radius, targetId]);
104131

105132
useEffect(() => {
106133
const monitor = () => {
@@ -133,31 +160,63 @@ const NglView = memo(
133160
}
134161
}, [div_id, getNglView]);
135162

163+
// Stable handler, always reads latest value from ref
136164
const handleStageClicked = useCallback(
137165
pickingProxy => {
166+
// Always use ref for latest value
167+
if (!isCoordinateFilterPermittedRef.current) return;
138168
if (!pickingProxy) return;
139169
if (!(pickingProxy.atom || pickingProxy.bond)) return;
140170
const pos = pickingProxy.position?.clone?.();
141171
if (!pos) return;
142172

143173
lastOriginRef.current = pos;
144-
ensureSphereAt(pos, parseRadius(radius));
174+
dispatch(selectionActions.setSphereCoordinate(pos));
175+
dispatch(selectionActions.setCoordinateRadius(radius));
176+
// ensureSphereAt(pos, parseRadius(radius));
145177

146178
// Anchor popover to mouse cursor using NGL's mouseObserver
147-
const canvas = stage?.viewer?.renderer?.domElement;
148-
if (canvas && stage?.mouseObserver?.position) {
179+
const canvas = rendererDomElement;
180+
if (canvas && mousePosition) {
149181
const rect = canvas.getBoundingClientRect();
150-
const m = stage.mouseObserver.position;
182+
const m = mousePosition;
151183
setAnchorPos({
152184
top: Math.round(rect.top + m.y),
153185
left: Math.round(rect.left + m.x)
154186
});
155187
}
156188
setPopoverOpen(true);
157189
},
158-
[ensureSphereAt, parseRadius, radius, stage]
190+
[dispatch, mousePosition, radius, rendererDomElement]
159191
);
160192

193+
useEffect(() => {
194+
if (!ready) return;
195+
if (sphereCoordinates && isCoordinateFilterPermitted && !sphereRendered) {
196+
dispatch(selectionActions.setSphereRendered(true));
197+
ensureSphereAt(sphereCoordinates, parseRadius(coordinateRadius));
198+
} else {
199+
if (!sphereCoordinates && sphereCompRef.current && sphereRendered) {
200+
try {
201+
stage.removeComponent(sphereCompRef.current);
202+
dispatch(selectionActions.setSphereRendered(false));
203+
} catch (e) {
204+
console.error(e);
205+
}
206+
}
207+
}
208+
}, [
209+
coordinateRadius,
210+
dispatch,
211+
ensureSphereAt,
212+
isCoordinateFilterPermitted,
213+
parseRadius,
214+
ready,
215+
sphereCoordinates,
216+
sphereRendered,
217+
stage
218+
]);
219+
161220
const registerStageEvents = useCallback(
162221
(newStage, getNglView) => {
163222
if (newStage) {
@@ -217,12 +276,12 @@ const NglView = memo(
217276
}
218277
}
219278

220-
return () => {
221-
if (stage) {
222-
unregisterStageEvents(stage, getNglView);
223-
unregisterNglView(div_id);
224-
}
225-
};
279+
// return () => {
280+
// if (stage) {
281+
// unregisterStageEvents(stage, getNglView);
282+
// unregisterNglView(div_id);
283+
// }
284+
// };
226285
}, [
227286
div_id,
228287
handleResize,
@@ -280,7 +339,17 @@ const NglView = memo(
280339
fullWidth
281340
/>
282341
<div style={{ display: 'flex', gap: 8, justifyContent: 'flex-end', marginTop: 12 }}>
283-
<Button onClick={() => setPopoverOpen(false)}>Cancel</Button>
342+
<Button
343+
onClick={() => {
344+
if (!isCoordinateFilterApplied) {
345+
dispatch(selectionActions.setSphereCoordinate(null));
346+
dispatch(selectionActions.setCoordinateRadius(''));
347+
}
348+
setPopoverOpen(false);
349+
}}
350+
>
351+
Cancel
352+
</Button>
284353
<Button variant="contained" color="primary" onClick={submitRadius}>
285354
Apply
286355
</Button>

0 commit comments

Comments
 (0)