use of org.vitrivr.cineast.core.config.ReadableQueryConfig in project cineast by vitrivr.
the class RetrievalResultCSVExporter method notify.
@Override
public void notify(List<ScoreElement> resultList, RetrievalTask task) {
ReadableQueryConfig qc = task.getConfig();
String queryIdString;
if (qc == null || qc.getQueryId() == null) {
LOGGER.error("could not determine query id, using 'null'");
queryIdString = "null";
} else {
queryIdString = qc.getQueryId().toString();
}
String filename = task.getRetriever().getClass().getSimpleName() + ".csv";
File outFolder = new File(baseFolder, queryIdString);
outFolder.mkdirs();
File out = new File(outFolder, filename);
ArrayList<String> ids = new ArrayList<>(resultList.size());
for (ScoreElement e : resultList) {
ids.add(e.getId());
}
Map<String, MediaSegmentDescriptor> segments = mediaSegmentReader.lookUpSegments(ids);
Set<String> objectIds = new HashSet<>();
for (MediaSegmentDescriptor sd : segments.values()) {
objectIds.add(sd.getObjectId());
}
Map<String, MediaObjectDescriptor> objects = mediaObjectReader.lookUpObjects(objectIds);
try (PrintWriter writer = new PrintWriter(out)) {
// header
writer.println("\"rank\", \"id\", \"score\", \"path\"");
int rank = 1;
for (ScoreElement e : resultList) {
writer.print(rank++);
writer.print(',');
writer.print(e.getId());
writer.print(',');
writer.print(e.getScore());
writer.print(',');
writer.print('"');
writer.print(objects.get(segments.get(e.getId()).getObjectId()).getPath().replace('\\', '/'));
writer.println('"');
}
writer.flush();
} catch (FileNotFoundException e) {
LOGGER.error("could not write file '{}': {}", out.getAbsolutePath(), LogHelper.getStackTrace(e));
}
}
use of org.vitrivr.cineast.core.config.ReadableQueryConfig in project cineast by vitrivr.
the class ADAMproSelector method getBatchedNearestNeighbours.
/**
* Performs a batched kNN-search with multiple vectors. That is, ADAM pro is tasked to perform the kNN search for each vector in the provided list and return results of each query.
*
* @param k The number k vectors to return per query.
* @param vectors The list of vectors to use.
* @param column The column to perform the kNN search on.
* @param distanceElementClass The class to use to create the resulting DistanceElements
* @param configs The query configurations, which may contain distance definitions or query-hints. Every feature should have its own QueryConfig object.
* @param <T> The type T of the resulting DistanceElements.
* @return List of results.
*/
@Override
public <T extends DistanceElement> List<T> getBatchedNearestNeighbours(int k, List<float[]> vectors, String column, Class<T> distanceElementClass, List<ReadableQueryConfig> configs) {
/* Check if sizes of configs and vectors array correspond. */
if (vectors.size() > configs.size()) {
throw new IllegalArgumentException("You must provide a separate QueryConfig entry for each vector - even if it is the same instance of the QueryConfig.");
}
/* Prepare list of QueryMessages. */
List<QueryMessage> queryMessages = new ArrayList<>(vectors.size());
for (int i = 0; i < vectors.size(); i++) {
float[] vector = vectors.get(i);
ReadableQueryConfig config = configs.get(i);
/* Extract hints from QueryConfig. If they're not set, then replace by DEFAULT_HINT. */
Collection<ReadableQueryConfig.Hints> hints;
if (!config.getHints().isEmpty()) {
hints = config.getHints();
} else {
hints = ADAMproMessageBuilder.DEFAULT_HINT;
}
NearestNeighbourQueryMessage nnqMessage = this.mb.buildNearestNeighbourQueryMessage(column, DataMessageConverter.convertVectorMessage(vector), k, config);
queryMessages.add(this.mb.buildQueryMessage(hints, this.fromMessage, this.mb.inList("id", config.getRelevantSegmentIds()), ADAMproMessageBuilder.DEFAULT_PROJECTION_MESSAGE, nnqMessage));
}
/* Prepare a BatchedQueryMessage. */
BatchedQueryMessage batchedQueryMessage = this.mb.buildBatchedQueryMessage(queryMessages);
ListenableFuture<BatchedQueryResultsMessage> future = this.adampro.batchedQuery(batchedQueryMessage);
BatchedQueryResultsMessage result;
try {
result = future.get();
} catch (InterruptedException | ExecutionException e) {
LOGGER.error(LogHelper.getStackTrace(e));
return new ArrayList<>(0);
}
/* Prepare empty list of results. */
List<T> results = new ArrayList<>(result.getResultsCount());
/*
* Merge results of the partial queries.
*/
for (int i = 0; i < result.getResultsCount(); i++) {
QueryResultsMessage partial = result.getResults(i);
AckMessage ack = partial.getAck();
if (ack.getCode() != AckMessage.Code.OK) {
LOGGER.error("error in getNearestNeighbours on entity {}, ({}) : {}", entityName, ack.getCode(), ack.getMessage());
continue;
}
if (partial.getResponsesCount() == 0) {
continue;
}
// only head (end-result) is important
QueryResultInfoMessage response = partial.getResponses(0);
results.addAll(handleNearestNeighbourResponse(response, k, distanceElementClass));
}
return results;
}
use of org.vitrivr.cineast.core.config.ReadableQueryConfig in project cineast by vitrivr.
the class ADAMproStreamingSelector method getBatchedNearestNeighbours.
@Override
public <T extends DistanceElement> List<T> getBatchedNearestNeighbours(int k, List<float[]> vectors, String column, Class<T> distanceElementClass, List<ReadableQueryConfig> configs) {
if (vectors == null || vectors.isEmpty()) {
return Collections.emptyList();
}
List<QueryMessage> messages = new ArrayList<>(vectors.size());
for (int i = 0; i < vectors.size(); ++i) {
float[] vector = vectors.get(i);
ReadableQueryConfig config = configs.get(i);
NearestNeighbourQueryMessage nnqMessage = mb.buildNearestNeighbourQueryMessage(column, DataMessageConverter.convertVectorMessage(vector), k, config);
QueryMessage sqMessage = this.mb.buildQueryMessage(ADAMproMessageBuilder.DEFAULT_HINT, fromMessage, this.mb.inList("id", config.getRelevantSegmentIds()), ADAMproMessageBuilder.DEFAULT_PROJECTION_MESSAGE, nnqMessage);
messages.add(sqMessage);
}
ArrayList<QueryResultsMessage> resultList = this.adampro.streamingStandardQuery(messages);
if (resultList.isEmpty()) {
return Collections.emptyList();
}
List<T> _return = new ArrayList<>(k);
for (QueryResultsMessage result : resultList) {
AckMessage ack = result.getAck();
if (ack.getCode() != AckMessage.Code.OK) {
LOGGER.error("error in getBatchedNearestNeighbours on entity {}, ({}) : {}", entityName, ack.getCode(), ack.getMessage());
return new ArrayList<>(0);
}
if (result.getResponsesCount() == 0) {
return new ArrayList<>(0);
}
// only head (end-result) is important
QueryResultInfoMessage response = result.getResponses(0);
_return.addAll(handleNearestNeighbourResponse(response, k, distanceElementClass));
}
return _return;
}
use of org.vitrivr.cineast.core.config.ReadableQueryConfig in project cineast by vitrivr.
the class AbstractFeatureModule method getSimilar.
/**
* Helper function to retrieve elements close to a generic primitive type
*/
protected List<ScoreElement> getSimilar(PrimitiveTypeProvider queryProvider, ReadableQueryConfig qc) {
ReadableQueryConfig qcc = setQueryConfig(qc);
List<SegmentDistanceElement> distances = this.selector.getNearestNeighboursGeneric(qc.getResultsPerModule(), queryProvider, FEATURE_COLUMN_QUALIFIER, SegmentDistanceElement.class, qcc);
CorrespondenceFunction function = qcc.getCorrespondenceFunction().orElse(correspondence);
return DistanceElement.toScore(distances, function);
}
use of org.vitrivr.cineast.core.config.ReadableQueryConfig in project cineast by vitrivr.
the class MetadataFeatureModule method getSimilar.
protected List<ScoreElement> getSimilar(float[] feature, ReadableQueryConfig rqc) {
QueryConfig qc = QueryConfig.clone(rqc).setDistanceIfEmpty(this.defaultDistance());
List<SegmentDistanceElement> sDistances = new ArrayList<>();
List<ObjectDistanceElement> oDistances = new ArrayList<>();
CorrespondenceFunction correspondence = qc.getCorrespondenceFunction().orElse(this.defaultCorrespondence());
if (this.segmentRetrievalScope) {
sDistances = this.dbSelector.getNearestNeighboursGeneric(rqc.getResultsPerModule(), feature, FEATURE_COLUMN_NAME, SegmentDistanceElement.class, qc);
return DistanceElement.toScore(sDistances, correspondence);
} else {
oDistances = this.dbSelector.getNearestNeighboursGeneric(rqc.getResultsPerModule(), feature, FEATURE_COLUMN_NAME, ObjectDistanceElement.class, qc);
return DistanceElement.toScore(oDistances, correspondence);
}
}
Aggregations