Skip to content

Commit

Permalink
Reorganized model URLs and added filter by model URL.
Browse files Browse the repository at this point in the history
  • Loading branch information
gaurav committed Apr 26, 2024
1 parent b29de5d commit 2e9ec3c
Show file tree
Hide file tree
Showing 3 changed files with 53 additions and 34 deletions.
10 changes: 5 additions & 5 deletions frontend/src/components/CAMKPFrontend.vue
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,12 @@ import SearchCAMs from "./SearchCAMs.vue";
// Some editable
const automatCAMKPEndpoint = ref("https://automat.renci.org/cam-kp")
const selectedModel = ref({})
const searchIds = ref<string[]>([]);
const selectedModelURL = ref('')
const searchIds = ref<Set<string>>(new Set<string>());
function changeSelectedModel(modelName: string) {
function changeSelectedModel(modelURL: string) {
// Allows other components to change the selected model.
selectedModel.value = modelName;
selectedModelURL.value = modelURL;
}
function changeSearchIds(searchIdList: string[]) {
Expand Down Expand Up @@ -41,7 +41,7 @@ function changeSearchIds(searchIdList: string[]) {

<div class="row">
<SearchCAMs :automatCAMKPEndpoint="automatCAMKPEndpoint" :changeSelectedModel="changeSelectedModel" :changeSearchIds="changeSearchIds" />
<DisplayCAM :selected-model="selectedModel" :search-ids="searchIds"></DisplayCAM>
<DisplayCAM :selected-model-u-r-l="selectedModelURL" :search-ids="searchIds"></DisplayCAM>
</div>

<div class="accordion" id="advancedOptionsAccordion">
Expand Down
20 changes: 8 additions & 12 deletions frontend/src/components/DisplayCAM.vue
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import {urlToID} from "./shared.ts";
export interface Props {
automatCAMKPEndpoint?: string,
selectedModel: object,
selectedModelURL: string,
searchIds: Set<string>,
}
Expand All @@ -13,8 +13,6 @@ const props = withDefaults(defineProps<Props>(), {
searchIDs: new Set(),
});
const modelNotSelected = computed(() => !('url' in props.selectedModel));
const downloadInProgress = ref(false);
const modelRows = ref([]);
const spos = ref([]);
Expand All @@ -32,9 +30,7 @@ function getPredicates(fromId: string, toId: string) {
}).sort();
}
watch(() => props.selectedModel, (_, model) => {
const modelURL = model.url;
watch(() => props.selectedModelURL, (_, modelURL) => {
modelRows.value = [];
spos.value = [];
labels.value = {};
Expand Down Expand Up @@ -85,21 +81,21 @@ async function getModelRows(modelURL: string) {
<template>

<div class="col-8">
<div class="card my-2" v-if="modelNotSelected">
<div class="card my-2" v-if="!selectedModelURL">
<div class="card-header">
No model selected. Please search for one using the controls on the left.
</div>
</div>

<div class="card my-2" v-if="downloadInProgress">
<div class="card-header">
Download of CAM <a target="cam" :href="selectedModel.url">{{selectedModel.url}}</a> in progress ...
Download of CAM <a target="cam" :href="selectedModelURL">{{ selectedModelURL }}</a> in progress ...
</div>
</div>

<div id="edges" class="card my-2" v-if="!downloadInProgress && !modelNotSelected">
<div id="edges" class="card my-2" v-if="!downloadInProgress && selectedModelURL">
<div class="card-header">
<strong>Edges in selected CAM:</strong> <a target="cam" :href="selectedModel.url">{{selectedModel.url}}</a> (<a href="#relationships">Relationships</a>)
<strong>Edges in selected CAM:</strong> <a target="cam" :href="selectedModelURL">{{ selectedModelURL }}</a> (<a href="#relationships">Relationships</a>)
</div>
<div class="card-body">
<table class="table table-bordered mb-2">
Expand Down Expand Up @@ -142,9 +138,9 @@ async function getModelRows(modelURL: string) {

<!-- This view is hard to compress, so let's give it the whole screen -->
<div class="col-12">
<div id="relationships" class="card my-2" v-if="!downloadInProgress && !modelNotSelected">
<div id="relationships" class="card my-2" v-if="!downloadInProgress && selectedModelURL">
<div class="card-header">
<strong>Relationships in selected CAM:</strong> <a target="cam" :href="selectedModel.url">{{selectedModel.url}}</a> (<a href="#edges">Edges</a>)
<strong>Relationships in selected CAM:</strong> <a target="cam" :href="selectedModelURL">{{ selectedModelURL }}</a> (<a href="#edges">Edges</a>)
</div>
<div class="card-body">
<div class="table-responsive">
Expand Down
57 changes: 40 additions & 17 deletions frontend/src/components/SearchCAMs.vue
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ const props = withDefaults(defineProps<Props>(), {
});
// We need to track the selected model (as well as letting the caller know via changeSelectedModel()
const selectedModel = ref({});
const selectedModelURL = ref('');
// Store results.
const results = ref([]);
Expand All @@ -26,6 +26,7 @@ const subjectOrObjectCURIEsCSV = ref('');
const subjectCURIEsCSV = ref('');
const objectCURIEsCSV = ref('');
const predicateCURIEsCSV = ref('');
const modelStartsWith = ref('');
const limit = ref(100);
const errors = ref([]);
Expand All @@ -51,6 +52,7 @@ async function updateModelList() {
subjectCURIEs,
predicateCURIEs,
objectCURIEs,
modelStartsWith.value,
limit.value
);
Expand All @@ -64,14 +66,16 @@ async function updateModelList() {
}
async function searchModels(subjectOrObjectCURIEs: string[] = [], subjectCURIEs: string[] = [], predicateCURIEs: string[] = [], objectCURIEs: string[] = [], limit=100): Promise<string[]> {
async function searchModels(subjectOrObjectCURIEs: string[] = [], subjectCURIEs: string[] = [], predicateCURIEs: string[] = [], objectCURIEs: string[] = [], modelURLStartsWith: string = '', limit=100): Promise<string[]> {
/*
* Search for models using the search criteria provided. Any search criteria that is empty is ignored. Search criteria with multiple values are ORed,
* but the overall query is ANDed (i.e. a particular predicate type and a object node).
* - subjectOrObjectCURIEs: CURIEs in either the subject or object slot. Cannot be combined with subjectCURIEs or objectCURIEs.
* - subjectCURIEs: CURIEs in the subject slot.
* - predicateCURIEs: CURIEs in the predicate slot.
* - objectCURIEs: CURIEs in the object slot.
* - modelURLStartsWith: The string that the model URL should start with, case-sensitive.
* - limit: The maximum number of models to return.
*/
// Set up node selects.
Expand Down Expand Up @@ -118,10 +122,15 @@ async function searchModels(subjectOrObjectCURIEs: string[] = [], subjectCURIEs:
if(subject_or_object_selects.length > 0) {
selects.push(subject_or_object_selects.map(select => `(${select})`).join(' AND '));
}
const select_query = selects.join(' AND ');
// Deal with modelURLStartsWith.
if(modelURLStartsWith) {
selects.push(`(ANY(url IN p.xref WHERE url STARTS WITH '${modelURLStartsWith.replaceAll("'", '')}'))`);
}
// Generate query.
let query = `MATCH (s)-[p]-(o) RETURN DISTINCT p.xref LIMIT ${limit}`;
let query = `MATCH (s)-[p]-(o) RETURN DISTINCT p.xref, s, o, TYPE(p) AS pred_type LIMIT ${limit}`;
const select_query = selects.join(' AND ');
if (select_query.length > 0) {
query = `MATCH (s)-[p]-(o) WHERE ${select_query} RETURN DISTINCT p.xref, s, o, TYPE(p) AS pred_type LIMIT ${limit}`
}
Expand All @@ -147,7 +156,7 @@ async function searchModels(subjectOrObjectCURIEs: string[] = [], subjectCURIEs:
const rows = j['results'][0]['data'].flatMap(row => ({
id: urlToID(row['row'][0][0]),
url: row['row'][0][0],
urls: row['row'][0],
subj: row['row'][1],
obj: row['row'][2],
predicate: row['row'][3],
Expand Down Expand Up @@ -185,6 +194,17 @@ async function searchModels(subjectOrObjectCURIEs: string[] = [], subjectCURIEs:
<label for="objectCURIEs" class="form-label">Object CURIEs</label>
<input type="text" class="form-control" id="objectCURIEs" placeholder="CHEMBL.COMPOUND:CHEMBL158, PUBCHEM.COMPOUND:5742832" v-model="objectCURIEsCSV">
</div>
<div class="mb-3">
<label for="modelStartsWith" class="form-label">Model starts with</label>
<ul>
<li>Examples</li>
<ul class="small">
<li>GO: <code>http://model.geneontology.org/</code></li>
<li>CTD: <code>http://ctdbase.org/detail.go?type=relationship&ixnId=</code></li>
</ul>
</ul>
<input type="text" class="form-control" id="modelStartsWith" v-model="modelStartsWith">
</div>
<div class="mb-3">
<label for="limit" class="form-label">Limit</label>
<input type="text" class="form-control" id="limit" v-model="limit">
Expand All @@ -204,23 +224,26 @@ async function searchModels(subjectOrObjectCURIEs: string[] = [], subjectCURIEs:
<div class="card-header">
<strong>Search results ({{results.length}})</strong>
</div>
<div class="card-body">
<table class="table table-bordered mb-2">
<div class="card-body p-0">
<table class="table table-bordered ">
<thead>
<tr>
<th>Models</th>
<th>Edges</th>
</tr>
</thead>
<tbody>
<tr v-for="result in results" @click="selectedModel = result; changeSelectedModel(result)" :class="(selectedModel.url == result.url) ? 'table-active' : ''">
<td>{{result.id}} (<a :href="result.url" target="model-url">URL</a>, <a href="#edges">Relationships</a>, <a href="#relationships">Relationships</a>)
<ul v-if="result.subj || result.predicate || result.obj">
<li v-if="result.subj">{{result.subj.id}} ("{{result.subj.name}}")</li>
<li>{{result.predicate}}</li>
<li v-if="result.obj">{{result.obj.id}} ("{{result.obj.name}}")</li>
</ul>
</td>
</tr>
<template v-for="result in results">
<tr v-for="url in result.urls" @click="selectedModelURL = url; changeSelectedModel(url)" :class="(selectedModelURL === url) ? 'table-active' : ''">
<td>
{{urlToID(url)}} (<a :href="url" target="model-url">URL</a>)
<ul v-if="result.subj || result.predicate || result.obj">
<li v-if="result.subj">{{result.subj.id}} ("{{result.subj.name}}")</li>
<li>{{result.predicate}}</li>
<li v-if="result.obj">{{result.obj.id}} ("{{result.obj.name}}")</li>
</ul>
</td>
</tr>
</template>
</tbody>
</table>
</div>
Expand Down

0 comments on commit 2e9ec3c

Please sign in to comment.