From c5a48a048d5fc0400389c46b963c483e24379438 Mon Sep 17 00:00:00 2001 From: silvanheller Date: Fri, 11 Mar 2022 12:18:50 +0100 Subject: [PATCH 1/9] setting queryid in most places --- .../vitrivr/cineast/core/db/DBSelector.java | 6 +-- .../cineast/core/db/ImporterSelector.java | 2 +- .../vitrivr/cineast/core/db/NoDBSelector.java | 2 +- .../core/db/adampro/ADAMproSelector.java | 2 +- .../db/adampro/ADAMproStreamingSelector.java | 2 +- .../db/cottontaildb/CottontailSelector.java | 51 ++++++++++--------- .../core/db/polypheny/PolyphenySelector.java | 4 +- .../cineast/core/features/CLIPText.java | 2 +- .../abstracts/AbstractFeatureModule.java | 2 +- .../abstracts/MetadataFeatureModule.java | 2 +- .../abstracts/MotionHistogramCalculator.java | 2 +- .../abstracts/StagedFeatureModule.java | 2 +- .../cineast/core/util/QueryIDGenerator.java | 6 ++- .../cineast/core/db/DBIntegrationTest.java | 6 +-- 14 files changed, 46 insertions(+), 45 deletions(-) diff --git a/cineast-core/src/main/java/org/vitrivr/cineast/core/db/DBSelector.java b/cineast-core/src/main/java/org/vitrivr/cineast/core/db/DBSelector.java index 852441719..d78f40751 100644 --- a/cineast-core/src/main/java/org/vitrivr/cineast/core/db/DBSelector.java +++ b/cineast-core/src/main/java/org/vitrivr/cineast/core/db/DBSelector.java @@ -88,14 +88,14 @@ List> getNearestNeighbourRows(int k, float[] /** * SELECT 'vectorname' from entity where 'fieldname' = 'value' */ - List getFeatureVectors(String fieldName, PrimitiveTypeProvider value, String vectorName); + List getFeatureVectors(String fieldName, PrimitiveTypeProvider value, String vectorName, ReadableQueryConfig queryConfig); /** * for legacy support, takes the float[] method by default */ default List getFeatureVectorsGeneric(String fieldName, PrimitiveTypeProvider value, - String vectorName) { - return getFeatureVectors(fieldName, value, vectorName).stream().map(FloatArrayTypeProvider::new) + String vectorName, ReadableQueryConfig qc) { + return getFeatureVectors(fieldName, value, vectorName, qc).stream().map(FloatArrayTypeProvider::new) .collect(Collectors.toList()); } diff --git a/cineast-core/src/main/java/org/vitrivr/cineast/core/db/ImporterSelector.java b/cineast-core/src/main/java/org/vitrivr/cineast/core/db/ImporterSelector.java index c9e3a25cd..2138c6f2b 100644 --- a/cineast-core/src/main/java/org/vitrivr/cineast/core/db/ImporterSelector.java +++ b/cineast-core/src/main/java/org/vitrivr/cineast/core/db/ImporterSelector.java @@ -174,7 +174,7 @@ public List> getNearestNeighbourRows(int k, f } @Override - public List getFeatureVectors(String fieldName, PrimitiveTypeProvider value, String vectorName) { + public List getFeatureVectors(String fieldName, PrimitiveTypeProvider value, String vectorName, ReadableQueryConfig queryConfig) { ArrayList _return = new ArrayList<>(1); if (value == null || value.getString().isEmpty()) { diff --git a/cineast-core/src/main/java/org/vitrivr/cineast/core/db/NoDBSelector.java b/cineast-core/src/main/java/org/vitrivr/cineast/core/db/NoDBSelector.java index 486e733ba..7cc568a70 100644 --- a/cineast-core/src/main/java/org/vitrivr/cineast/core/db/NoDBSelector.java +++ b/cineast-core/src/main/java/org/vitrivr/cineast/core/db/NoDBSelector.java @@ -32,7 +32,7 @@ public List> getNearestNeighbourRows(int k, f } @Override - public List getFeatureVectors(String fieldName, PrimitiveTypeProvider value, String vectorName) { + public List getFeatureVectors(String fieldName, PrimitiveTypeProvider value, String vectorName, ReadableQueryConfig queryConfig) { return new ArrayList<>(0); } diff --git a/cineast-core/src/main/java/org/vitrivr/cineast/core/db/adampro/ADAMproSelector.java b/cineast-core/src/main/java/org/vitrivr/cineast/core/db/adampro/ADAMproSelector.java index df9188293..79f0d1ac0 100644 --- a/cineast-core/src/main/java/org/vitrivr/cineast/core/db/adampro/ADAMproSelector.java +++ b/cineast-core/src/main/java/org/vitrivr/cineast/core/db/adampro/ADAMproSelector.java @@ -47,7 +47,7 @@ public ADAMproSelector(ADAMproWrapper wrapper) { } @Override - public List getFeatureVectors(String fieldName, PrimitiveTypeProvider value, String vectorName) { + public List getFeatureVectors(String fieldName, PrimitiveTypeProvider value, String vectorName, ReadableQueryConfig queryConfig) { QueryMessage qbqm = this.mb.buildQueryMessage(ADAMproMessageBuilder.DEFAULT_HINT, this.fromMessage, this.mb.buildBooleanQueryMessage(this.mb.buildWhereMessage(fieldName, value.getString())), null, null); ListenableFuture f = this.adampro.booleanQuery(qbqm); diff --git a/cineast-core/src/main/java/org/vitrivr/cineast/core/db/adampro/ADAMproStreamingSelector.java b/cineast-core/src/main/java/org/vitrivr/cineast/core/db/adampro/ADAMproStreamingSelector.java index af6cdb2ce..4c2e53e88 100644 --- a/cineast-core/src/main/java/org/vitrivr/cineast/core/db/adampro/ADAMproStreamingSelector.java +++ b/cineast-core/src/main/java/org/vitrivr/cineast/core/db/adampro/ADAMproStreamingSelector.java @@ -205,7 +205,7 @@ public List> getNearestNeighbourRows(int k, f } @Override - public List getFeatureVectors(String fieldName, PrimitiveTypeProvider value, String vectorName) { + public List getFeatureVectors(String fieldName, PrimitiveTypeProvider value, String vectorName, ReadableQueryConfig queryConfig) { QueryMessage qbqm = this.mb.buildQueryMessage(ADAMproMessageBuilder.DEFAULT_HINT, this.fromMessage, this.mb.buildBooleanQueryMessage(this.mb.buildWhereMessage(fieldName, value.getString())), null, null); ArrayList resultList = this.adampro.streamingStandardQuery(qbqm); diff --git a/cineast-core/src/main/java/org/vitrivr/cineast/core/db/cottontaildb/CottontailSelector.java b/cineast-core/src/main/java/org/vitrivr/cineast/core/db/cottontaildb/CottontailSelector.java index 9ad4df271..43424a253 100644 --- a/cineast-core/src/main/java/org/vitrivr/cineast/core/db/cottontaildb/CottontailSelector.java +++ b/cineast-core/src/main/java/org/vitrivr/cineast/core/db/cottontaildb/CottontailSelector.java @@ -28,6 +28,7 @@ import org.vitrivr.cineast.core.db.DBSelector; import org.vitrivr.cineast.core.db.RelationalOperator; import org.vitrivr.cineast.core.db.dao.MetadataAccessSpecification; +import org.vitrivr.cineast.core.util.QueryIDGenerator; import org.vitrivr.cottontail.client.iterators.Tuple; import org.vitrivr.cottontail.client.iterators.TupleIterator; import org.vitrivr.cottontail.client.language.basics.Direction; @@ -95,8 +96,8 @@ public List> getNearestNeighbourRows(int k, f } @Override - public List getFeatureVectors(String fieldName, PrimitiveTypeProvider value, String vectorName) { - final Query query = new Query(this.fqn).select(vectorName, null).where(new Literal(fieldName, "==", value.toObject())); + public List getFeatureVectors(String fieldName, PrimitiveTypeProvider value, String vectorName, ReadableQueryConfig queryConfig) { + final Query query = new Query(this.fqn).select(vectorName, null).where(new Literal(fieldName, "==", value.toObject())).queryId(queryConfig.getQueryId().toString()); try { final TupleIterator results = this.cottontail.client.query(query); final List _return = new LinkedList<>(); @@ -112,8 +113,8 @@ public List getFeatureVectors(String fieldName, PrimitiveTypeProvider v } @Override - public List getFeatureVectorsGeneric(String fieldName, PrimitiveTypeProvider value, String vectorName) { - final Query query = new Query(this.fqn).select(vectorName, null).where(new Literal(fieldName, "==", value.toObject())); + public List getFeatureVectorsGeneric(String fieldName, PrimitiveTypeProvider value, String vectorName, ReadableQueryConfig qc) { + final Query query = new Query(this.fqn).select(vectorName, null).where(new Literal(fieldName, "==", value.toObject())).queryId(qc.getQueryId().toString()); try { return toSingleCol(this.cottontail.client.query(query), vectorName); } catch (StatusRuntimeException e) { @@ -125,32 +126,25 @@ public List getFeatureVectorsGeneric(String fieldName, Pr @Override public List> getRows(String fieldName, Iterable values) { final Object[] mapped = StreamSupport.stream(values.spliterator(), false).map(PrimitiveTypeProvider::toObject).toArray(); - final Query query = new Query(this.fqn).select("*", null).where(new Literal(fieldName, "IN", mapped)); - try { - return processResults(this.cottontail.client.query(query)); - } catch (StatusRuntimeException e) { - LOGGER.warn("Error occurred during query execution in getRows(): {}", e.getMessage()); - return new ArrayList<>(0); - } + return getRowsHelper(fieldName, "IN", mapped, "get-rows-in-iterable"); } @Override public List> getRows(String fieldName, List values) { final Object[] mapped = values.toArray(); - final Query query = new Query(this.fqn).select("*", null).where(new Literal(fieldName, "IN", mapped)); - try { - return processResults(this.cottontail.client.query(query)); - } catch (StatusRuntimeException e) { - LOGGER.warn("Error occurred during query execution in getRows(): {}", e.getMessage()); - return new ArrayList<>(0); - } + return getRowsHelper(fieldName, "IN", mapped, "get-rows-stringlist"); } @Override public List> getRows(String fieldName, RelationalOperator operator, Iterable values) { final Object[] mapped = StreamSupport.stream(values.spliterator(), false).map(PrimitiveTypeProvider::toObject).toArray(); final String op = toOperator(operator); - final Query query = new Query(this.fqn).select("*", null).where(new Literal(fieldName, op, mapped)); + return getRowsHelper(fieldName, op, mapped, "get-rows-" + op + "-iterable"); + } + + private List> getRowsHelper(String fieldName, String op, Object[] mapped, String qIdInfix) { + String queryId = QueryIDGenerator.generateQueryID(qIdInfix); + final Query query = new Query(this.fqn).select("*", null).where(new Literal(fieldName, op, mapped)).queryId(queryId); try { return processResults(this.cottontail.client.query(query)); } catch (StatusRuntimeException e) { @@ -172,6 +166,7 @@ public List> getFulltextRows(int rows, String final Set relevant = queryConfig.getRelevantSegmentIds(); final Literal segmentIds = new Literal(GENERIC_ID_COLUMN_QUALIFIER, "IN", relevant.toArray()); query.where(new And(segmentIds, new Literal(DB_DISTANCE_VALUE_QUALIFIER, ">", 0.0))); + query.queryId(queryConfig.getQueryId().toString()); } else { query.where(new Literal(DB_DISTANCE_VALUE_QUALIFIER, ">", 0.0)); } @@ -188,6 +183,9 @@ public List> getFulltextRows(int rows, String public List> getRowsAND(List>> conditions, String identifier, List projection, ReadableQueryConfig qc) { /* Prepare plain query. */ final Query query = new Query(this.fqn); + if (qc != null) { + query.queryId(qc.getQueryId().toString()); + } if (projection.isEmpty()) { query.select("*", null); } else { @@ -276,7 +274,7 @@ public Optional generateQueryFromMetadataSpec(List getAll(String column) { - final Query query = new Query(this.fqn).select(column, null); + final Query query = new Query(this.fqn).select(column, null).queryId(QueryIDGenerator.generateQueryID("all-" + column)); try { return toSingleCol(this.cottontail.client.query(query), column); } catch (StatusRuntimeException e) { @@ -288,6 +286,7 @@ public List getAll(String column) { @Override public List> getAll(List columns, int limit) { final Query query = new Query(this.fqn); + query.queryId(QueryIDGenerator.generateQueryID("all-cols-limit-" + limit)); for (String c : columns) { query.select(c, null); } @@ -304,7 +303,8 @@ public List> getAll(List columns, int @Override public List getUniqueValues(String column) { - final Query query = new Query(this.fqn).distinct(column, null); + final Query query = new Query(this.fqn).distinct(column, null). + queryId(QueryIDGenerator.generateQueryID("unique-" + column)); try { return toSingleCol(this.cottontail.client.query(query), column); } catch (StatusRuntimeException e) { @@ -314,7 +314,8 @@ public List getUniqueValues(String column) { } public Map countDistinctValues(String column) { - final Query query = new Query(this.fqn).select(column, null); + final Query query = new Query(this.fqn).select(column, null) + .queryId(QueryIDGenerator.generateQueryID("count-distinct-" + column)); final Map count = new HashMap<>(); try { final TupleIterator results = this.cottontail.client.query(query); @@ -331,7 +332,8 @@ public Map countDistinctValues(String column) { @Override public List> getAll() { - final Query query = new Query(this.fqn).select("*", null); + final Query query = new Query(this.fqn).select("*", null) + .queryId("get-all"); try { return processResults(this.cottontail.client.query(query)); } catch (StatusRuntimeException e) { @@ -394,7 +396,8 @@ private Query knn(int k, float[] vector, String column, ReadableQueryConfig conf final Query query = new Query(this.fqn) .distance(column, vector, distance, DB_DISTANCE_VALUE_QUALIFIER) .order(DB_DISTANCE_VALUE_QUALIFIER, Direction.ASC) - .limit(k); + .limit(k) + .queryId(config.getQueryId().toString()); for (String s : select) { query.select(s, null); diff --git a/cineast-core/src/main/java/org/vitrivr/cineast/core/db/polypheny/PolyphenySelector.java b/cineast-core/src/main/java/org/vitrivr/cineast/core/db/polypheny/PolyphenySelector.java index c0138e031..84039032a 100644 --- a/cineast-core/src/main/java/org/vitrivr/cineast/core/db/polypheny/PolyphenySelector.java +++ b/cineast-core/src/main/java/org/vitrivr/cineast/core/db/polypheny/PolyphenySelector.java @@ -8,12 +8,10 @@ import java.sql.SQLException; import java.sql.Statement; import java.util.ArrayList; -import java.util.Collections; import java.util.HashMap; import java.util.LinkedList; import java.util.List; import java.util.Map; -import java.util.Set; import java.util.concurrent.TimeUnit; import java.util.stream.Collectors; import java.util.stream.StreamSupport; @@ -111,7 +109,7 @@ public List> getNearestNeighbourRows(int k, f } @Override - public List getFeatureVectors(String fieldName, PrimitiveTypeProvider value, String vectorName) { + public List getFeatureVectors(String fieldName, PrimitiveTypeProvider value, String vectorName, ReadableQueryConfig queryConfig) { try (final PreparedStatement statement = this.prepareStatement(fieldName, RelationalOperator.EQ, List.of(value))) { /* Execute query and return results. */ final List _return = new LinkedList<>(); diff --git a/cineast-core/src/main/java/org/vitrivr/cineast/core/features/CLIPText.java b/cineast-core/src/main/java/org/vitrivr/cineast/core/features/CLIPText.java index 50ddae2e5..44d134b1d 100644 --- a/cineast-core/src/main/java/org/vitrivr/cineast/core/features/CLIPText.java +++ b/cineast-core/src/main/java/org/vitrivr/cineast/core/features/CLIPText.java @@ -124,7 +124,7 @@ private float[] embedText(String text) { @Override public List getSimilar(String segmentId, ReadableQueryConfig qc) { - List list = this.selector.getFeatureVectorsGeneric(GENERIC_ID_COLUMN_QUALIFIER, new StringTypeProvider(segmentId), FEATURE_COLUMN_QUALIFIER); + List list = this.selector.getFeatureVectorsGeneric(GENERIC_ID_COLUMN_QUALIFIER, new StringTypeProvider(segmentId), FEATURE_COLUMN_QUALIFIER, qc); if (list.isEmpty()) { LOGGER.warn("No feature vector for shotId {} found, returning empty result-list", segmentId); return Collections.emptyList(); diff --git a/cineast-core/src/main/java/org/vitrivr/cineast/core/features/abstracts/AbstractFeatureModule.java b/cineast-core/src/main/java/org/vitrivr/cineast/core/features/abstracts/AbstractFeatureModule.java index 7938b310a..f9deb37b4 100644 --- a/cineast-core/src/main/java/org/vitrivr/cineast/core/features/abstracts/AbstractFeatureModule.java +++ b/cineast-core/src/main/java/org/vitrivr/cineast/core/features/abstracts/AbstractFeatureModule.java @@ -94,7 +94,7 @@ protected ReadableQueryConfig setQueryConfig(ReadableQueryConfig qc) { @Override public List getSimilar(String segmentId, ReadableQueryConfig qc) { - List list = this.selector.getFeatureVectorsGeneric(GENERIC_ID_COLUMN_QUALIFIER, new StringTypeProvider(segmentId), FEATURE_COLUMN_QUALIFIER); + List list = this.selector.getFeatureVectorsGeneric(GENERIC_ID_COLUMN_QUALIFIER, new StringTypeProvider(segmentId), FEATURE_COLUMN_QUALIFIER, qc); if (list.isEmpty()) { LOGGER.warn("No feature vector for shotId {} found, returning empty result-list", segmentId); return new ArrayList<>(0); diff --git a/cineast-core/src/main/java/org/vitrivr/cineast/core/features/abstracts/MetadataFeatureModule.java b/cineast-core/src/main/java/org/vitrivr/cineast/core/features/abstracts/MetadataFeatureModule.java index 81657704a..ce60fc3d1 100644 --- a/cineast-core/src/main/java/org/vitrivr/cineast/core/features/abstracts/MetadataFeatureModule.java +++ b/cineast-core/src/main/java/org/vitrivr/cineast/core/features/abstracts/MetadataFeatureModule.java @@ -170,7 +170,7 @@ public List getSimilar(SegmentContainer sc, ReadableQueryConfig qc public List getSimilar(String segmentId, ReadableQueryConfig rqc) { return this.mediaSegmentReader.lookUpSegment(segmentId) .map(MediaSegmentDescriptor::getObjectId) - .map(objId -> this.dbSelector.getFeatureVectors(ID_COLUMN_NAME, new StringTypeProvider(objId), FEATURE_COLUMN_NAME)) + .map(objId -> this.dbSelector.getFeatureVectors(ID_COLUMN_NAME, new StringTypeProvider(objId), FEATURE_COLUMN_NAME, rqc)) .flatMap(features -> features.stream().findFirst()) // Feature vectors are unique per id .map(feature -> this.getSimilar(feature, rqc)) .orElse(Collections.emptyList()); diff --git a/cineast-core/src/main/java/org/vitrivr/cineast/core/features/abstracts/MotionHistogramCalculator.java b/cineast-core/src/main/java/org/vitrivr/cineast/core/features/abstracts/MotionHistogramCalculator.java index db52b3d4d..c6a1e1bf0 100644 --- a/cineast-core/src/main/java/org/vitrivr/cineast/core/features/abstracts/MotionHistogramCalculator.java +++ b/cineast-core/src/main/java/org/vitrivr/cineast/core/features/abstracts/MotionHistogramCalculator.java @@ -128,7 +128,7 @@ protected List getSimilar(float[] vector, ReadableQueryConfig qc) @Override public List getSimilar(String segmentId, ReadableQueryConfig qc) { - List list = this.selector.getFeatureVectors(GENERIC_ID_COLUMN_QUALIFIER, new StringTypeProvider(segmentId), this.fieldName); + List list = this.selector.getFeatureVectors(GENERIC_ID_COLUMN_QUALIFIER, new StringTypeProvider(segmentId), this.fieldName, qc); if (list.isEmpty()) { return new ArrayList<>(1); } diff --git a/cineast-core/src/main/java/org/vitrivr/cineast/core/features/abstracts/StagedFeatureModule.java b/cineast-core/src/main/java/org/vitrivr/cineast/core/features/abstracts/StagedFeatureModule.java index ec6abd7e4..16fb27a90 100644 --- a/cineast-core/src/main/java/org/vitrivr/cineast/core/features/abstracts/StagedFeatureModule.java +++ b/cineast-core/src/main/java/org/vitrivr/cineast/core/features/abstracts/StagedFeatureModule.java @@ -95,7 +95,7 @@ public List getSimilar(String segmentId, ReadableQueryConfig qc) { QueryConfig qcc = this.defaultQueryConfig(qc); /* Lookup features. */ - List features = this.selector.getFeatureVectors(GENERIC_ID_COLUMN_QUALIFIER, new StringTypeProvider(segmentId), FEATURE_COLUMN_QUALIFIER); + List features = this.selector.getFeatureVectors(GENERIC_ID_COLUMN_QUALIFIER, new StringTypeProvider(segmentId), FEATURE_COLUMN_QUALIFIER, qc); if (features.isEmpty()) { LOGGER.warn("No features could be fetched for the provided segmentId '{}'. Aborting query execution...", segmentId); return new ArrayList<>(0); diff --git a/cineast-core/src/main/java/org/vitrivr/cineast/core/util/QueryIDGenerator.java b/cineast-core/src/main/java/org/vitrivr/cineast/core/util/QueryIDGenerator.java index 94b639f66..060b9644e 100644 --- a/cineast-core/src/main/java/org/vitrivr/cineast/core/util/QueryIDGenerator.java +++ b/cineast-core/src/main/java/org/vitrivr/cineast/core/util/QueryIDGenerator.java @@ -5,6 +5,10 @@ public class QueryIDGenerator { public static String generateQueryID() { - return "q-" + RandomStringUtils.randomNumeric(3); + return generateQueryID(""); + } + + public static String generateQueryID(String infix) { + return "q-" + infix + RandomStringUtils.randomNumeric(3); } } diff --git a/cineast-core/src/test/java/org/vitrivr/cineast/core/db/DBIntegrationTest.java b/cineast-core/src/test/java/org/vitrivr/cineast/core/db/DBIntegrationTest.java index 50ca3a469..080835836 100644 --- a/cineast-core/src/test/java/org/vitrivr/cineast/core/db/DBIntegrationTest.java +++ b/cineast-core/src/test/java/org/vitrivr/cineast/core/db/DBIntegrationTest.java @@ -6,7 +6,6 @@ import com.google.gson.Gson; import java.util.ArrayList; import java.util.Arrays; -import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.concurrent.atomic.AtomicBoolean; @@ -29,11 +28,8 @@ import org.vitrivr.cineast.core.config.ReadableQueryConfig; import org.vitrivr.cineast.core.config.ReadableQueryConfig.Distance; import org.vitrivr.cineast.core.data.distance.SegmentDistanceElement; -import org.vitrivr.cineast.core.data.providers.primitive.IntTypeProvider; -import org.vitrivr.cineast.core.data.providers.primitive.LongTypeProvider; import org.vitrivr.cineast.core.data.providers.primitive.PrimitiveTypeProvider; import org.vitrivr.cineast.core.data.providers.primitive.StringTypeProvider; -import org.vitrivr.cineast.core.db.polypheny.PolyphenyWrapper; import org.vitrivr.cineast.core.db.setup.AttributeDefinition; import org.vitrivr.cineast.core.db.setup.AttributeDefinition.AttributeType; import org.vitrivr.cineast.core.db.setup.EntityCreator; @@ -225,7 +221,7 @@ void entriesExistById() { @DisplayName("get multiple feature vectors") void getFeatureVectors() { this.selector.open(testVectorTableName); - final List vectors = this.selector.getFeatureVectorsGeneric(ID_COL_NAME, new StringTypeProvider("0"), FEATURE_VECTOR_COL_NAME); + final List vectors = this.selector.getFeatureVectorsGeneric(ID_COL_NAME, new StringTypeProvider("0"), FEATURE_VECTOR_COL_NAME, queryConfig); Assertions.assertTrue((Arrays.equals(PrimitiveTypeProvider.getSafeFloatArray(vectors.get(0)), new float[]{0, 0, 0}) | Arrays.equals(PrimitiveTypeProvider.getSafeFloatArray(vectors.get(0)), new float[]{0, 1, 0}))); Assertions.assertTrue((Arrays.equals(PrimitiveTypeProvider.getSafeFloatArray(vectors.get(1)), new float[]{0, 0, 0}) | Arrays.equals(PrimitiveTypeProvider.getSafeFloatArray(vectors.get(1)), new float[]{0, 1, 0}))); } From 1f55d6c901c7a669e2beccbdf2cf3ac9433d25bb Mon Sep 17 00:00:00 2001 From: Silvan Heller Date: Sun, 13 Mar 2022 13:01:37 +0100 Subject: [PATCH 2/9] cleanup of import code, removing adampro grpc and adding needed libraries --- .travis.yml | 22 - build.gradle | 4 + cineast-api/build.gradle | 2 + .../api/grpc/util/QueryContainerUtil.java | 11 - .../api/messages/query/QueryTermType.java | 2 - .../queries/TemporalQueryMessageHandler.java | 5 +- cineast-core/build.gradle | 11 +- .../core/data/DefaultValueHashMap.java | 49 -- .../cineast/core/data/DynamicGrid.java | 129 ----- .../org/vitrivr/cineast/core/data/Grid.java | 27 -- .../vitrivr/cineast/core/data/Position.java | 77 --- .../cineast/core/data/QuerySubTitleItem.java | 32 -- .../cineast/core/data/UniqueElementGrid.java | 78 --- .../containers/MotionQueryTermContainer.java | 95 ---- .../cineast/core/db/DataMessageConverter.java | 231 --------- .../idgenerator/UniqueObjectIdGenerator.java | 4 +- .../features/CollectionBooleanRetriever.java | 30 ++ .../DailyCollectionBooleanRetriever.java | 11 - .../features/DailyRangeBooleanRetriever.java | 10 - .../core/features/MotionHistogram.java | 59 --- .../features/MotionHistogramBackground.java | 61 --- .../cineast/core/features/OCRSearch.java | 8 +- .../core/features/SubDivMotionHistogram2.java | 54 --- .../core/features/SubDivMotionHistogram3.java | 54 --- .../core/features/SubDivMotionHistogram4.java | 55 --- .../core/features/SubDivMotionHistogram5.java | 54 --- .../SubDivMotionHistogramBackground2.java | 54 --- .../SubDivMotionHistogramBackground3.java | 53 -- .../SubDivMotionHistogramBackground4.java | 53 -- .../SubDivMotionHistogramBackground5.java | 54 --- .../core/features/SubDivMotionSum2.java | 27 -- .../core/features/SubDivMotionSum3.java | 27 -- .../core/features/SubDivMotionSum4.java | 28 -- .../core/features/SubDivMotionSum5.java | 27 -- .../features/SubDivMotionSumBackground2.java | 26 - .../features/SubDivMotionSumBackground3.java | 27 -- .../features/SubDivMotionSumBackground4.java | 28 -- .../features/SubDivMotionSumBackground5.java | 27 -- .../WSDMTICollectionBooleanRetriever.java | 11 - .../abstracts/MotionHistogramCalculator.java | 159 ------ .../abstracts/SubDivMotionHistogram.java | 50 -- .../exporter/MotionFrameExporter.java | 122 ----- .../exporter/MotionHistoryImageExporter.java | 89 ---- .../retriever/CollectionBooleanRetriever.java | 33 -- .../importer/TupleInsertMessageImporter.java | 57 --- .../AbstractTemporalScoringAlgorithm.java | 5 +- .../cineast/core/util/MotionHistoryImage.java | 98 ---- .../core/util/RandomStringGenerator.java | 83 ---- .../cineast/core/util/TagsPerSegment.java | 43 -- .../util/{ => ocr}/HungarianAlgorithm.java | 2 +- .../core/util/{ => ocr}/MultiTracker.java | 2 +- .../util/{ => ocr}/NeedlemanWunschMerge.java | 2 +- .../{ => ocr}/ThreadLocalObjectCache.java | 2 +- .../core/db/DBBooleanIntegrationTest.java | 37 +- .../PolyphenyBooleanIntegrationTest.java | 82 ++-- .../cineast/standalone/cli/ImportCommand.java | 198 +++----- .../standalone/cli/RetrieveCommand.java | 7 - .../standalone/cli/TextRetrievalCommand.java | 1 - .../standalone/config/ExplorativeConfig.java | 70 --- .../config/RetrievalRuntimeConfig.java | 21 - .../evaluation/EvaluationConfig.java | 134 ----- .../evaluation/EvaluationException.java | 18 - .../evaluation/EvaluationResult.java | 164 ------- .../evaluation/EvaluationRuntime.java | 246 ---------- .../standalone/evaluation/Groundtruth.java | 134 ----- .../importer/PlainTextImporter.java | 63 --- .../importer/TagsFulltextImporter.java | 66 --- .../standalone/importer/VbsMetaImporter.java | 69 --- .../handlers/AsrDataImportHandler.java | 26 - .../handlers/OcrDataImportHandler.java | 30 -- .../handlers/ProtoDataImportHandler.java | 42 -- .../lsc2020/CaptionImportHandler.java | 28 -- .../importer/lsc2020/CaptionImporter.java | 72 --- .../importer/lsc2020/JsonTagReader.java | 77 --- .../lsc2020/LSCAllTagsImportHandler.java | 67 --- .../importer/lsc2020/LSCUtilities.java | 457 ------------------ .../importer/lsc2020/MetaImportHandler.java | 46 -- .../importer/lsc2020/MetaImporter.java | 204 -------- .../lsc2020/MyscealTagImportHandler.java | 26 - .../importer/lsc2020/MyscealTagImporter.java | 112 ----- .../importer/lsc2020/OCRImportHandler.java | 38 -- .../importer/lsc2020/OCRImporter.java | 60 --- .../lsc2020/ProcessingMetaImportHandler.java | 133 ----- .../lsc2020/ProcessingMetaImporter.java | 340 ------------- .../lsc2020/SpatialImportHandler.java | 35 -- .../importer/lsc2020/SpatialImporter.java | 106 ---- .../lsc2020/TemporalImportHandler.java | 42 -- .../importer/lsc2020/TemporalImporter.java | 82 ---- .../VisualConceptTagImportHandler.java | 30 -- .../lsc2020/VisualConceptTagImporter.java | 198 -------- .../vbs2019/AudioTranscriptImportHandler.java | 36 -- .../vbs2019/AudioTranscriptionImporter.java | 85 ---- .../vbs2019/CaptionTextImportHandler.java | 36 -- .../importer/vbs2019/CaptionTextImporter.java | 84 ---- .../vbs2019/GoogleVisionImportHandler.java | 47 -- .../vbs2019/GoogleVisionImporter.java | 248 ---------- .../importer/vbs2019/MLTFeatureImporter.java | 72 --- .../vbs2019/ObjectMetadataImportHandler.java | 36 -- .../vbs2019/ObjectMetadataImporter.java | 130 ----- .../importer/vbs2019/TagImportHandler.java | 32 -- .../importer/vbs2019/TagImporter.java | 100 ---- .../vbs2019/gvision/GoogleVisionCategory.java | 12 - .../gvision/GoogleVisionLabelTuple.java | 20 - .../vbs2019/gvision/GoogleVisionOCRTuple.java | 22 - .../vbs2019/gvision/GoogleVisionTuple.java | 49 -- .../vbs2019/gvision/GoogleVisionWebTuple.java | 20 - .../v3c1analysis/ColorlabelImportHandler.java | 36 -- .../v3c1analysis/ColorlabelImporter.java | 61 --- .../v3c1analysis/SequenceIdLookupService.java | 45 -- .../listener/RetrievalResultCSVExporter.java | 90 ---- .../listener/RetrievalResultListener.java | 21 - .../runtime/ContinuousQueryDispatcher.java | 19 - .../util/ContinuousRetrievalLogic.java | 9 - cineast.json | 6 - 114 files changed, 169 insertions(+), 7072 deletions(-) delete mode 100644 .travis.yml delete mode 100644 cineast-core/src/main/java/org/vitrivr/cineast/core/data/DefaultValueHashMap.java delete mode 100644 cineast-core/src/main/java/org/vitrivr/cineast/core/data/DynamicGrid.java delete mode 100644 cineast-core/src/main/java/org/vitrivr/cineast/core/data/Grid.java delete mode 100644 cineast-core/src/main/java/org/vitrivr/cineast/core/data/Position.java delete mode 100644 cineast-core/src/main/java/org/vitrivr/cineast/core/data/QuerySubTitleItem.java delete mode 100644 cineast-core/src/main/java/org/vitrivr/cineast/core/data/UniqueElementGrid.java delete mode 100644 cineast-core/src/main/java/org/vitrivr/cineast/core/data/query/containers/MotionQueryTermContainer.java delete mode 100644 cineast-core/src/main/java/org/vitrivr/cineast/core/db/DataMessageConverter.java create mode 100644 cineast-core/src/main/java/org/vitrivr/cineast/core/features/CollectionBooleanRetriever.java delete mode 100644 cineast-core/src/main/java/org/vitrivr/cineast/core/features/DailyCollectionBooleanRetriever.java delete mode 100644 cineast-core/src/main/java/org/vitrivr/cineast/core/features/DailyRangeBooleanRetriever.java delete mode 100644 cineast-core/src/main/java/org/vitrivr/cineast/core/features/MotionHistogram.java delete mode 100644 cineast-core/src/main/java/org/vitrivr/cineast/core/features/MotionHistogramBackground.java delete mode 100644 cineast-core/src/main/java/org/vitrivr/cineast/core/features/SubDivMotionHistogram2.java delete mode 100644 cineast-core/src/main/java/org/vitrivr/cineast/core/features/SubDivMotionHistogram3.java delete mode 100644 cineast-core/src/main/java/org/vitrivr/cineast/core/features/SubDivMotionHistogram4.java delete mode 100644 cineast-core/src/main/java/org/vitrivr/cineast/core/features/SubDivMotionHistogram5.java delete mode 100644 cineast-core/src/main/java/org/vitrivr/cineast/core/features/SubDivMotionHistogramBackground2.java delete mode 100644 cineast-core/src/main/java/org/vitrivr/cineast/core/features/SubDivMotionHistogramBackground3.java delete mode 100644 cineast-core/src/main/java/org/vitrivr/cineast/core/features/SubDivMotionHistogramBackground4.java delete mode 100644 cineast-core/src/main/java/org/vitrivr/cineast/core/features/SubDivMotionHistogramBackground5.java delete mode 100644 cineast-core/src/main/java/org/vitrivr/cineast/core/features/SubDivMotionSum2.java delete mode 100644 cineast-core/src/main/java/org/vitrivr/cineast/core/features/SubDivMotionSum3.java delete mode 100644 cineast-core/src/main/java/org/vitrivr/cineast/core/features/SubDivMotionSum4.java delete mode 100644 cineast-core/src/main/java/org/vitrivr/cineast/core/features/SubDivMotionSum5.java delete mode 100644 cineast-core/src/main/java/org/vitrivr/cineast/core/features/SubDivMotionSumBackground2.java delete mode 100644 cineast-core/src/main/java/org/vitrivr/cineast/core/features/SubDivMotionSumBackground3.java delete mode 100644 cineast-core/src/main/java/org/vitrivr/cineast/core/features/SubDivMotionSumBackground4.java delete mode 100644 cineast-core/src/main/java/org/vitrivr/cineast/core/features/SubDivMotionSumBackground5.java delete mode 100644 cineast-core/src/main/java/org/vitrivr/cineast/core/features/WSDMTICollectionBooleanRetriever.java delete mode 100644 cineast-core/src/main/java/org/vitrivr/cineast/core/features/abstracts/MotionHistogramCalculator.java delete mode 100644 cineast-core/src/main/java/org/vitrivr/cineast/core/features/abstracts/SubDivMotionHistogram.java delete mode 100644 cineast-core/src/main/java/org/vitrivr/cineast/core/features/exporter/MotionFrameExporter.java delete mode 100644 cineast-core/src/main/java/org/vitrivr/cineast/core/features/exporter/MotionHistoryImageExporter.java delete mode 100644 cineast-core/src/main/java/org/vitrivr/cineast/core/features/retriever/CollectionBooleanRetriever.java delete mode 100644 cineast-core/src/main/java/org/vitrivr/cineast/core/importer/TupleInsertMessageImporter.java delete mode 100644 cineast-core/src/main/java/org/vitrivr/cineast/core/util/MotionHistoryImage.java delete mode 100644 cineast-core/src/main/java/org/vitrivr/cineast/core/util/RandomStringGenerator.java delete mode 100644 cineast-core/src/main/java/org/vitrivr/cineast/core/util/TagsPerSegment.java rename cineast-core/src/main/java/org/vitrivr/cineast/core/util/{ => ocr}/HungarianAlgorithm.java (99%) rename cineast-core/src/main/java/org/vitrivr/cineast/core/util/{ => ocr}/MultiTracker.java (98%) rename cineast-core/src/main/java/org/vitrivr/cineast/core/util/{ => ocr}/NeedlemanWunschMerge.java (98%) rename cineast-core/src/main/java/org/vitrivr/cineast/core/util/{ => ocr}/ThreadLocalObjectCache.java (94%) delete mode 100644 cineast-runtime/src/main/java/org/vitrivr/cineast/standalone/config/ExplorativeConfig.java delete mode 100644 cineast-runtime/src/main/java/org/vitrivr/cineast/standalone/evaluation/EvaluationConfig.java delete mode 100644 cineast-runtime/src/main/java/org/vitrivr/cineast/standalone/evaluation/EvaluationException.java delete mode 100644 cineast-runtime/src/main/java/org/vitrivr/cineast/standalone/evaluation/EvaluationResult.java delete mode 100644 cineast-runtime/src/main/java/org/vitrivr/cineast/standalone/evaluation/EvaluationRuntime.java delete mode 100644 cineast-runtime/src/main/java/org/vitrivr/cineast/standalone/evaluation/Groundtruth.java delete mode 100644 cineast-runtime/src/main/java/org/vitrivr/cineast/standalone/importer/PlainTextImporter.java delete mode 100644 cineast-runtime/src/main/java/org/vitrivr/cineast/standalone/importer/TagsFulltextImporter.java delete mode 100644 cineast-runtime/src/main/java/org/vitrivr/cineast/standalone/importer/VbsMetaImporter.java delete mode 100644 cineast-runtime/src/main/java/org/vitrivr/cineast/standalone/importer/handlers/AsrDataImportHandler.java delete mode 100644 cineast-runtime/src/main/java/org/vitrivr/cineast/standalone/importer/handlers/OcrDataImportHandler.java delete mode 100644 cineast-runtime/src/main/java/org/vitrivr/cineast/standalone/importer/handlers/ProtoDataImportHandler.java delete mode 100644 cineast-runtime/src/main/java/org/vitrivr/cineast/standalone/importer/lsc2020/CaptionImportHandler.java delete mode 100644 cineast-runtime/src/main/java/org/vitrivr/cineast/standalone/importer/lsc2020/CaptionImporter.java delete mode 100644 cineast-runtime/src/main/java/org/vitrivr/cineast/standalone/importer/lsc2020/JsonTagReader.java delete mode 100644 cineast-runtime/src/main/java/org/vitrivr/cineast/standalone/importer/lsc2020/LSCAllTagsImportHandler.java delete mode 100644 cineast-runtime/src/main/java/org/vitrivr/cineast/standalone/importer/lsc2020/LSCUtilities.java delete mode 100644 cineast-runtime/src/main/java/org/vitrivr/cineast/standalone/importer/lsc2020/MetaImportHandler.java delete mode 100644 cineast-runtime/src/main/java/org/vitrivr/cineast/standalone/importer/lsc2020/MetaImporter.java delete mode 100644 cineast-runtime/src/main/java/org/vitrivr/cineast/standalone/importer/lsc2020/MyscealTagImportHandler.java delete mode 100644 cineast-runtime/src/main/java/org/vitrivr/cineast/standalone/importer/lsc2020/MyscealTagImporter.java delete mode 100644 cineast-runtime/src/main/java/org/vitrivr/cineast/standalone/importer/lsc2020/OCRImportHandler.java delete mode 100644 cineast-runtime/src/main/java/org/vitrivr/cineast/standalone/importer/lsc2020/OCRImporter.java delete mode 100644 cineast-runtime/src/main/java/org/vitrivr/cineast/standalone/importer/lsc2020/ProcessingMetaImportHandler.java delete mode 100644 cineast-runtime/src/main/java/org/vitrivr/cineast/standalone/importer/lsc2020/ProcessingMetaImporter.java delete mode 100644 cineast-runtime/src/main/java/org/vitrivr/cineast/standalone/importer/lsc2020/SpatialImportHandler.java delete mode 100644 cineast-runtime/src/main/java/org/vitrivr/cineast/standalone/importer/lsc2020/SpatialImporter.java delete mode 100644 cineast-runtime/src/main/java/org/vitrivr/cineast/standalone/importer/lsc2020/TemporalImportHandler.java delete mode 100644 cineast-runtime/src/main/java/org/vitrivr/cineast/standalone/importer/lsc2020/TemporalImporter.java delete mode 100644 cineast-runtime/src/main/java/org/vitrivr/cineast/standalone/importer/lsc2020/VisualConceptTagImportHandler.java delete mode 100644 cineast-runtime/src/main/java/org/vitrivr/cineast/standalone/importer/lsc2020/VisualConceptTagImporter.java delete mode 100644 cineast-runtime/src/main/java/org/vitrivr/cineast/standalone/importer/vbs2019/AudioTranscriptImportHandler.java delete mode 100644 cineast-runtime/src/main/java/org/vitrivr/cineast/standalone/importer/vbs2019/AudioTranscriptionImporter.java delete mode 100644 cineast-runtime/src/main/java/org/vitrivr/cineast/standalone/importer/vbs2019/CaptionTextImportHandler.java delete mode 100644 cineast-runtime/src/main/java/org/vitrivr/cineast/standalone/importer/vbs2019/CaptionTextImporter.java delete mode 100644 cineast-runtime/src/main/java/org/vitrivr/cineast/standalone/importer/vbs2019/GoogleVisionImportHandler.java delete mode 100644 cineast-runtime/src/main/java/org/vitrivr/cineast/standalone/importer/vbs2019/GoogleVisionImporter.java delete mode 100644 cineast-runtime/src/main/java/org/vitrivr/cineast/standalone/importer/vbs2019/MLTFeatureImporter.java delete mode 100644 cineast-runtime/src/main/java/org/vitrivr/cineast/standalone/importer/vbs2019/ObjectMetadataImportHandler.java delete mode 100644 cineast-runtime/src/main/java/org/vitrivr/cineast/standalone/importer/vbs2019/ObjectMetadataImporter.java delete mode 100644 cineast-runtime/src/main/java/org/vitrivr/cineast/standalone/importer/vbs2019/TagImportHandler.java delete mode 100644 cineast-runtime/src/main/java/org/vitrivr/cineast/standalone/importer/vbs2019/TagImporter.java delete mode 100644 cineast-runtime/src/main/java/org/vitrivr/cineast/standalone/importer/vbs2019/gvision/GoogleVisionCategory.java delete mode 100644 cineast-runtime/src/main/java/org/vitrivr/cineast/standalone/importer/vbs2019/gvision/GoogleVisionLabelTuple.java delete mode 100644 cineast-runtime/src/main/java/org/vitrivr/cineast/standalone/importer/vbs2019/gvision/GoogleVisionOCRTuple.java delete mode 100644 cineast-runtime/src/main/java/org/vitrivr/cineast/standalone/importer/vbs2019/gvision/GoogleVisionTuple.java delete mode 100644 cineast-runtime/src/main/java/org/vitrivr/cineast/standalone/importer/vbs2019/gvision/GoogleVisionWebTuple.java delete mode 100644 cineast-runtime/src/main/java/org/vitrivr/cineast/standalone/importer/vbs2019/v3c1analysis/ColorlabelImportHandler.java delete mode 100644 cineast-runtime/src/main/java/org/vitrivr/cineast/standalone/importer/vbs2019/v3c1analysis/ColorlabelImporter.java delete mode 100644 cineast-runtime/src/main/java/org/vitrivr/cineast/standalone/importer/vbs2019/v3c1analysis/SequenceIdLookupService.java delete mode 100644 cineast-runtime/src/main/java/org/vitrivr/cineast/standalone/listener/RetrievalResultCSVExporter.java delete mode 100644 cineast-runtime/src/main/java/org/vitrivr/cineast/standalone/listener/RetrievalResultListener.java diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index add6a5b09..000000000 --- a/.travis.yml +++ /dev/null @@ -1,22 +0,0 @@ -language: java - -matrix: - include: - - os: linux - jdk: - - openjdk8 - - openjdk11 - - os: osx - osx_image: xcode8 - -before_cache: - - rm -f $HOME/.gradle/caches/modules-2/modules-2.lock - - rm -fr $HOME/.gradle/caches/*/plugin-resolution/ -cache: - directories: - - $HOME/.gradle/caches/ - - $HOME/.gradle/wrapper/ - -script: - - if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then ./gradlew check ; fi - - if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then ./gradlew jar ; fi diff --git a/build.gradle b/build.gradle index 333e98f45..7e39ef00f 100644 --- a/build.gradle +++ b/build.gradle @@ -68,6 +68,10 @@ subprojects { implementation group: 'com.fasterxml.jackson.core', name: 'jackson-core', version: version_jackson implementation group: 'com.fasterxml.jackson.core', name: 'jackson-databind', version: version_jackson + /** Protobuf */ + implementation group: 'io.grpc', name: 'grpc-stub', version: '1.45.0' + implementation group: 'io.grpc', name: 'grpc-netty', version: '1.45.0' + /** Test dependencies (JUnit 5) */ testImplementation group: 'org.junit.jupiter', name: 'junit-jupiter-api', version: version_junit testRuntimeOnly group: 'org.junit.jupiter', name: 'junit-jupiter-engine', version: version_junit diff --git a/cineast-api/build.gradle b/cineast-api/build.gradle index 94edb6a98..704edae9c 100644 --- a/cineast-api/build.gradle +++ b/cineast-api/build.gradle @@ -111,6 +111,8 @@ dependencies { implementation group: 'com.fasterxml.jackson.module', name: 'jackson-module-kotlin', version: version_jackson implementation group: 'de.svenkubiak', name: 'jBCrypt', version: version_jbcrypt implementation group: 'org.vitrivr', name: 'cineast-proto', version: version_cineast_proto + implementation group: 'it.unimi.dsi', name: 'fastutil', version: '8.5.8' + } diff --git a/cineast-api/src/main/java/org/vitrivr/cineast/api/grpc/util/QueryContainerUtil.java b/cineast-api/src/main/java/org/vitrivr/cineast/api/grpc/util/QueryContainerUtil.java index 8c30e2ce7..1382e31a3 100644 --- a/cineast-api/src/main/java/org/vitrivr/cineast/api/grpc/util/QueryContainerUtil.java +++ b/cineast-api/src/main/java/org/vitrivr/cineast/api/grpc/util/QueryContainerUtil.java @@ -40,7 +40,6 @@ import org.vitrivr.cineast.core.data.query.containers.InstantQueryTermContainer; import org.vitrivr.cineast.core.data.query.containers.LocationQueryTermContainer; import org.vitrivr.cineast.core.data.query.containers.ModelQueryTermContainer; -import org.vitrivr.cineast.core.data.query.containers.MotionQueryTermContainer; import org.vitrivr.cineast.core.data.query.containers.SemanticMapQueryTermContainer; import org.vitrivr.cineast.core.data.query.containers.TagQueryTermContainer; import org.vitrivr.cineast.core.data.query.containers.TextQueryTermContainer; @@ -159,13 +158,6 @@ public static ModelQueryTermContainer modelQueryContainer(CineastGrpc.ModelQuery return null; } - public static MotionQueryTermContainer motionQueryContainer(CineastGrpc.MotionQueryContainer container) { - MotionQueryTermContainer motionQueryContainer = new MotionQueryTermContainer(); - container.getBackgroundPathList().stream().forEach(path -> motionQueryContainer.addBgPath(motionPath(path))); - container.getForegroundPathList().stream().forEach(path -> motionQueryContainer.addPath(motionPath(path))); - return motionQueryContainer; - } - public static LinkedList motionPath(CineastGrpc.MotionQueryContainer.MotionPath path) { LinkedList list = new LinkedList<>(); list.addAll(path.getPathList().stream().map(QueryContainerUtil::point).collect(Collectors.toList())); @@ -199,7 +191,6 @@ public static TextQueryTermContainer textQueryContainer(CineastGrpc.TextQueryCon public static AbstractQueryTermContainer queryTermContainer(CineastGrpc.QueryTerm term) { switch (term.getContainerCase()) { - case AUDIOQUERYCONTAINER: return audioQueryContainer(term.getAudioQueryContainer()); case BOOLEANQUERYCONTAINER: @@ -214,8 +205,6 @@ public static AbstractQueryTermContainer queryTermContainer(CineastGrpc.QueryTer return locationQueryContainer(term.getLocationQueryContainer()); case MODELQUERYCONTAINER: return modelQueryContainer(term.getModelQueryContainer()); - case MOTIONQUERYCONTAINER: - return motionQueryContainer(term.getMotionQueryContainer()); case SEMANTICMAPQUERYCONTAINER: return semanticMapQueryContainer(term.getSemanticMapQueryContainer()); case TAGQUERYCONTAINER: diff --git a/cineast-api/src/main/java/org/vitrivr/cineast/api/messages/query/QueryTermType.java b/cineast-api/src/main/java/org/vitrivr/cineast/api/messages/query/QueryTermType.java index f9e891fc6..f341f45e1 100644 --- a/cineast-api/src/main/java/org/vitrivr/cineast/api/messages/query/QueryTermType.java +++ b/cineast-api/src/main/java/org/vitrivr/cineast/api/messages/query/QueryTermType.java @@ -13,7 +13,6 @@ import org.vitrivr.cineast.core.data.query.containers.InstantQueryTermContainer; import org.vitrivr.cineast.core.data.query.containers.LocationQueryTermContainer; import org.vitrivr.cineast.core.data.query.containers.ModelQueryTermContainer; -import org.vitrivr.cineast.core.data.query.containers.MotionQueryTermContainer; import org.vitrivr.cineast.core.data.query.containers.ParameterisedLocationQueryTermContainer; import org.vitrivr.cineast.core.data.query.containers.SemanticMapQueryTermContainer; import org.vitrivr.cineast.core.data.query.containers.TagQueryTermContainer; @@ -26,7 +25,6 @@ public enum QueryTermType { IMAGE(ImageQueryTermContainer.class), AUDIO(AudioQueryTermContainer.class), - MOTION(MotionQueryTermContainer.class), MODEL3D(ModelQueryTermContainer.class), LOCATION(LocationQueryTermContainer.class), PARAMETERISED_LOCATION(ParameterisedLocationQueryTermContainer.class), diff --git a/cineast-api/src/main/java/org/vitrivr/cineast/api/websocket/handlers/queries/TemporalQueryMessageHandler.java b/cineast-api/src/main/java/org/vitrivr/cineast/api/websocket/handlers/queries/TemporalQueryMessageHandler.java index 862f0cf7f..e511a9f66 100644 --- a/cineast-api/src/main/java/org/vitrivr/cineast/api/websocket/handlers/queries/TemporalQueryMessageHandler.java +++ b/cineast-api/src/main/java/org/vitrivr/cineast/api/websocket/handlers/queries/TemporalQueryMessageHandler.java @@ -1,6 +1,5 @@ package org.vitrivr.cineast.api.websocket.handlers.queries; -import io.netty.util.collection.IntObjectHashMap; import java.util.ArrayList; import java.util.HashMap; import java.util.HashSet; @@ -10,6 +9,8 @@ import java.util.concurrent.CompletableFuture; import java.util.stream.Collectors; import java.util.stream.IntStream; + +import it.unimi.dsi.fastutil.ints.Int2ObjectLinkedOpenHashMap; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import org.eclipse.jetty.websocket.api.Session; @@ -53,7 +54,7 @@ public void execute(Session session, QueryConfig qconf, TemporalQuery message, S List cleanupThreads = new ArrayList<>(); /* We need a set of segments and objects to be used for temporal scoring as well as a storage of all container results where are the index of the outer list is where container i was scored */ - Map> containerResults = new IntObjectHashMap<>(); + Map> containerResults = new Int2ObjectLinkedOpenHashMap<>(); Set segments = new HashSet<>(); Set sentSegmentIds = new HashSet<>(); diff --git a/cineast-core/build.gradle b/cineast-core/build.gradle index bb6ff7408..c7db2387f 100644 --- a/cineast-core/build.gradle +++ b/cineast-core/build.gradle @@ -75,11 +75,6 @@ signing { sign publishing.publications.mavenJava } - -/** - * We cannot switch to implementation yet in multi-module setups. - * With Gradle 6.7 and MacOS, declaring dependencies as implementation means they do not get exposed to other projects - */ dependencies { /** THE Cottontail DB proto dependency */ @@ -89,9 +84,6 @@ dependencies { /** THE Polypheny dependency */ api group: "org.polypheny", name: "polypheny-jdbc-driver", version: version_polypheny - /** THE ADAMpro proto dependency (legacy) */ - api group: 'org.vitrivr', name: 'adampro-proto', version: version_adampro - /* Google Json: GSON, since JSON db layer is based on this */ api group: 'com.google.code.gson', name: 'gson', version: version_gson @@ -99,6 +91,8 @@ dependencies { api group: "net.sf.trove4j", name: "trove4j", version: version_trove4j api group: "com.google.guava", name: "guava", version: version_guava api group: "com.googlecode.javaewah", name: "JavaEWAH", version: version_javaewah + implementation group: 'it.unimi.dsi', name: 'fastutil', version: '8.5.8' + /** Mockito for unit testing */ implementation 'org.mockito:mockito-inline:3.11.0' @@ -152,6 +146,7 @@ dependencies { /** Java 9+ compatibility. */ api group: 'javax.annotation', name: 'javax.annotation-api', version: '1.3.2' api group: 'javax.activation', name: 'activation', version: '1.1.1' + } shadowJar { diff --git a/cineast-core/src/main/java/org/vitrivr/cineast/core/data/DefaultValueHashMap.java b/cineast-core/src/main/java/org/vitrivr/cineast/core/data/DefaultValueHashMap.java deleted file mode 100644 index 1f09f4a5c..000000000 --- a/cineast-core/src/main/java/org/vitrivr/cineast/core/data/DefaultValueHashMap.java +++ /dev/null @@ -1,49 +0,0 @@ -package org.vitrivr.cineast.core.data; - -import java.util.HashMap; -import java.util.Map; -import org.apache.logging.log4j.LogManager; -import org.apache.logging.log4j.Logger; - -/** - * HashMap which returns a default value in case the key is unknown - */ -public class DefaultValueHashMap extends HashMap { - - private static final long serialVersionUID = -8326007409332438019L; - - private static final Logger LOGGER = LogManager.getLogger(); - - private final V defaultValue; - - public DefaultValueHashMap(V defaultValue) { - super(); - this.defaultValue = defaultValue; - } - - public DefaultValueHashMap(int initialCapacity, float loadFactor, V defaultValue) { - super(initialCapacity, loadFactor); - this.defaultValue = defaultValue; - } - - public DefaultValueHashMap(int initialCapacity, V defaultValue) { - super(initialCapacity); - this.defaultValue = defaultValue; - } - - public DefaultValueHashMap(Map m, V defaultValue) { - super(m); - this.defaultValue = defaultValue; - } - - @Override - public V get(Object key) { - if (containsKey(key)) { - return super.get(key); - } - LOGGER.info("key {} not present, returning default value {}", key, defaultValue); - return defaultValue; - } - - -} diff --git a/cineast-core/src/main/java/org/vitrivr/cineast/core/data/DynamicGrid.java b/cineast-core/src/main/java/org/vitrivr/cineast/core/data/DynamicGrid.java deleted file mode 100644 index 6af913000..000000000 --- a/cineast-core/src/main/java/org/vitrivr/cineast/core/data/DynamicGrid.java +++ /dev/null @@ -1,129 +0,0 @@ -package org.vitrivr.cineast.core.data; - -import gnu.trove.iterator.TIntIterator; -import gnu.trove.map.hash.TIntObjectHashMap; -import java.io.Serializable; -import java.util.HashSet; -import java.util.Set; - -public class DynamicGrid implements Serializable, Grid { - - private static final long serialVersionUID = -2284330171007553138L; - private final TIntObjectHashMap> grid = new TIntObjectHashMap>(); - private final T defaultElement; - - public DynamicGrid(T defaultElement) { - this.defaultElement = defaultElement; - } - - public DynamicGrid() { - this(null); - } - - public DynamicGrid(T defaultElement, T[][] data) { - this(defaultElement); - for (int x = 0; x < data.length; ++x) { - T[] arr = data[x]; - TIntObjectHashMap map = new TIntObjectHashMap<>(); - for (int y = 0; y < arr.length; ++y) { - T element = arr[y]; - if (element != null) { - map.put(y, element); - } - } - map.compact(); - grid.put(x, map); - } - grid.compact(); - } - - /* (non-Javadoc) - * @see Grid#setElement(int, int, T) - */ - @Override - public Grid setElement(int x, int y, T element) { - if (!grid.containsKey(x)) { - grid.put(x, new TIntObjectHashMap<>()); - } - grid.get(x).put(y, element); - return this; - } - - /* (non-Javadoc) - * @see Grid#get(int, int) - */ - @Override - public T get(int x, int y) { - if (!grid.containsKey(x)) { - return defaultElement; - } - TIntObjectHashMap map = grid.get(x); - if (!map.containsKey(y)) { - return defaultElement; - } - return map.get(y); - } - - /* (non-Javadoc) - * @see Grid#isset(int, int) - */ - @Override - public boolean isset(int x, int y) { - if (!grid.containsKey(x)) { - return false; - } - return grid.get(x).containsKey(y); - } - - /* (non-Javadoc) - * @see Grid#remove(int, int) - */ - @Override - public T remove(int x, int y) { - if (!grid.containsKey(x)) { - return null; - } - TIntObjectHashMap map = grid.get(x); - if (!map.containsKey(y)) { - return null; - } - T _return = map.remove(y); - if (map.isEmpty()) { - grid.remove(x); - } - return _return; - } - - /* (non-Javadoc) - * @see Grid#compact() - */ - @Override - public void compact() { - TIntIterator iter = grid.keySet().iterator(); - while (iter.hasNext()) { - int x = iter.next(); - TIntObjectHashMap map = grid.get(x); - if (map.isEmpty()) { - grid.remove(x); - } else { - map.compact(); - } - } - grid.compact(); - } - - @Override - public Set getKeySet() { - HashSet _return = new HashSet<>(); - TIntIterator xiter = grid.keySet().iterator(); - while (xiter.hasNext()) { - int x = xiter.next(); - TIntIterator yiter = grid.get(x).keySet().iterator(); - while (yiter.hasNext()) { - _return.add(new Position(x, yiter.next())); - } - } - return _return; - } - -} diff --git a/cineast-core/src/main/java/org/vitrivr/cineast/core/data/Grid.java b/cineast-core/src/main/java/org/vitrivr/cineast/core/data/Grid.java deleted file mode 100644 index 4cefa6ffc..000000000 --- a/cineast-core/src/main/java/org/vitrivr/cineast/core/data/Grid.java +++ /dev/null @@ -1,27 +0,0 @@ -package org.vitrivr.cineast.core.data; - -import java.util.Set; - -public interface Grid { - - Grid setElement(int x, int y, T element); - - T get(int x, int y); - - boolean isset(int x, int y); - - /** - * returns and removes the element at (x,y). - * - * @return the element at position (x,y) or null if there was no such element - */ - T remove(int x, int y); - - /** - * compacts the grid by removing unnecessary data structures. - */ - void compact(); - - Set getKeySet(); - -} \ No newline at end of file diff --git a/cineast-core/src/main/java/org/vitrivr/cineast/core/data/Position.java b/cineast-core/src/main/java/org/vitrivr/cineast/core/data/Position.java deleted file mode 100644 index e91355589..000000000 --- a/cineast-core/src/main/java/org/vitrivr/cineast/core/data/Position.java +++ /dev/null @@ -1,77 +0,0 @@ -package org.vitrivr.cineast.core.data; - -import java.io.Serializable; - -/** - * Created by silvanstich on 04.10.16. - */ -public class Position implements Serializable { - - private static final long serialVersionUID = -4360148820779089159L; - public final int x; - public final int y; - - public Position(int x, int y) { - this.x = x; - this.y = y; - } - - public int getX() { - return x; - } - - public int getY() { - return y; - } - - public Position getPosBottom() { - return new Position(x, y - 1); - } - - public Position getPosLeft() { - return new Position(x - 1, y); - } - - public Position getPosRight() { - return new Position(x + 1, y); - } - - public Position getPosTop() { - return new Position(x, y + 1); - } - - public Position[] getNeighborPositions() { - return new Position[]{getPosTop(), getPosLeft(), getPosBottom(), getPosRight()}; - } - - @Override - public int hashCode() { - return (x >>> 16) | (x << 16) | y; - } - - @Override - public boolean equals(Object obj) { - if (this == obj) { - return true; - } - if (obj == null) { - return false; - } - if (getClass() != obj.getClass()) { - return false; - } - Position other = (Position) obj; - if (x != other.x) { - return false; - } - if (y != other.y) { - return false; - } - return true; - } - - @Override - public String toString() { - return "Position is (" + x + "," + y + ")"; - } -} diff --git a/cineast-core/src/main/java/org/vitrivr/cineast/core/data/QuerySubTitleItem.java b/cineast-core/src/main/java/org/vitrivr/cineast/core/data/QuerySubTitleItem.java deleted file mode 100644 index 5ddf63b49..000000000 --- a/cineast-core/src/main/java/org/vitrivr/cineast/core/data/QuerySubTitleItem.java +++ /dev/null @@ -1,32 +0,0 @@ -package org.vitrivr.cineast.core.data; - -import org.vitrivr.cineast.core.extraction.decode.subtitle.SubtitleItem; - -public class QuerySubTitleItem implements SubtitleItem { - - private final String text; - - public QuerySubTitleItem(String text) { - this.text = text; - } - - @Override - public int getLength() { - return 0; - } - - @Override - public String getText() { - return text; - } - - @Override - public long getStartTimestamp() { - return 0; - } - - @Override - public long getEndTimestamp() { - return 0; - } -} diff --git a/cineast-core/src/main/java/org/vitrivr/cineast/core/data/UniqueElementGrid.java b/cineast-core/src/main/java/org/vitrivr/cineast/core/data/UniqueElementGrid.java deleted file mode 100644 index 2252aed03..000000000 --- a/cineast-core/src/main/java/org/vitrivr/cineast/core/data/UniqueElementGrid.java +++ /dev/null @@ -1,78 +0,0 @@ -package org.vitrivr.cineast.core.data; - -import com.google.common.collect.HashBiMap; -import java.util.HashSet; -import java.util.Set; - -public class UniqueElementGrid implements Grid { - - private final HashBiMap map = HashBiMap.create(); - - @Override - public Grid setElement(int x, int y, T element) { - map.forcePut(new Position(x, y), element); - return this; - } - - public Grid setElement(Position p, T element) { - map.forcePut(p, element); - return this; - } - - @Override - public T get(int x, int y) { - return map.get(new Position(x, y)); - } - - public T get(Position p) { - if (p == null) { - return null; - } - return map.get(p); - } - - /** - * Returns the grid position of the specified element or null if the element is not part of the map. - */ - public Position getPosition(T element) { - return map.inverse().get(element); - } - - @Override - public boolean isset(int x, int y) { - return map.containsKey(new Position(x, y)); - } - - public boolean isset(Position p) { - if (p == null) { - return false; - } - return map.containsKey(p); - } - - @Override - public T remove(int x, int y) { - return map.remove(new Position(x, y)); - } - - public T remove(Position p) { - return map.remove(p); - } - - public Position remove(T element) { - return map.inverse().remove(element); - } - - @Override - public void compact() { - // not supported - } - - @Override - public Set getKeySet() { - HashSet _return = new HashSet<>(); - _return.addAll(_return); - return _return; - } - -} diff --git a/cineast-core/src/main/java/org/vitrivr/cineast/core/data/query/containers/MotionQueryTermContainer.java b/cineast-core/src/main/java/org/vitrivr/cineast/core/data/query/containers/MotionQueryTermContainer.java deleted file mode 100644 index b5d19e1e7..000000000 --- a/cineast-core/src/main/java/org/vitrivr/cineast/core/data/query/containers/MotionQueryTermContainer.java +++ /dev/null @@ -1,95 +0,0 @@ -package org.vitrivr.cineast.core.data.query.containers; - -import com.fasterxml.jackson.databind.JsonNode; -import georegression.struct.point.Point2D_F32; -import java.util.ArrayList; -import java.util.LinkedList; -import java.util.List; -import org.vitrivr.cineast.core.data.Pair; -import org.vitrivr.cineast.core.util.web.DataURLParser; - -//FIXME integer in pair is never used -public class MotionQueryTermContainer extends AbstractQueryTermContainer { - - private List>> paths = new ArrayList>>(); - private List>> bgPaths = new ArrayList>>(); - - public MotionQueryTermContainer() { - //empty container - } - - /** - * Constructs an {@link MotionQueryTermContainer} from base 64 encoded JSON data. - * - * @param data The 3D model data that should be converted. - */ - public MotionQueryTermContainer(String data) { - this(DataURLParser.dataURLtoJsonNode(data).orElseThrow(() -> new IllegalArgumentException("Failed to parse the provided motion data."))); - } - - /** - * Constructs an {@link MotionQueryTermContainer} from a JsonNode object. - * - * @param jsonNode The JsonNode representing the motion data. - */ - public MotionQueryTermContainer(JsonNode jsonNode) { - final JsonNode foreground = jsonNode.get("foreground"); - ArrayList> list = nodeToList(foreground); - for (LinkedList path : list) { - this.addPath(path); - } - - final JsonNode background = jsonNode.get("background"); - list = nodeToList(background); - for (LinkedList path : list) { - this.addPath(path); - } - } - - @Override - public List>> getPaths() { - return this.paths; - } - - @Override - public List>> getBgPaths() { - return this.bgPaths; - } - - public void addPath(LinkedList path) { - this.paths.add(new Pair>(0, path)); - } - - public void addBgPath(LinkedList path) { - this.bgPaths.add(new Pair>(0, path)); - } - - public static AbstractQueryTermContainer fromJson(JsonNode jsonNode) { - return new MotionQueryTermContainer(jsonNode); - } - - private static ArrayList> nodeToList(JsonNode jsonNode) { - if (jsonNode == null || !jsonNode.isArray()) { - return new ArrayList<>(); - } - ArrayList> _return = new ArrayList<>(jsonNode.size()); - for (final JsonNode list : jsonNode) { - JsonNode path = list.get("path"); - if (path == null || !path.isArray()) { - continue; - } - int size = path.size(); - LinkedList pathList = new LinkedList(); - for (int i = 0; i < size; ++i) { - JsonNode point = path.get(i); - if (point == null) { - continue; - } - pathList.add(new Point2D_F32(point.get("x").floatValue(), point.get("y").floatValue())); - } - _return.add(pathList); - } - return _return; - } - -} diff --git a/cineast-core/src/main/java/org/vitrivr/cineast/core/db/DataMessageConverter.java b/cineast-core/src/main/java/org/vitrivr/cineast/core/db/DataMessageConverter.java deleted file mode 100644 index da02a49ad..000000000 --- a/cineast-core/src/main/java/org/vitrivr/cineast/core/db/DataMessageConverter.java +++ /dev/null @@ -1,231 +0,0 @@ -package org.vitrivr.cineast.core.db; - -import java.util.List; -import org.vitrivr.adampro.grpc.AdamGrpc.DataMessage; -import org.vitrivr.adampro.grpc.AdamGrpc.DenseVectorMessage; -import org.vitrivr.adampro.grpc.AdamGrpc.IntVectorMessage; -import org.vitrivr.adampro.grpc.AdamGrpc.SparseVectorMessage; -import org.vitrivr.adampro.grpc.AdamGrpc.VectorMessage; -import org.vitrivr.cineast.core.data.FloatArrayIterable; -import org.vitrivr.cineast.core.data.IntArrayIterable; -import org.vitrivr.cineast.core.data.providers.primitive.BooleanTypeProvider; -import org.vitrivr.cineast.core.data.providers.primitive.DoubleTypeProvider; -import org.vitrivr.cineast.core.data.providers.primitive.FloatArrayProvider; -import org.vitrivr.cineast.core.data.providers.primitive.FloatTypeProvider; -import org.vitrivr.cineast.core.data.providers.primitive.FloatVectorProvider; -import org.vitrivr.cineast.core.data.providers.primitive.IntArrayProvider; -import org.vitrivr.cineast.core.data.providers.primitive.IntTypeProvider; -import org.vitrivr.cineast.core.data.providers.primitive.IntVectorProvider; -import org.vitrivr.cineast.core.data.providers.primitive.LongTypeProvider; -import org.vitrivr.cineast.core.data.providers.primitive.NothingProvider; -import org.vitrivr.cineast.core.data.providers.primitive.PrimitiveTypeProvider; -import org.vitrivr.cineast.core.data.providers.primitive.StringTypeProvider; - -public final class DataMessageConverter { - - private DataMessageConverter() { - } - - public static final PrimitiveTypeProvider convert(DataMessage message) { - switch (message.getDatatypeCase()) { - case BOOLEANDATA: - return new BooleanTypeProvider(message.getBooleanData()); - case DOUBLEDATA: - return new DoubleTypeProvider(message.getDoubleData()); - case VECTORDATA: - VectorMessage VectorMessage = message.getVectorData(); - switch (VectorMessage.getVectorCase()) { - case DENSEVECTOR: - return new FloatVectorProvider(convert(VectorMessage.getDenseVector())); - case INTVECTOR: - return new IntVectorProvider(convert(VectorMessage.getIntVector())); - case SPARSEVECTOR: - return new FloatVectorProvider(convert(VectorMessage.getSparseVector())); - case VECTOR_NOT_SET: - default: - return new NothingProvider(); - } - case FLOATDATA: - return new FloatTypeProvider(message.getFloatData()); - case INTDATA: - return new IntTypeProvider(message.getIntData()); - case LONGDATA: - return new LongTypeProvider(message.getLongData()); - case STRINGDATA: - return new StringTypeProvider(message.getStringData()); - case DATATYPE_NOT_SET: - default: - return new NothingProvider(); - - } - } - - private static final DataMessage.Builder builder = DataMessage.newBuilder(); - private static final VectorMessage.Builder vectorBuilder = VectorMessage.newBuilder(); - private static final DenseVectorMessage.Builder denseVectorBuilder = DenseVectorMessage.newBuilder(); - private static final IntVectorMessage.Builder intVectorBuilder = IntVectorMessage.newBuilder(); - - public static DataMessage convert(PrimitiveTypeProvider provider) { - switch (provider.getType()) { - case BOOLEAN: - return convert(provider.getBoolean()); - case BYTE: - return convert(provider.getByte()); - case DOUBLE: - return convert(provider.getDouble()); - case FLOAT: - return convert(provider.getFloat()); - case FLOAT_ARRAY: - return convert(provider.getFloatArray()); - case INT: - return convert(provider.getInt()); - case INT_ARRAY: - return convert(provider.getIntArray()); - case LONG: - return convert(provider.getLong()); - case SHORT: - return convert(provider.getShort()); - case STRING: - return convert(provider.getString()); - case UNKNOWN: - default: - throw new IllegalArgumentException("Cannot convert ProviderDataType " + provider.getType() + " to DataMessage"); - - } - } - - - public static final DataMessage convert(boolean bool) { - synchronized (builder) { - builder.clear(); - return builder.setBooleanData(bool).build(); - } - } - - public static final DataMessage convert(int i) { - synchronized (builder) { - builder.clear(); - return builder.setIntData(i).build(); - } - } - - public static DataMessage convert(double d) { - synchronized (builder) { - builder.clear(); - return builder.setDoubleData(d).build(); - } - } - - public static DataMessage convert(float f) { - synchronized (builder) { - builder.clear(); - return builder.setFloatData(f).build(); - } - } - - public static DataMessage convert(long l) { - synchronized (builder) { - builder.clear(); - return builder.setLongData(l).build(); - } - } - - public static DataMessage convert(String s) { - synchronized (builder) { - builder.clear(); - return builder.setStringData(s).build(); - } - } - - public static VectorMessage convertVectorMessage(float[] vector) { - if (vector == null) { - vector = new float[0]; - } - DenseVectorMessage dvmg; - synchronized (denseVectorBuilder) { - dvmg = denseVectorBuilder.clear().addAllVector(new FloatArrayIterable(vector)).build(); - } - synchronized (vectorBuilder) { - vectorBuilder.clear(); - return vectorBuilder.setDenseVector(dvmg).build(); - } - } - - public static DataMessage convert(float[] vector) { - synchronized (builder) { - builder.clear(); - return builder.setVectorData(convertVectorMessage(vector)).build(); - } - } - - public static VectorMessage convertVectorMessage(int[] vector) { - if (vector == null) { - vector = new int[0]; - } - IntVectorMessage ivmg; - synchronized (intVectorBuilder) { - ivmg = intVectorBuilder.clear().addAllVector(new IntArrayIterable(vector)).build(); - } - synchronized (vectorBuilder) { - vectorBuilder.clear(); - return vectorBuilder.setIntVector(ivmg).build(); - } - } - - public static DataMessage convert(int[] vector) { - synchronized (builder) { - builder.clear(); - return builder.setVectorData(convertVectorMessage(vector)).build(); - } - } - - private static float[] convert(DenseVectorMessage message) { - List floatlist = message.getVectorList(); - if (floatlist == null || floatlist.isEmpty()) { - return FloatArrayProvider.DEFAULT_FLOAT_ARRAY; - } - float[] _return = new float[floatlist.size()]; - int i = 0; - for (float f : floatlist) { - _return[i++] = f; - } - return _return; - } - - private static float[] convert(SparseVectorMessage message) { - List indexList = message.getIndexList(); - if (indexList == null || indexList.isEmpty()) { - return FloatArrayProvider.DEFAULT_FLOAT_ARRAY; - } - - int maxIndex = 0; - for (int i : indexList) { - maxIndex = maxIndex < i ? i : maxIndex; - } - - float[] _return = new float[maxIndex + 1]; - - List valueList = message.getDataList(); - - for (int i = 0; i < indexList.size(); ++i) { - _return[indexList.get(i)] = valueList.get(i); - } - - return _return; - } - - private static int[] convert(IntVectorMessage message) { - List intList = message.getVectorList(); - if (intList == null || intList.isEmpty()) { - return IntArrayProvider.DEFAULT_INT_ARRAY; - } - int[] _return = new int[intList.size()]; - int i = 0; - for (int j : intList) { - _return[i++] = j; - } - return _return; - } - -} - diff --git a/cineast-core/src/main/java/org/vitrivr/cineast/core/extraction/idgenerator/UniqueObjectIdGenerator.java b/cineast-core/src/main/java/org/vitrivr/cineast/core/extraction/idgenerator/UniqueObjectIdGenerator.java index d3fcfd16f..655525ba7 100644 --- a/cineast-core/src/main/java/org/vitrivr/cineast/core/extraction/idgenerator/UniqueObjectIdGenerator.java +++ b/cineast-core/src/main/java/org/vitrivr/cineast/core/extraction/idgenerator/UniqueObjectIdGenerator.java @@ -3,8 +3,8 @@ import java.nio.file.Path; import java.util.HashSet; import java.util.Map; +import org.apache.commons.lang3.RandomStringUtils; import org.vitrivr.cineast.core.data.MediaType; -import org.vitrivr.cineast.core.util.RandomStringGenerator; /** * Generates an objectId from a random string. @@ -54,7 +54,7 @@ public UniqueObjectIdGenerator(Map properties) { public String next(Path path, MediaType type) { String rawId; do { - rawId = RandomStringGenerator.generateRandomString(this.length); + rawId = RandomStringUtils.randomAlphanumeric(this.length); } while (this.usedIds.contains(rawId)); this.usedIds.add(rawId); return MediaType.generateId(type, rawId); diff --git a/cineast-core/src/main/java/org/vitrivr/cineast/core/features/CollectionBooleanRetriever.java b/cineast-core/src/main/java/org/vitrivr/cineast/core/features/CollectionBooleanRetriever.java new file mode 100644 index 000000000..f504f3ee5 --- /dev/null +++ b/cineast-core/src/main/java/org/vitrivr/cineast/core/features/CollectionBooleanRetriever.java @@ -0,0 +1,30 @@ +package org.vitrivr.cineast.core.features; + +import org.vitrivr.cineast.core.db.RelationalOperator; +import org.vitrivr.cineast.core.features.abstracts.BooleanRetriever; + +import java.util.*; + +public class CollectionBooleanRetriever extends BooleanRetriever { + + private static final List SUPPORTED_OPERATORS = + Collections.unmodifiableList( + Arrays.asList( + RelationalOperator.EQ, + RelationalOperator.NEQ, + RelationalOperator.IN, + RelationalOperator.LIKE)); + + protected CollectionBooleanRetriever(String entity, Collection attributes) { + super(entity, attributes); + } + + protected CollectionBooleanRetriever(LinkedHashMap properties) { + super(properties); + } + + @Override + protected Collection getSupportedOperators() { + return SUPPORTED_OPERATORS; + } +} diff --git a/cineast-core/src/main/java/org/vitrivr/cineast/core/features/DailyCollectionBooleanRetriever.java b/cineast-core/src/main/java/org/vitrivr/cineast/core/features/DailyCollectionBooleanRetriever.java deleted file mode 100644 index 65d660cf1..000000000 --- a/cineast-core/src/main/java/org/vitrivr/cineast/core/features/DailyCollectionBooleanRetriever.java +++ /dev/null @@ -1,11 +0,0 @@ -package org.vitrivr.cineast.core.features; - -import java.util.Collections; -import org.vitrivr.cineast.core.features.retriever.CollectionBooleanRetriever; - -public class DailyCollectionBooleanRetriever extends CollectionBooleanRetriever { - - public DailyCollectionBooleanRetriever() { - super("features_daily", Collections.singletonList("location")); - } -} \ No newline at end of file diff --git a/cineast-core/src/main/java/org/vitrivr/cineast/core/features/DailyRangeBooleanRetriever.java b/cineast-core/src/main/java/org/vitrivr/cineast/core/features/DailyRangeBooleanRetriever.java deleted file mode 100644 index dcbe4cc4c..000000000 --- a/cineast-core/src/main/java/org/vitrivr/cineast/core/features/DailyRangeBooleanRetriever.java +++ /dev/null @@ -1,10 +0,0 @@ -package org.vitrivr.cineast.core.features; - -import java.util.Arrays; - -public class DailyRangeBooleanRetriever extends RangeBooleanRetriever { - - public DailyRangeBooleanRetriever() { - super("features_daily", Arrays.asList("heart_rate", "skim_temp", "steps", "calories", "gsr")); - } -} diff --git a/cineast-core/src/main/java/org/vitrivr/cineast/core/features/MotionHistogram.java b/cineast-core/src/main/java/org/vitrivr/cineast/core/features/MotionHistogram.java deleted file mode 100644 index cb005a025..000000000 --- a/cineast-core/src/main/java/org/vitrivr/cineast/core/features/MotionHistogram.java +++ /dev/null @@ -1,59 +0,0 @@ -package org.vitrivr.cineast.core.features; - -import static org.vitrivr.cineast.core.util.CineastConstants.FEATURE_COLUMN_QUALIFIER; - -import java.util.ArrayList; -import java.util.List; -import java.util.function.Supplier; -import org.vitrivr.cineast.core.config.ReadableQueryConfig; -import org.vitrivr.cineast.core.data.FloatVectorImpl; -import org.vitrivr.cineast.core.data.Pair; -import org.vitrivr.cineast.core.data.ReadableFloatVector; -import org.vitrivr.cineast.core.data.score.ScoreElement; -import org.vitrivr.cineast.core.data.segments.SegmentContainer; -import org.vitrivr.cineast.core.db.PersistentTuple; -import org.vitrivr.cineast.core.db.setup.EntityCreator; -import org.vitrivr.cineast.core.features.abstracts.SubDivMotionHistogram; -import org.vitrivr.cineast.core.util.math.MathHelper; - -public class MotionHistogram extends SubDivMotionHistogram { - - public MotionHistogram() { - super("features_motionhistogram", FEATURE_COLUMN_QUALIFIER, MathHelper.SQRT2, 1); - } - - - @Override - public void processSegment(SegmentContainer shot) { - if (!phandler.idExists(shot.getId())) { - - Pair, ArrayList>> pair = getSubDivHist(1, shot.getPaths()); - - double sum = pair.first.get(0); - FloatVectorImpl fv = new FloatVectorImpl(pair.second.get(0)); - - persist(shot.getId(), sum, fv); - } - } - - protected void persist(String shotId, double sum, ReadableFloatVector fs) { - PersistentTuple tuple = this.phandler.generateTuple(shotId, sum, fs); - this.phandler.persist(tuple); - } - - @Override - public List getSimilar(SegmentContainer sc, ReadableQueryConfig qc) { - Pair, ArrayList>> pair = getSubDivHist(1, sc.getPaths()); - - FloatVectorImpl fv = new FloatVectorImpl(pair.second.get(0)); - return getSimilar(ReadableFloatVector.toArray(fv), qc); - } - - - @Override - public void initalizePersistentLayer(Supplier supply) { - supply.get().createFeatureEntity("features_MotionHistogram", true); - - } - -} diff --git a/cineast-core/src/main/java/org/vitrivr/cineast/core/features/MotionHistogramBackground.java b/cineast-core/src/main/java/org/vitrivr/cineast/core/features/MotionHistogramBackground.java deleted file mode 100644 index 640d1b291..000000000 --- a/cineast-core/src/main/java/org/vitrivr/cineast/core/features/MotionHistogramBackground.java +++ /dev/null @@ -1,61 +0,0 @@ -package org.vitrivr.cineast.core.features; - -import static org.vitrivr.cineast.core.util.CineastConstants.FEATURE_COLUMN_QUALIFIER; - -import java.util.ArrayList; -import java.util.List; -import java.util.function.Supplier; -import org.vitrivr.cineast.core.config.ReadableQueryConfig; -import org.vitrivr.cineast.core.data.FloatVectorImpl; -import org.vitrivr.cineast.core.data.Pair; -import org.vitrivr.cineast.core.data.ReadableFloatVector; -import org.vitrivr.cineast.core.data.score.ScoreElement; -import org.vitrivr.cineast.core.data.segments.SegmentContainer; -import org.vitrivr.cineast.core.db.PersistentTuple; -import org.vitrivr.cineast.core.db.setup.AttributeDefinition; -import org.vitrivr.cineast.core.db.setup.AttributeDefinition.AttributeType; -import org.vitrivr.cineast.core.db.setup.EntityCreator; -import org.vitrivr.cineast.core.features.abstracts.SubDivMotionHistogram; -import org.vitrivr.cineast.core.util.math.MathHelper; - -public class MotionHistogramBackground extends SubDivMotionHistogram { - - public MotionHistogramBackground() { - super("features_MotionHistogramBackground", FEATURE_COLUMN_QUALIFIER, MathHelper.SQRT2, 1); - } - - @Override - public void processSegment(SegmentContainer shot) { - if (!phandler.idExists(shot.getId())) { - - Pair, ArrayList>> pair = getSubDivHist(1, shot.getBgPaths()); - - double sum = pair.first.get(0); - FloatVectorImpl fv = new FloatVectorImpl(pair.second.get(0)); - - persist(shot.getId(), sum, fv); - } - } - - protected void persist(String shotId, double sum, ReadableFloatVector fs) { - PersistentTuple tuple = this.phandler.generateTuple(shotId, sum, fs); - this.phandler.persist(tuple); - } - - @Override - public List getSimilar(SegmentContainer sc, ReadableQueryConfig qc) { - Pair, ArrayList>> pair = getSubDivHist(1, sc.getBgPaths()); - - FloatVectorImpl fv = new FloatVectorImpl(pair.second.get(0)); - return getSimilar(ReadableFloatVector.toArray(fv), qc); - } - - @Override - public void initalizePersistentLayer(Supplier supply) { - supply.get().createFeatureEntity("features_MotionHistogramBackground", true, - new AttributeDefinition("sum", AttributeType.FLOAT), - new AttributeDefinition("hist", AttributeType.VECTOR)); - } - - -} diff --git a/cineast-core/src/main/java/org/vitrivr/cineast/core/features/OCRSearch.java b/cineast-core/src/main/java/org/vitrivr/cineast/core/features/OCRSearch.java index 97e8edbec..a24da8051 100644 --- a/cineast-core/src/main/java/org/vitrivr/cineast/core/features/OCRSearch.java +++ b/cineast-core/src/main/java/org/vitrivr/cineast/core/features/OCRSearch.java @@ -20,13 +20,13 @@ import org.vitrivr.cineast.core.data.entities.SimpleFulltextFeatureDescriptor; import org.vitrivr.cineast.core.data.segments.SegmentContainer; import org.vitrivr.cineast.core.features.abstracts.AbstractTextRetriever; -import org.vitrivr.cineast.core.util.HungarianAlgorithm; -import org.vitrivr.cineast.core.util.MultiTracker; -import org.vitrivr.cineast.core.util.NeedlemanWunschMerge; +import org.vitrivr.cineast.core.util.ocr.HungarianAlgorithm; +import org.vitrivr.cineast.core.util.ocr.MultiTracker; +import org.vitrivr.cineast.core.util.ocr.NeedlemanWunschMerge; import org.vitrivr.cineast.core.util.text.TextDetector_EAST; import org.vitrivr.cineast.core.util.text.TextRecognizer_CTC; import org.vitrivr.cineast.core.util.text.TextStream; -import org.vitrivr.cineast.core.util.ThreadLocalObjectCache; +import org.vitrivr.cineast.core.util.ocr.ThreadLocalObjectCache; /** * OCR is handled by adding fuzziness / levenshtein-distance support to the query if there are no quotes present (as quotes indicate precision) This makes sense here since we expect small errors from OCR sources diff --git a/cineast-core/src/main/java/org/vitrivr/cineast/core/features/SubDivMotionHistogram2.java b/cineast-core/src/main/java/org/vitrivr/cineast/core/features/SubDivMotionHistogram2.java deleted file mode 100644 index 038e97718..000000000 --- a/cineast-core/src/main/java/org/vitrivr/cineast/core/features/SubDivMotionHistogram2.java +++ /dev/null @@ -1,54 +0,0 @@ -package org.vitrivr.cineast.core.features; - -import java.util.ArrayList; -import java.util.List; -import org.vitrivr.cineast.core.config.ReadableQueryConfig; -import org.vitrivr.cineast.core.data.FloatVector; -import org.vitrivr.cineast.core.data.FloatVectorImpl; -import org.vitrivr.cineast.core.data.Pair; -import org.vitrivr.cineast.core.data.ReadableFloatVector; -import org.vitrivr.cineast.core.data.score.ScoreElement; -import org.vitrivr.cineast.core.data.segments.SegmentContainer; -import org.vitrivr.cineast.core.features.abstracts.SubDivMotionHistogram; -import org.vitrivr.cineast.core.util.math.MathHelper; - -public class SubDivMotionHistogram2 extends SubDivMotionHistogram { - - public SubDivMotionHistogram2() { - super("features_SubDivMotionHistogram2", "hists", MathHelper.SQRT2 * 4, 2); - } - - @Override - public void processSegment(SegmentContainer shot) { - if (!phandler.idExists(shot.getId())) { - - Pair, ArrayList>> pair = getSubDivHist(2, shot.getPaths()); - - FloatVector sum = new FloatVectorImpl(pair.first); - ArrayList tmp = new ArrayList(2 * 2 * 8); - for (List l : pair.second) { - for (float f : l) { - tmp.add(f); - } - } - FloatVectorImpl fv = new FloatVectorImpl(tmp); - - persist(shot.getId(), sum, fv); - } - } - - @Override - public List getSimilar(SegmentContainer sc, ReadableQueryConfig qc) { - Pair, ArrayList>> pair = getSubDivHist(2, sc.getPaths()); - ArrayList tmp = new ArrayList(2 * 2 * 8); - for (List l : pair.second) { - for (float f : l) { - tmp.add(f); - } - } - FloatVectorImpl fv = new FloatVectorImpl(tmp); - return getSimilar(ReadableFloatVector.toArray(fv), qc); - } - - -} diff --git a/cineast-core/src/main/java/org/vitrivr/cineast/core/features/SubDivMotionHistogram3.java b/cineast-core/src/main/java/org/vitrivr/cineast/core/features/SubDivMotionHistogram3.java deleted file mode 100644 index d4601e961..000000000 --- a/cineast-core/src/main/java/org/vitrivr/cineast/core/features/SubDivMotionHistogram3.java +++ /dev/null @@ -1,54 +0,0 @@ -package org.vitrivr.cineast.core.features; - -import java.util.ArrayList; -import java.util.List; -import org.vitrivr.cineast.core.config.ReadableQueryConfig; -import org.vitrivr.cineast.core.data.FloatVector; -import org.vitrivr.cineast.core.data.FloatVectorImpl; -import org.vitrivr.cineast.core.data.Pair; -import org.vitrivr.cineast.core.data.ReadableFloatVector; -import org.vitrivr.cineast.core.data.score.ScoreElement; -import org.vitrivr.cineast.core.data.segments.SegmentContainer; -import org.vitrivr.cineast.core.features.abstracts.SubDivMotionHistogram; -import org.vitrivr.cineast.core.util.math.MathHelper; - -public class SubDivMotionHistogram3 extends SubDivMotionHistogram { - - public SubDivMotionHistogram3() { - super("features_SubDivMotionHistogram3", "hists", MathHelper.SQRT2 * 9, 3); - } - - @Override - public void processSegment(SegmentContainer shot) { - if (!phandler.idExists(shot.getId())) { - - Pair, ArrayList>> pair = getSubDivHist(3, shot.getPaths()); - - FloatVector sum = new FloatVectorImpl(pair.first); - ArrayList tmp = new ArrayList(3 * 3 * 8); - for (List l : pair.second) { - for (float f : l) { - tmp.add(f); - } - } - FloatVectorImpl fv = new FloatVectorImpl(tmp); - - persist(shot.getId(), sum, fv); - } - } - - @Override - public List getSimilar(SegmentContainer sc, ReadableQueryConfig qc) { - Pair, ArrayList>> pair = getSubDivHist(3, sc.getPaths()); - - ArrayList tmp = new ArrayList(3 * 3 * 8); - for (List l : pair.second) { - for (float f : l) { - tmp.add(f); - } - } - FloatVectorImpl fv = new FloatVectorImpl(tmp); - return getSimilar(ReadableFloatVector.toArray(fv), qc); - } - -} diff --git a/cineast-core/src/main/java/org/vitrivr/cineast/core/features/SubDivMotionHistogram4.java b/cineast-core/src/main/java/org/vitrivr/cineast/core/features/SubDivMotionHistogram4.java deleted file mode 100644 index 7364efe25..000000000 --- a/cineast-core/src/main/java/org/vitrivr/cineast/core/features/SubDivMotionHistogram4.java +++ /dev/null @@ -1,55 +0,0 @@ -package org.vitrivr.cineast.core.features; - -import java.util.ArrayList; -import java.util.List; -import org.vitrivr.cineast.core.config.ReadableQueryConfig; -import org.vitrivr.cineast.core.data.FloatVector; -import org.vitrivr.cineast.core.data.FloatVectorImpl; -import org.vitrivr.cineast.core.data.Pair; -import org.vitrivr.cineast.core.data.ReadableFloatVector; -import org.vitrivr.cineast.core.data.score.ScoreElement; -import org.vitrivr.cineast.core.data.segments.SegmentContainer; -import org.vitrivr.cineast.core.features.abstracts.SubDivMotionHistogram; -import org.vitrivr.cineast.core.util.math.MathHelper; - -public class SubDivMotionHistogram4 extends SubDivMotionHistogram { - - public SubDivMotionHistogram4() { - super("features_SubDivMotionHistogram4", "hists", MathHelper.SQRT2 * 16, 4); - } - - @Override - public void processSegment(SegmentContainer shot) { - if (!phandler.idExists(shot.getId())) { - - Pair, ArrayList>> pair = getSubDivHist(4, shot.getPaths()); - - FloatVector sum = new FloatVectorImpl(pair.first); - ArrayList tmp = new ArrayList(4 * 4 * 8); - for (List l : pair.second) { - for (float f : l) { - tmp.add(f); - } - } - FloatVectorImpl fv = new FloatVectorImpl(tmp); - - persist(shot.getId(), sum, fv); - } - } - - @Override - public List getSimilar(SegmentContainer sc, ReadableQueryConfig qc) { - Pair, ArrayList>> pair = getSubDivHist(4, sc.getPaths()); - - ArrayList tmp = new ArrayList(4 * 4 * 8); - for (List l : pair.second) { - for (float f : l) { - tmp.add(f); - } - } - FloatVectorImpl fv = new FloatVectorImpl(tmp); - return getSimilar(ReadableFloatVector.toArray(fv), qc); - } - - -} diff --git a/cineast-core/src/main/java/org/vitrivr/cineast/core/features/SubDivMotionHistogram5.java b/cineast-core/src/main/java/org/vitrivr/cineast/core/features/SubDivMotionHistogram5.java deleted file mode 100644 index 57aedabfb..000000000 --- a/cineast-core/src/main/java/org/vitrivr/cineast/core/features/SubDivMotionHistogram5.java +++ /dev/null @@ -1,54 +0,0 @@ -package org.vitrivr.cineast.core.features; - -import java.util.ArrayList; -import java.util.List; -import org.vitrivr.cineast.core.config.ReadableQueryConfig; -import org.vitrivr.cineast.core.data.FloatVector; -import org.vitrivr.cineast.core.data.FloatVectorImpl; -import org.vitrivr.cineast.core.data.Pair; -import org.vitrivr.cineast.core.data.ReadableFloatVector; -import org.vitrivr.cineast.core.data.score.ScoreElement; -import org.vitrivr.cineast.core.data.segments.SegmentContainer; -import org.vitrivr.cineast.core.features.abstracts.SubDivMotionHistogram; -import org.vitrivr.cineast.core.util.math.MathHelper; - -public class SubDivMotionHistogram5 extends SubDivMotionHistogram { - - public SubDivMotionHistogram5() { - super("features_SubDivMotionHistogram5", "hists", MathHelper.SQRT2 * 25, 5); - } - - @Override - public void processSegment(SegmentContainer shot) { - if (!phandler.idExists(shot.getId())) { - - Pair, ArrayList>> pair = getSubDivHist(5, shot.getPaths()); - - FloatVector sum = new FloatVectorImpl(pair.first); - ArrayList tmp = new ArrayList(5 * 5 * 8); - for (List l : pair.second) { - for (float f : l) { - tmp.add(f); - } - } - FloatVectorImpl fv = new FloatVectorImpl(tmp); - - persist(shot.getId(), sum, fv); - } - } - - @Override - public List getSimilar(SegmentContainer sc, ReadableQueryConfig qc) { - Pair, ArrayList>> pair = getSubDivHist(5, sc.getPaths()); - - ArrayList tmp = new ArrayList(5 * 5 * 8); - for (List l : pair.second) { - for (float f : l) { - tmp.add(f); - } - } - FloatVectorImpl fv = new FloatVectorImpl(tmp); - return getSimilar(ReadableFloatVector.toArray(fv), qc); - } - -} diff --git a/cineast-core/src/main/java/org/vitrivr/cineast/core/features/SubDivMotionHistogramBackground2.java b/cineast-core/src/main/java/org/vitrivr/cineast/core/features/SubDivMotionHistogramBackground2.java deleted file mode 100644 index acffc6672..000000000 --- a/cineast-core/src/main/java/org/vitrivr/cineast/core/features/SubDivMotionHistogramBackground2.java +++ /dev/null @@ -1,54 +0,0 @@ -package org.vitrivr.cineast.core.features; - -import java.util.ArrayList; -import java.util.List; -import org.vitrivr.cineast.core.config.ReadableQueryConfig; -import org.vitrivr.cineast.core.data.FloatVector; -import org.vitrivr.cineast.core.data.FloatVectorImpl; -import org.vitrivr.cineast.core.data.Pair; -import org.vitrivr.cineast.core.data.ReadableFloatVector; -import org.vitrivr.cineast.core.data.score.ScoreElement; -import org.vitrivr.cineast.core.data.segments.SegmentContainer; -import org.vitrivr.cineast.core.features.abstracts.SubDivMotionHistogram; -import org.vitrivr.cineast.core.util.math.MathHelper; - -public class SubDivMotionHistogramBackground2 extends SubDivMotionHistogram { - - public SubDivMotionHistogramBackground2() { - super("features_SubDivMotionHistogramBackground2", "hists", MathHelper.SQRT2 * 4, 2); - } - - @Override - public void processSegment(SegmentContainer shot) { - if (!phandler.idExists(shot.getId())) { - - Pair, ArrayList>> pair = getSubDivHist(2, shot.getBgPaths()); - - FloatVector sum = new FloatVectorImpl(pair.first); - ArrayList tmp = new ArrayList(2 * 2 * 8); - for (List l : pair.second) { - for (float f : l) { - tmp.add(f); - } - } - FloatVectorImpl fv = new FloatVectorImpl(tmp); - - persist(shot.getId(), sum, fv); - } - } - - @Override - public List getSimilar(SegmentContainer sc, ReadableQueryConfig qc) { - Pair, ArrayList>> pair = getSubDivHist(2, sc.getBgPaths()); - ArrayList tmp = new ArrayList(2 * 2 * 8); - for (List l : pair.second) { - for (float f : l) { - tmp.add(f); - } - } - FloatVectorImpl fv = new FloatVectorImpl(tmp); - return getSimilar(ReadableFloatVector.toArray(fv), qc); - } - - -} diff --git a/cineast-core/src/main/java/org/vitrivr/cineast/core/features/SubDivMotionHistogramBackground3.java b/cineast-core/src/main/java/org/vitrivr/cineast/core/features/SubDivMotionHistogramBackground3.java deleted file mode 100644 index 451668033..000000000 --- a/cineast-core/src/main/java/org/vitrivr/cineast/core/features/SubDivMotionHistogramBackground3.java +++ /dev/null @@ -1,53 +0,0 @@ -package org.vitrivr.cineast.core.features; - -import java.util.ArrayList; -import java.util.List; -import org.vitrivr.cineast.core.config.ReadableQueryConfig; -import org.vitrivr.cineast.core.data.FloatVector; -import org.vitrivr.cineast.core.data.FloatVectorImpl; -import org.vitrivr.cineast.core.data.Pair; -import org.vitrivr.cineast.core.data.ReadableFloatVector; -import org.vitrivr.cineast.core.data.score.ScoreElement; -import org.vitrivr.cineast.core.data.segments.SegmentContainer; -import org.vitrivr.cineast.core.features.abstracts.SubDivMotionHistogram; -import org.vitrivr.cineast.core.util.math.MathHelper; - -public class SubDivMotionHistogramBackground3 extends SubDivMotionHistogram { - - public SubDivMotionHistogramBackground3() { - super("features_SubDivMotionHistogramBackground3", "hists", MathHelper.SQRT2 * 9, 3); - } - - @Override - public void processSegment(SegmentContainer shot) { - if (!phandler.idExists(shot.getId())) { - - Pair, ArrayList>> pair = getSubDivHist(3, shot.getBgPaths()); - - FloatVector sum = new FloatVectorImpl(pair.first); - ArrayList tmp = new ArrayList(3 * 3 * 8); - for (List l : pair.second) { - for (float f : l) { - tmp.add(f); - } - } - FloatVectorImpl fv = new FloatVectorImpl(tmp); - - persist(shot.getId(), sum, fv); - } - } - - @Override - public List getSimilar(SegmentContainer sc, ReadableQueryConfig qc) { - Pair, ArrayList>> pair = getSubDivHist(3, sc.getBgPaths()); - - ArrayList tmp = new ArrayList(3 * 3 * 8); - for (List l : pair.second) { - for (float f : l) { - tmp.add(f); - } - } - FloatVectorImpl fv = new FloatVectorImpl(tmp); - return getSimilar(ReadableFloatVector.toArray(fv), qc); - } -} diff --git a/cineast-core/src/main/java/org/vitrivr/cineast/core/features/SubDivMotionHistogramBackground4.java b/cineast-core/src/main/java/org/vitrivr/cineast/core/features/SubDivMotionHistogramBackground4.java deleted file mode 100644 index 84180120d..000000000 --- a/cineast-core/src/main/java/org/vitrivr/cineast/core/features/SubDivMotionHistogramBackground4.java +++ /dev/null @@ -1,53 +0,0 @@ -package org.vitrivr.cineast.core.features; - -import java.util.ArrayList; -import java.util.List; -import org.vitrivr.cineast.core.config.ReadableQueryConfig; -import org.vitrivr.cineast.core.data.FloatVector; -import org.vitrivr.cineast.core.data.FloatVectorImpl; -import org.vitrivr.cineast.core.data.Pair; -import org.vitrivr.cineast.core.data.ReadableFloatVector; -import org.vitrivr.cineast.core.data.score.ScoreElement; -import org.vitrivr.cineast.core.data.segments.SegmentContainer; -import org.vitrivr.cineast.core.features.abstracts.SubDivMotionHistogram; -import org.vitrivr.cineast.core.util.math.MathHelper; - -public class SubDivMotionHistogramBackground4 extends SubDivMotionHistogram { - - public SubDivMotionHistogramBackground4() { - super("features_SubDivMotionHistogramBackground4", "hists", MathHelper.SQRT2 * 16, 4); - } - - @Override - public void processSegment(SegmentContainer shot) { - if (!phandler.idExists(shot.getId())) { - - Pair, ArrayList>> pair = getSubDivHist(4, shot.getBgPaths()); - - FloatVector sum = new FloatVectorImpl(pair.first); - ArrayList tmp = new ArrayList(4 * 4 * 8); - for (List l : pair.second) { - for (float f : l) { - tmp.add(f); - } - } - FloatVectorImpl fv = new FloatVectorImpl(tmp); - - persist(shot.getId(), sum, fv); - } - } - - @Override - public List getSimilar(SegmentContainer sc, ReadableQueryConfig qc) { - Pair, ArrayList>> pair = getSubDivHist(4, sc.getBgPaths()); - - ArrayList tmp = new ArrayList(4 * 4 * 8); - for (List l : pair.second) { - for (float f : l) { - tmp.add(f); - } - } - FloatVectorImpl fv = new FloatVectorImpl(tmp); - return getSimilar(ReadableFloatVector.toArray(fv), qc); - } -} diff --git a/cineast-core/src/main/java/org/vitrivr/cineast/core/features/SubDivMotionHistogramBackground5.java b/cineast-core/src/main/java/org/vitrivr/cineast/core/features/SubDivMotionHistogramBackground5.java deleted file mode 100644 index 3fb552088..000000000 --- a/cineast-core/src/main/java/org/vitrivr/cineast/core/features/SubDivMotionHistogramBackground5.java +++ /dev/null @@ -1,54 +0,0 @@ -package org.vitrivr.cineast.core.features; - -import java.util.ArrayList; -import java.util.List; -import org.vitrivr.cineast.core.config.ReadableQueryConfig; -import org.vitrivr.cineast.core.data.FloatVector; -import org.vitrivr.cineast.core.data.FloatVectorImpl; -import org.vitrivr.cineast.core.data.Pair; -import org.vitrivr.cineast.core.data.ReadableFloatVector; -import org.vitrivr.cineast.core.data.score.ScoreElement; -import org.vitrivr.cineast.core.data.segments.SegmentContainer; -import org.vitrivr.cineast.core.features.abstracts.SubDivMotionHistogram; -import org.vitrivr.cineast.core.util.math.MathHelper; - -public class SubDivMotionHistogramBackground5 extends SubDivMotionHistogram { - - public SubDivMotionHistogramBackground5() { - super("features_SubDivMotionHistogramBackground5", "hists", MathHelper.SQRT2 * 25, 5); - } - - @Override - public void processSegment(SegmentContainer shot) { - if (!phandler.idExists(shot.getId())) { - - Pair, ArrayList>> pair = getSubDivHist(5, shot.getBgPaths()); - - FloatVector sum = new FloatVectorImpl(pair.first); - ArrayList tmp = new ArrayList(5 * 5 * 8); - for (List l : pair.second) { - for (float f : l) { - tmp.add(f); - } - } - FloatVectorImpl fv = new FloatVectorImpl(tmp); - - persist(shot.getId(), sum, fv); - } - } - - @Override - public List getSimilar(SegmentContainer sc, ReadableQueryConfig qc) { - Pair, ArrayList>> pair = getSubDivHist(5, sc.getBgPaths()); - - ArrayList tmp = new ArrayList(5 * 5 * 8); - for (List l : pair.second) { - for (float f : l) { - tmp.add(f); - } - } - FloatVectorImpl fv = new FloatVectorImpl(tmp); - return getSimilar(ReadableFloatVector.toArray(fv), qc); - } - -} diff --git a/cineast-core/src/main/java/org/vitrivr/cineast/core/features/SubDivMotionSum2.java b/cineast-core/src/main/java/org/vitrivr/cineast/core/features/SubDivMotionSum2.java deleted file mode 100644 index 0534929f0..000000000 --- a/cineast-core/src/main/java/org/vitrivr/cineast/core/features/SubDivMotionSum2.java +++ /dev/null @@ -1,27 +0,0 @@ -package org.vitrivr.cineast.core.features; - -import java.util.ArrayList; -import java.util.List; -import org.vitrivr.cineast.core.config.ReadableQueryConfig; -import org.vitrivr.cineast.core.data.FloatVectorImpl; -import org.vitrivr.cineast.core.data.Pair; -import org.vitrivr.cineast.core.data.ReadableFloatVector; -import org.vitrivr.cineast.core.data.score.ScoreElement; -import org.vitrivr.cineast.core.data.segments.SegmentContainer; -import org.vitrivr.cineast.core.features.abstracts.MotionHistogramCalculator; - -public class SubDivMotionSum2 extends MotionHistogramCalculator { - - public SubDivMotionSum2() { - super("features_SubDivMotionHistogram2", "sums", 400, 2); - } - - @Override - public List getSimilar(SegmentContainer sc, ReadableQueryConfig qc) { - Pair, ArrayList>> pair = getSubDivHist(2, sc.getPaths()); - - FloatVectorImpl fv = new FloatVectorImpl(pair.first); - return getSimilar(ReadableFloatVector.toArray(fv), qc); - } - -} diff --git a/cineast-core/src/main/java/org/vitrivr/cineast/core/features/SubDivMotionSum3.java b/cineast-core/src/main/java/org/vitrivr/cineast/core/features/SubDivMotionSum3.java deleted file mode 100644 index 9310011b2..000000000 --- a/cineast-core/src/main/java/org/vitrivr/cineast/core/features/SubDivMotionSum3.java +++ /dev/null @@ -1,27 +0,0 @@ -package org.vitrivr.cineast.core.features; - -import java.util.ArrayList; -import java.util.List; -import org.vitrivr.cineast.core.config.ReadableQueryConfig; -import org.vitrivr.cineast.core.data.FloatVectorImpl; -import org.vitrivr.cineast.core.data.Pair; -import org.vitrivr.cineast.core.data.ReadableFloatVector; -import org.vitrivr.cineast.core.data.score.ScoreElement; -import org.vitrivr.cineast.core.data.segments.SegmentContainer; -import org.vitrivr.cineast.core.features.abstracts.MotionHistogramCalculator; - -public class SubDivMotionSum3 extends MotionHistogramCalculator { - - public SubDivMotionSum3() { - super("features_SubDivMotionHistogram3", "sums", 900f, 3); - } - - @Override - public List getSimilar(SegmentContainer sc, ReadableQueryConfig qc) { - Pair, ArrayList>> pair = getSubDivHist(3, sc.getPaths()); - - FloatVectorImpl fv = new FloatVectorImpl(pair.first); - return getSimilar(ReadableFloatVector.toArray(fv), qc); - } - -} diff --git a/cineast-core/src/main/java/org/vitrivr/cineast/core/features/SubDivMotionSum4.java b/cineast-core/src/main/java/org/vitrivr/cineast/core/features/SubDivMotionSum4.java deleted file mode 100644 index 52ff159f6..000000000 --- a/cineast-core/src/main/java/org/vitrivr/cineast/core/features/SubDivMotionSum4.java +++ /dev/null @@ -1,28 +0,0 @@ -package org.vitrivr.cineast.core.features; - -import java.util.ArrayList; -import java.util.List; -import org.vitrivr.cineast.core.config.ReadableQueryConfig; -import org.vitrivr.cineast.core.data.FloatVectorImpl; -import org.vitrivr.cineast.core.data.Pair; -import org.vitrivr.cineast.core.data.ReadableFloatVector; -import org.vitrivr.cineast.core.data.score.ScoreElement; -import org.vitrivr.cineast.core.data.segments.SegmentContainer; -import org.vitrivr.cineast.core.features.abstracts.MotionHistogramCalculator; - -public class SubDivMotionSum4 extends MotionHistogramCalculator { - - - public SubDivMotionSum4() { - super("features_SubDivMotionHistogram4", "sums", 100 * 16, 4); - } - - @Override - public List getSimilar(SegmentContainer sc, ReadableQueryConfig qc) { - Pair, ArrayList>> pair = getSubDivHist(4, sc.getPaths()); - - FloatVectorImpl fv = new FloatVectorImpl(pair.first); - return getSimilar(ReadableFloatVector.toArray(fv), qc); - } - -} diff --git a/cineast-core/src/main/java/org/vitrivr/cineast/core/features/SubDivMotionSum5.java b/cineast-core/src/main/java/org/vitrivr/cineast/core/features/SubDivMotionSum5.java deleted file mode 100644 index 83a3b6bcd..000000000 --- a/cineast-core/src/main/java/org/vitrivr/cineast/core/features/SubDivMotionSum5.java +++ /dev/null @@ -1,27 +0,0 @@ -package org.vitrivr.cineast.core.features; - -import java.util.ArrayList; -import java.util.List; -import org.vitrivr.cineast.core.config.ReadableQueryConfig; -import org.vitrivr.cineast.core.data.FloatVectorImpl; -import org.vitrivr.cineast.core.data.Pair; -import org.vitrivr.cineast.core.data.ReadableFloatVector; -import org.vitrivr.cineast.core.data.score.ScoreElement; -import org.vitrivr.cineast.core.data.segments.SegmentContainer; -import org.vitrivr.cineast.core.features.abstracts.MotionHistogramCalculator; - -public class SubDivMotionSum5 extends MotionHistogramCalculator { - - - public SubDivMotionSum5() { - super("features_SubDivMotionHistogram5", "sums", 2500, 5); - } - - @Override - public List getSimilar(SegmentContainer sc, ReadableQueryConfig qc) { - Pair, ArrayList>> pair = getSubDivHist(5, sc.getBgPaths()); - FloatVectorImpl fv = new FloatVectorImpl(pair.first); - return getSimilar(ReadableFloatVector.toArray(fv), qc); - } - -} diff --git a/cineast-core/src/main/java/org/vitrivr/cineast/core/features/SubDivMotionSumBackground2.java b/cineast-core/src/main/java/org/vitrivr/cineast/core/features/SubDivMotionSumBackground2.java deleted file mode 100644 index d9fe71e7d..000000000 --- a/cineast-core/src/main/java/org/vitrivr/cineast/core/features/SubDivMotionSumBackground2.java +++ /dev/null @@ -1,26 +0,0 @@ -package org.vitrivr.cineast.core.features; - -import java.util.ArrayList; -import java.util.List; -import org.vitrivr.cineast.core.config.ReadableQueryConfig; -import org.vitrivr.cineast.core.data.FloatVectorImpl; -import org.vitrivr.cineast.core.data.Pair; -import org.vitrivr.cineast.core.data.ReadableFloatVector; -import org.vitrivr.cineast.core.data.score.ScoreElement; -import org.vitrivr.cineast.core.data.segments.SegmentContainer; -import org.vitrivr.cineast.core.features.abstracts.MotionHistogramCalculator; - -public class SubDivMotionSumBackground2 extends MotionHistogramCalculator { - - public SubDivMotionSumBackground2() { - super("features_SubDivMotionHistogramBackground2", "sums", 400, 2); - } - - @Override - public List getSimilar(SegmentContainer sc, ReadableQueryConfig qc) { - Pair, ArrayList>> pair = getSubDivHist(2, sc.getBgPaths()); - - FloatVectorImpl fv = new FloatVectorImpl(pair.first); - return getSimilar(ReadableFloatVector.toArray(fv), qc); - } -} diff --git a/cineast-core/src/main/java/org/vitrivr/cineast/core/features/SubDivMotionSumBackground3.java b/cineast-core/src/main/java/org/vitrivr/cineast/core/features/SubDivMotionSumBackground3.java deleted file mode 100644 index 371d1785b..000000000 --- a/cineast-core/src/main/java/org/vitrivr/cineast/core/features/SubDivMotionSumBackground3.java +++ /dev/null @@ -1,27 +0,0 @@ -package org.vitrivr.cineast.core.features; - -import java.util.ArrayList; -import java.util.List; -import org.vitrivr.cineast.core.config.ReadableQueryConfig; -import org.vitrivr.cineast.core.data.FloatVectorImpl; -import org.vitrivr.cineast.core.data.Pair; -import org.vitrivr.cineast.core.data.ReadableFloatVector; -import org.vitrivr.cineast.core.data.score.ScoreElement; -import org.vitrivr.cineast.core.data.segments.SegmentContainer; -import org.vitrivr.cineast.core.features.abstracts.MotionHistogramCalculator; - -public class SubDivMotionSumBackground3 extends MotionHistogramCalculator { - - public SubDivMotionSumBackground3() { - super("features_SubDivMotionHistogramBackground3", "sums", 900f, 3); - } - - @Override - public List getSimilar(SegmentContainer sc, ReadableQueryConfig qc) { - Pair, ArrayList>> pair = getSubDivHist(3, sc.getBgPaths()); - - FloatVectorImpl fv = new FloatVectorImpl(pair.first); - return getSimilar(ReadableFloatVector.toArray(fv), qc); - } - -} diff --git a/cineast-core/src/main/java/org/vitrivr/cineast/core/features/SubDivMotionSumBackground4.java b/cineast-core/src/main/java/org/vitrivr/cineast/core/features/SubDivMotionSumBackground4.java deleted file mode 100644 index dafc12a93..000000000 --- a/cineast-core/src/main/java/org/vitrivr/cineast/core/features/SubDivMotionSumBackground4.java +++ /dev/null @@ -1,28 +0,0 @@ -package org.vitrivr.cineast.core.features; - -import java.util.ArrayList; -import java.util.List; -import org.vitrivr.cineast.core.config.ReadableQueryConfig; -import org.vitrivr.cineast.core.data.FloatVectorImpl; -import org.vitrivr.cineast.core.data.Pair; -import org.vitrivr.cineast.core.data.ReadableFloatVector; -import org.vitrivr.cineast.core.data.score.ScoreElement; -import org.vitrivr.cineast.core.data.segments.SegmentContainer; -import org.vitrivr.cineast.core.features.abstracts.MotionHistogramCalculator; - -public class SubDivMotionSumBackground4 extends MotionHistogramCalculator { - - - public SubDivMotionSumBackground4() { - super("features_SubDivMotionHistogramBackground4", "sums", 100 * 16, 4); - } - - @Override - public List getSimilar(SegmentContainer sc, ReadableQueryConfig qc) { - Pair, ArrayList>> pair = getSubDivHist(4, sc.getBgPaths()); - - FloatVectorImpl fv = new FloatVectorImpl(pair.first); - return getSimilar(ReadableFloatVector.toArray(fv), qc); - } - -} diff --git a/cineast-core/src/main/java/org/vitrivr/cineast/core/features/SubDivMotionSumBackground5.java b/cineast-core/src/main/java/org/vitrivr/cineast/core/features/SubDivMotionSumBackground5.java deleted file mode 100644 index 37b4f931b..000000000 --- a/cineast-core/src/main/java/org/vitrivr/cineast/core/features/SubDivMotionSumBackground5.java +++ /dev/null @@ -1,27 +0,0 @@ -package org.vitrivr.cineast.core.features; - -import java.util.ArrayList; -import java.util.List; -import org.vitrivr.cineast.core.config.ReadableQueryConfig; -import org.vitrivr.cineast.core.data.FloatVectorImpl; -import org.vitrivr.cineast.core.data.Pair; -import org.vitrivr.cineast.core.data.ReadableFloatVector; -import org.vitrivr.cineast.core.data.score.ScoreElement; -import org.vitrivr.cineast.core.data.segments.SegmentContainer; -import org.vitrivr.cineast.core.features.abstracts.MotionHistogramCalculator; - -public class SubDivMotionSumBackground5 extends MotionHistogramCalculator { - - - public SubDivMotionSumBackground5() { - super("features.SubDivMotionHistogramBackground5", "sums", 2500, 5); - } - - @Override - public List getSimilar(SegmentContainer sc, ReadableQueryConfig qc) { - Pair, ArrayList>> pair = getSubDivHist(5, sc.getBgPaths()); - FloatVectorImpl fv = new FloatVectorImpl(pair.first); - return getSimilar(ReadableFloatVector.toArray(fv), qc); - } - -} diff --git a/cineast-core/src/main/java/org/vitrivr/cineast/core/features/WSDMTICollectionBooleanRetriever.java b/cineast-core/src/main/java/org/vitrivr/cineast/core/features/WSDMTICollectionBooleanRetriever.java deleted file mode 100644 index 268fdec6c..000000000 --- a/cineast-core/src/main/java/org/vitrivr/cineast/core/features/WSDMTICollectionBooleanRetriever.java +++ /dev/null @@ -1,11 +0,0 @@ -package org.vitrivr.cineast.core.features; - -import java.util.Arrays; -import org.vitrivr.cineast.core.features.retriever.CollectionBooleanRetriever; - -public class WSDMTICollectionBooleanRetriever extends CollectionBooleanRetriever { - - public WSDMTICollectionBooleanRetriever() { - super("features_wsdmtiannotations", Arrays.asList("annotation", "object")); - } -} \ No newline at end of file diff --git a/cineast-core/src/main/java/org/vitrivr/cineast/core/features/abstracts/MotionHistogramCalculator.java b/cineast-core/src/main/java/org/vitrivr/cineast/core/features/abstracts/MotionHistogramCalculator.java deleted file mode 100644 index c6a1e1bf0..000000000 --- a/cineast-core/src/main/java/org/vitrivr/cineast/core/features/abstracts/MotionHistogramCalculator.java +++ /dev/null @@ -1,159 +0,0 @@ -package org.vitrivr.cineast.core.features.abstracts; - -import static org.vitrivr.cineast.core.util.CineastConstants.GENERIC_ID_COLUMN_QUALIFIER; - -import georegression.struct.point.Point2D_F32; -import java.util.ArrayList; -import java.util.Collections; -import java.util.Iterator; -import java.util.LinkedList; -import java.util.List; -import java.util.function.Supplier; -import org.vitrivr.cineast.core.config.QueryConfig; -import org.vitrivr.cineast.core.config.ReadableQueryConfig; -import org.vitrivr.cineast.core.config.ReadableQueryConfig.Distance; -import org.vitrivr.cineast.core.data.CorrespondenceFunction; -import org.vitrivr.cineast.core.data.Pair; -import org.vitrivr.cineast.core.data.distance.DistanceElement; -import org.vitrivr.cineast.core.data.distance.SegmentDistanceElement; -import org.vitrivr.cineast.core.data.providers.primitive.StringTypeProvider; -import org.vitrivr.cineast.core.data.score.ScoreElement; -import org.vitrivr.cineast.core.db.DBSelector; -import org.vitrivr.cineast.core.db.DBSelectorSupplier; -import org.vitrivr.cineast.core.db.setup.AttributeDefinition; -import org.vitrivr.cineast.core.db.setup.AttributeDefinition.AttributeType; -import org.vitrivr.cineast.core.db.setup.EntityCreator; -import org.vitrivr.cineast.core.features.retriever.Retriever; - -public abstract class MotionHistogramCalculator implements Retriever { - - protected DBSelector selector; - protected final float maxDist; - protected final CorrespondenceFunction linearCorrespondence; - protected final String tableName; - protected final String fieldName; - private final int vectorLength; - - protected MotionHistogramCalculator(String tableName, String fieldName, float maxDist, int cells) { - this.maxDist = maxDist; - this.linearCorrespondence = CorrespondenceFunction.linear(this.maxDist); - this.tableName = tableName; - this.fieldName = fieldName; - this.vectorLength = cells * cells; - } - - @Override - public void init(DBSelectorSupplier supply) { - this.selector = supply.get(); - this.selector.open(tableName); - } - - @Override - public List getTableNames() { - return Collections.singletonList(tableName); - } - - private static int getidx(int subdiv, float x, float y) { - int ix = (int) Math.floor(subdiv * x); - int iy = (int) Math.floor(subdiv * y); - ix = Math.max(Math.min(ix, subdiv - 1), 0); - iy = Math.max(Math.min(iy, subdiv - 1), 0); - - return ix * subdiv + iy; - } - - protected Pair, ArrayList>> getSubDivHist( - int subdiv, List>> list) { - - double[] sums = new double[subdiv * subdiv]; - float[][] hists = new float[subdiv * subdiv][8]; - - for (Pair> pair : list) { - LinkedList path = pair.second; - if (path.size() > 1) { - Iterator iter = path.iterator(); - Point2D_F32 last = iter.next(); - while (iter.hasNext()) { - Point2D_F32 current = iter.next(); - double dx = current.x - last.x; - double dy = current.y - last.y; - int idx = ((int) Math.floor(4 * Math.atan2(dy, dx) - / Math.PI) + 4) % 8; - double len = Math.sqrt(dx * dx + dy * dy); - hists[getidx(subdiv, last.x, last.y)][idx] += len; - last = current; - } - } - } - - for (int i = 0; i < sums.length; ++i) { - float[] hist = hists[i]; - double sum = 0; - for (float v : hist) { - sum += v; - } - if (sum > 0) { - for (int j = 0; j < hist.length; ++j) { - hist[j] /= sum; - } - hists[i] = hist; - } - sums[i] = sum; - } - - ArrayList sumList = new ArrayList<>(sums.length); - for (double d : sums) { - sumList.add(d); - } - - ArrayList> histList = new ArrayList<>( - hists.length); - for (float[] hist : hists) { - ArrayList h = new ArrayList<>(8); - for (float f : hist) { - h.add(f); - } - histList.add(h); - } - - return new Pair<>(sumList, - histList); - } - - protected List getSimilar(float[] vector, ReadableQueryConfig qc) { - ReadableQueryConfig qcc = setQueryConfig(qc); - List distances = this.selector.getNearestNeighboursGeneric(qcc.getResultsPerModule(), vector, this.fieldName, SegmentDistanceElement.class, qcc); - return DistanceElement.toScore(distances, qcc.getCorrespondenceFunction().get()); - } - - @Override - public List getSimilar(String segmentId, ReadableQueryConfig qc) { - List list = this.selector.getFeatureVectors(GENERIC_ID_COLUMN_QUALIFIER, new StringTypeProvider(segmentId), this.fieldName, qc); - if (list.isEmpty()) { - return new ArrayList<>(1); - } - return getSimilar(list.get(0), qc); - } - - @Override - public void finish() { - if (this.selector != null) { - this.selector.close(); - } - } - - @Override - public void initalizePersistentLayer(Supplier supply) { - supply.get().createFeatureEntity(this.tableName, true, new AttributeDefinition("hist", AttributeType.VECTOR, vectorLength * 8), new AttributeDefinition("sums", AttributeType.VECTOR, vectorLength)); - } - - @Override - public void dropPersistentLayer(Supplier supply) { - supply.get().dropEntity(this.tableName); - } - - protected ReadableQueryConfig setQueryConfig(ReadableQueryConfig qc) { - return QueryConfig.clone(qc).setDistanceIfEmpty(Distance.chisquared) - .setCorrespondenceFunctionIfEmpty(this.linearCorrespondence); - } -} diff --git a/cineast-core/src/main/java/org/vitrivr/cineast/core/features/abstracts/SubDivMotionHistogram.java b/cineast-core/src/main/java/org/vitrivr/cineast/core/features/abstracts/SubDivMotionHistogram.java deleted file mode 100644 index 4809cccbd..000000000 --- a/cineast-core/src/main/java/org/vitrivr/cineast/core/features/abstracts/SubDivMotionHistogram.java +++ /dev/null @@ -1,50 +0,0 @@ -package org.vitrivr.cineast.core.features.abstracts; - -import static org.vitrivr.cineast.core.util.CineastConstants.GENERIC_ID_COLUMN_QUALIFIER; - -import java.util.List; -import org.vitrivr.cineast.core.config.ReadableQueryConfig; -import org.vitrivr.cineast.core.data.ReadableFloatVector; -import org.vitrivr.cineast.core.data.distance.DistanceElement; -import org.vitrivr.cineast.core.data.distance.SegmentDistanceElement; -import org.vitrivr.cineast.core.data.score.ScoreElement; -import org.vitrivr.cineast.core.db.PersistencyWriter; -import org.vitrivr.cineast.core.db.PersistencyWriterSupplier; -import org.vitrivr.cineast.core.db.PersistentTuple; -import org.vitrivr.cineast.core.features.extractor.Extractor; - -public abstract class SubDivMotionHistogram extends MotionHistogramCalculator implements Extractor { - - protected PersistencyWriter phandler; - - protected SubDivMotionHistogram(String tableName, String fieldName, double maxDist, int cells) { - super(tableName, fieldName, (float) maxDist, cells); - } - - @Override - public void init(PersistencyWriterSupplier supply) { - this.phandler = supply.get(); - this.phandler.open(this.tableName); - this.phandler.setFieldNames(GENERIC_ID_COLUMN_QUALIFIER, "sums", "hist"); - } - - protected void persist(String shotId, ReadableFloatVector fs1, ReadableFloatVector fs2) { - PersistentTuple tuple = this.phandler.generateTuple(shotId, fs1, fs2); - this.phandler.persist(tuple); - } - - @Override - protected List getSimilar(float[] vector, ReadableQueryConfig qc) { - ReadableQueryConfig rqc = setQueryConfig(qc); - List distances = this.selector.getNearestNeighboursGeneric(qc.getResultsPerModule(), vector, "hist", SegmentDistanceElement.class, qc); - return DistanceElement.toScore(distances, rqc.getCorrespondenceFunction().get()); - } - - @Override - public void finish() { - if (this.phandler != null) { - this.phandler.close(); - } - super.finish(); - } -} diff --git a/cineast-core/src/main/java/org/vitrivr/cineast/core/features/exporter/MotionFrameExporter.java b/cineast-core/src/main/java/org/vitrivr/cineast/core/features/exporter/MotionFrameExporter.java deleted file mode 100644 index c2813af17..000000000 --- a/cineast-core/src/main/java/org/vitrivr/cineast/core/features/exporter/MotionFrameExporter.java +++ /dev/null @@ -1,122 +0,0 @@ -package org.vitrivr.cineast.core.features.exporter; - -import georegression.struct.point.Point2D_F32; -import java.awt.Color; -import java.awt.Graphics2D; -import java.awt.image.BufferedImage; -import java.io.File; -import java.io.IOException; -import java.util.HashMap; -import java.util.Iterator; -import java.util.LinkedList; -import java.util.List; -import java.util.function.Supplier; -import javax.imageio.ImageIO; -import org.vitrivr.cineast.core.data.Pair; -import org.vitrivr.cineast.core.data.frames.VideoFrame; -import org.vitrivr.cineast.core.data.segments.SegmentContainer; -import org.vitrivr.cineast.core.db.PersistencyWriterSupplier; -import org.vitrivr.cineast.core.db.setup.EntityCreator; -import org.vitrivr.cineast.core.features.extractor.Extractor; - -public class MotionFrameExporter implements Extractor { - - private static final String PROPERTY_NAME_DESTINATION = "destination"; - - private final File folder; - - /** - * Default constructor - no parameters. - */ - public MotionFrameExporter() { - this(new HashMap<>()); - } - - /** - * Constructor with property HashMap that allows for passing of parameters. - *

- * Supported parameters: - * - *

    - *
  1. destination: Path where motion frameimages should be stored.
  2. - *
- * - * @param properties HashMap containing named properties - */ - public MotionFrameExporter(HashMap properties) { - this.folder = new File(properties.getOrDefault(PROPERTY_NAME_DESTINATION, "./motion_frames")); - } - - - @Override - public void init(PersistencyWriterSupplier phandlerSupply) { - if (!folder.exists()) { - folder.mkdirs(); - } - } - - @Override - public void processSegment(SegmentContainer shot) { - List>> paths = shot.getPaths(); - for (VideoFrame f : shot.getVideoFrames()) { - File file = new File(folder, String.format("%06d", f.getId()) + ".jpg"); - BufferedImage bimg = f.getImage().getBufferedImage(); - for (Pair> pair : paths) { - draw(bimg, pair.second); - } - try { - ImageIO.write(bimg, "jpg", file); - } catch (IOException e) { - // TODO Auto-generated catch block - e.printStackTrace(); - } - } - - } - - private static Color[] colors = new Color[]{ - new Color(255, 0, 0), - new Color(230, 30, 0), - new Color(205, 55, 0), - new Color(180, 80, 0), - new Color(155, 105, 0), - new Color(130, 130, 0), - new Color(105, 155, 0), - new Color(80, 180, 0), - new Color(55, 205, 0), - new Color(30, 230, 0), - new Color(0, 255, 0), - - }; - - //private static BasicStroke fgStroke = new BasicStroke(1f, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND); - - public static void draw(BufferedImage img, LinkedList path) { - int col = 0, width = img.getWidth(), height = img.getHeight(); - if (path.size() > 1) { - Graphics2D g = (Graphics2D) img.getGraphics(); - Iterator iter = path.iterator(); - Point2D_F32 last = iter.next(); - //g.setStroke(fgStroke); - while (iter.hasNext()) { - g.setColor(colors[col]); - col = (col + 1) % colors.length; - Point2D_F32 current = iter.next(); - g.drawLine((int) (last.x * width), (int) (last.y * height), (int) (current.x * width), (int) (current.y * height)); - last = current; - } - } - } - - @Override - public void finish() { - } - - @Override - public void initalizePersistentLayer(Supplier supply) { - } - - @Override - public void dropPersistentLayer(Supplier supply) { - } -} diff --git a/cineast-core/src/main/java/org/vitrivr/cineast/core/features/exporter/MotionHistoryImageExporter.java b/cineast-core/src/main/java/org/vitrivr/cineast/core/features/exporter/MotionHistoryImageExporter.java deleted file mode 100644 index 6776b520b..000000000 --- a/cineast-core/src/main/java/org/vitrivr/cineast/core/features/exporter/MotionHistoryImageExporter.java +++ /dev/null @@ -1,89 +0,0 @@ -package org.vitrivr.cineast.core.features.exporter; - -import java.awt.image.BufferedImage; -import java.io.File; -import java.io.IOException; -import java.util.HashMap; -import java.util.function.Supplier; -import javax.imageio.ImageIO; -import org.apache.logging.log4j.LogManager; -import org.apache.logging.log4j.Logger; -import org.vitrivr.cineast.core.color.ReadableRGBContainer; -import org.vitrivr.cineast.core.data.segments.SegmentContainer; -import org.vitrivr.cineast.core.db.PersistencyWriterSupplier; -import org.vitrivr.cineast.core.db.setup.EntityCreator; -import org.vitrivr.cineast.core.features.extractor.Extractor; -import org.vitrivr.cineast.core.util.LogHelper; -import org.vitrivr.cineast.core.util.MotionHistoryImage; - -public class MotionHistoryImageExporter implements Extractor { - - private static final String PROPERTY_NAME_DESTINATION = "destination"; - private static final String PROPERTY_NAME_FORMAT = "format"; - private static final Logger LOGGER = LogManager.getLogger(); - - private final File folder; - private final String format; - - /** - * Default constructor - no parameters. - */ - public MotionHistoryImageExporter() { - this(new HashMap<>()); - } - - /** - * Constructor with property HashMap that allows for passing of parameters. - *

- * Supported parameters: - * - *

    - *
  1. destination: Path where motion history image images should be stored.
  2. - *
- * - * @param properties HashMap containing named properties - */ - public MotionHistoryImageExporter(HashMap properties) { - this.folder = new File(properties.getOrDefault(PROPERTY_NAME_DESTINATION, "./motion_history")); - this.format = properties.getOrDefault(PROPERTY_NAME_FORMAT, "PNG"); - } - - @Override - public void init(PersistencyWriterSupplier phandlerSupply) { - if (!this.folder.exists()) { - this.folder.mkdirs(); - } - } - - @Override - public void processSegment(SegmentContainer shot) { - MotionHistoryImage mhi = MotionHistoryImage.motionHistoryImage(shot, 30, 30); - if (mhi == null) { - return; - } - BufferedImage img = new BufferedImage(mhi.getWidth(), mhi.getHeight(), BufferedImage.TYPE_INT_RGB); - int[] colors = new int[mhi.getIntensities().length]; - for (int i = 0; i < colors.length; ++i) { - int c = mhi.getIntensities()[i] * 2; - colors[i] = ReadableRGBContainer.toIntColor(c, c, c); - } - img.setRGB(0, 0, img.getWidth(), img.getHeight(), colors, 0, img.getWidth()); - try { - ImageIO.write(img, format, new File(folder, String.format("%s.%s", shot.getId(), this.format.toLowerCase()))); - } catch (IOException e) { - LOGGER.error("Error while exporting motion history image: {}", LogHelper.getStackTrace(e)); - } - } - - @Override - public void finish() { - } - - @Override - public void initalizePersistentLayer(Supplier supply) { - } - - @Override - public void dropPersistentLayer(Supplier supply) { - } -} diff --git a/cineast-core/src/main/java/org/vitrivr/cineast/core/features/retriever/CollectionBooleanRetriever.java b/cineast-core/src/main/java/org/vitrivr/cineast/core/features/retriever/CollectionBooleanRetriever.java deleted file mode 100644 index 36bca615f..000000000 --- a/cineast-core/src/main/java/org/vitrivr/cineast/core/features/retriever/CollectionBooleanRetriever.java +++ /dev/null @@ -1,33 +0,0 @@ -package org.vitrivr.cineast.core.features.retriever; - -import java.util.Arrays; -import java.util.Collection; -import java.util.Collections; -import java.util.List; -import java.util.Map; -import org.vitrivr.cineast.core.db.RelationalOperator; -import org.vitrivr.cineast.core.features.abstracts.BooleanRetriever; - -public class CollectionBooleanRetriever extends BooleanRetriever { - - private static final List SUPPORTED_OPERATORS = - Collections.unmodifiableList( - Arrays.asList( - RelationalOperator.EQ, - RelationalOperator.NEQ, - RelationalOperator.IN, - RelationalOperator.LIKE)); - - protected CollectionBooleanRetriever(String entity, Collection attributes) { - super(entity, attributes); - } - - protected CollectionBooleanRetriever(Map properties) { - super(properties); - } - - @Override - protected Collection getSupportedOperators() { - return SUPPORTED_OPERATORS; - } -} diff --git a/cineast-core/src/main/java/org/vitrivr/cineast/core/importer/TupleInsertMessageImporter.java b/cineast-core/src/main/java/org/vitrivr/cineast/core/importer/TupleInsertMessageImporter.java deleted file mode 100644 index 1a8b43b5c..000000000 --- a/cineast-core/src/main/java/org/vitrivr/cineast/core/importer/TupleInsertMessageImporter.java +++ /dev/null @@ -1,57 +0,0 @@ -package org.vitrivr.cineast.core.importer; - -import java.io.EOFException; -import java.io.File; -import java.io.FileInputStream; -import java.io.FileNotFoundException; -import java.io.IOException; -import java.util.HashMap; -import java.util.Map; -import org.apache.logging.log4j.LogManager; -import org.apache.logging.log4j.Logger; -import org.vitrivr.adampro.grpc.AdamGrpc.DataMessage; -import org.vitrivr.adampro.grpc.AdamGrpc.InsertMessage.TupleInsertMessage; -import org.vitrivr.cineast.core.data.providers.primitive.PrimitiveTypeProvider; -import org.vitrivr.cineast.core.db.DataMessageConverter; - -public class TupleInsertMessageImporter implements Importer { - - private final FileInputStream inStream; - private static final Logger LOGGER = LogManager.getLogger(); - - public TupleInsertMessageImporter(File inputFile) throws FileNotFoundException { - this.inStream = new FileInputStream(inputFile); - } - - @Override - public TupleInsertMessage readNext() { - while (true) { - try { - return TupleInsertMessage.parseDelimitedFrom(this.inStream); - } catch (EOFException eof) { - return null; - } catch (IOException e) { - LOGGER.error("error while reading TupleInsertMessage, skipping"); - } - } - } - - @Override - public Map convert(TupleInsertMessage message) { - if (message == null) { - return null; - } - - Map data = message.getDataMap(); - - HashMap map = new HashMap<>(); - - for (String key : data.keySet()) { - map.put(key, DataMessageConverter.convert(data.get(key))); - } - - return map; - } - - -} diff --git a/cineast-core/src/main/java/org/vitrivr/cineast/core/temporal/AbstractTemporalScoringAlgorithm.java b/cineast-core/src/main/java/org/vitrivr/cineast/core/temporal/AbstractTemporalScoringAlgorithm.java index e83706f67..66aaa89cc 100644 --- a/cineast-core/src/main/java/org/vitrivr/cineast/core/temporal/AbstractTemporalScoringAlgorithm.java +++ b/cineast-core/src/main/java/org/vitrivr/cineast/core/temporal/AbstractTemporalScoringAlgorithm.java @@ -1,11 +1,12 @@ package org.vitrivr.cineast.core.temporal; -import io.netty.util.collection.IntObjectHashMap; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.TreeSet; import java.util.stream.Collectors; + +import it.unimi.dsi.fastutil.ints.Int2ObjectLinkedOpenHashMap; import org.vitrivr.cineast.core.data.StringDoublePair; import org.vitrivr.cineast.core.data.TemporalObject; import org.vitrivr.cineast.core.data.entities.MediaSegmentDescriptor; @@ -55,7 +56,7 @@ protected AbstractTemporalScoringAlgorithm(Map s /* Else assign the scored segment to the ScoredSegment and if there is already a scored Segment present att this score to the one present. */ - scoredSegmentStorage.putIfAbsent(segmentDescriptor.getSegmentId(), new IntObjectHashMap<>()); + scoredSegmentStorage.putIfAbsent(segmentDescriptor.getSegmentId(), new Int2ObjectLinkedOpenHashMap<>()); if (scoredSegmentStorage.get(segmentDescriptor.getSegmentId()).containsKey(currentContainerId)) { scoredSegmentStorage.get(segmentDescriptor.getSegmentId()).get(currentContainerId).addScore(stringDoublePair); } else { diff --git a/cineast-core/src/main/java/org/vitrivr/cineast/core/util/MotionHistoryImage.java b/cineast-core/src/main/java/org/vitrivr/cineast/core/util/MotionHistoryImage.java deleted file mode 100644 index dfe9523dd..000000000 --- a/cineast-core/src/main/java/org/vitrivr/cineast/core/util/MotionHistoryImage.java +++ /dev/null @@ -1,98 +0,0 @@ -package org.vitrivr.cineast.core.util; - -import java.util.ArrayList; -import org.vitrivr.cineast.core.color.ReadableRGBContainer; -import org.vitrivr.cineast.core.data.frames.VideoFrame; -import org.vitrivr.cineast.core.data.raw.images.MultiImage; -import org.vitrivr.cineast.core.data.segments.SegmentContainer; - -public class MotionHistoryImage { - - private MotionHistoryImage(int width, int height) { - this.width = width; - this.height = height; - this.intensities = new byte[width * height]; - } - - private final int width, height; - private final byte[] intensities; - - public int getWidth() { - return this.width; - } - - public int getHeight() { - return this.height; - } - - public byte[] getIntensities() { - return this.intensities; - } - - public static MotionHistoryImage motionHistoryImage(SegmentContainer container, int lifeTime, int threshold) { - return motionHistoryImage(container, lifeTime, threshold, true); - } - - /** - * @param lifeTime number of frames to consider for image - * @param threshold threshold distance [0, 255] - * @param useThumbnails produce image based on thumbnails to entire frame - */ - public static MotionHistoryImage motionHistoryImage(SegmentContainer container, int lifeTime, int threshold, boolean useThumbnails) { - if (container.getVideoFrames().isEmpty()) { - return null; - } - - ArrayList images = new ArrayList(container.getVideoFrames().size()); - for (VideoFrame f : container.getVideoFrames()) { - if (useThumbnails) { - images.add(f.getImage().getThumbnailColors()); - } else { - images.add(f.getImage().getColors()); - } - } - - MultiImage first = container.getVideoFrames().get(0).getImage(); - - MotionHistoryImage _return = new MotionHistoryImage( - useThumbnails ? first.getThumbnailImage().getWidth() : first.getWidth(), - useThumbnails ? first.getThumbnailImage().getHeight() : first.getHeight()); - - if (container.getVideoFrames().size() == 1) { - return _return; - } - - float sub = 1f / lifeTime; - - float[] tmp = new float[images.get(0).length]; - for (int i = 1; i < images.size(); ++i) { - int[] current = images.get(i); - int[] last = images.get(i - 1); - - for (int j = 0; j < current.length; ++j) { - int dist = dist(last[j], current[j]); - if (dist > threshold) { - tmp[j] = 1f; - } else { - tmp[j] = Math.max(0f, tmp[j] - sub); - } - } - - } - - for (int i = 0; i < tmp.length; ++i) { - _return.intensities[i] = (byte) Math.round(127f * tmp[i]); - } - - return _return; - } - - private static int dist(int color1, int color2) { - - float l1 = 0.2126f * ReadableRGBContainer.getRed(color1) + 0.7152f * ReadableRGBContainer.getGreen(color1) + 0.0722f * ReadableRGBContainer.getBlue(color1); - float l2 = 0.2126f * ReadableRGBContainer.getRed(color2) + 0.7152f * ReadableRGBContainer.getGreen(color2) + 0.0722f * ReadableRGBContainer.getBlue(color2); - - return Math.round(Math.abs(l1 - l2)); - } - -} diff --git a/cineast-core/src/main/java/org/vitrivr/cineast/core/util/RandomStringGenerator.java b/cineast-core/src/main/java/org/vitrivr/cineast/core/util/RandomStringGenerator.java deleted file mode 100644 index ce5f2f8bd..000000000 --- a/cineast-core/src/main/java/org/vitrivr/cineast/core/util/RandomStringGenerator.java +++ /dev/null @@ -1,83 +0,0 @@ -package org.vitrivr.cineast.core.util; - -import java.util.Random; - -/** - * Generates random strings to be used for Ids - */ -public class RandomStringGenerator { - - private RandomStringGenerator() { - } - - public static final int DEFAULT_LENGTH = 16; - public static final char[] DEFAULT_ALPHABET = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', - 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', - 't', 'u', 'v', 'w', 'x', 'y', 'z', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', - 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z'}; - - private static final Random r = new Random(); - - public static String generateRandomString(String prefix, int length, char[] alphabet) { - return generateRandomString(r, prefix, length, alphabet); - } - - public static String generateRandomString(int length, char[] alphabet) { - return generateRandomString("", length, alphabet); - } - - public static String generateRandomString(int length) { - return generateRandomString(length, DEFAULT_ALPHABET); - } - - public static String generateRandomString(String prefix, int length) { - return generateRandomString(prefix, length, DEFAULT_ALPHABET); - } - - public static String generateRandomString(String prefix) { - return generateRandomString(prefix, DEFAULT_LENGTH); - } - - public static String generateRandomString() { - return generateRandomString("", DEFAULT_LENGTH, DEFAULT_ALPHABET); - } - - /** - * Generates a random string from a given alphabet with a given length. The prefix of the string can be optionally specified. - * - * @param random the random number generator to be used for string generation - * @param prefix the prefix for the generated string. if null is provided, the string will have no prefix. - * @param length the length of the string to generate, must be positive - * @param alphabet the set of characters from which to generate the string - */ - public static String generateRandomString(Random random, String prefix, int length, - char[] alphabet) { - if (random == null) { - throw new NullPointerException("random cannot be null"); - } - if (length <= 0) { - throw new IllegalArgumentException("length must be positive"); - } - if (prefix.length() >= length) { - throw new IllegalArgumentException("prefix must be shorter than length of output"); - } - if (alphabet == null) { - throw new NullPointerException("alphabet cannot be null"); - } - if (alphabet.length == 0) { - throw new IllegalArgumentException("alphabet cannot be empty"); - } - - StringBuilder sb = new StringBuilder(); - if (prefix != null) { - sb.append(prefix); - } - - for (int l = sb.length(); l < length; ++l) { - sb.append(alphabet[random.nextInt(alphabet.length)]); - } - - return sb.toString(); - } - -} diff --git a/cineast-core/src/main/java/org/vitrivr/cineast/core/util/TagsPerSegment.java b/cineast-core/src/main/java/org/vitrivr/cineast/core/util/TagsPerSegment.java deleted file mode 100644 index 7c4e9a7d9..000000000 --- a/cineast-core/src/main/java/org/vitrivr/cineast/core/util/TagsPerSegment.java +++ /dev/null @@ -1,43 +0,0 @@ -package org.vitrivr.cineast.core.util; - -import java.util.Collections; -import java.util.HashSet; -import java.util.Set; - -public class TagsPerSegment { - - public Set tags; - public String segmentID; - - public Set getTags() { - return tags; - } - - public void setTags(Set tags) { - this.tags = tags; - } - - public String getSegmentID() { - return segmentID; - } - - - public TagsPerSegment(String segmentID, Set tags) { - this.segmentID = segmentID; - this.tags = tags; - } - - public TagsPerSegment(String segmentID, String tag) { - this.segmentID = segmentID; - this.tags = new HashSet<>(Collections.singleton(tag)); - } - - - public boolean addTags(String tag) { - return this.tags.add(tag); - } - - -} - - diff --git a/cineast-core/src/main/java/org/vitrivr/cineast/core/util/HungarianAlgorithm.java b/cineast-core/src/main/java/org/vitrivr/cineast/core/util/ocr/HungarianAlgorithm.java similarity index 99% rename from cineast-core/src/main/java/org/vitrivr/cineast/core/util/HungarianAlgorithm.java rename to cineast-core/src/main/java/org/vitrivr/cineast/core/util/ocr/HungarianAlgorithm.java index 5817d038b..a2a336847 100644 --- a/cineast-core/src/main/java/org/vitrivr/cineast/core/util/HungarianAlgorithm.java +++ b/cineast-core/src/main/java/org/vitrivr/cineast/core/util/ocr/HungarianAlgorithm.java @@ -1,4 +1,4 @@ -package org.vitrivr.cineast.core.util; +package org.vitrivr.cineast.core.util.ocr; import java.util.Arrays; diff --git a/cineast-core/src/main/java/org/vitrivr/cineast/core/util/MultiTracker.java b/cineast-core/src/main/java/org/vitrivr/cineast/core/util/ocr/MultiTracker.java similarity index 98% rename from cineast-core/src/main/java/org/vitrivr/cineast/core/util/MultiTracker.java rename to cineast-core/src/main/java/org/vitrivr/cineast/core/util/ocr/MultiTracker.java index 03efead6f..9f535f223 100644 --- a/cineast-core/src/main/java/org/vitrivr/cineast/core/util/MultiTracker.java +++ b/cineast-core/src/main/java/org/vitrivr/cineast/core/util/ocr/MultiTracker.java @@ -1,4 +1,4 @@ -package org.vitrivr.cineast.core.util; +package org.vitrivr.cineast.core.util.ocr; import boofcv.abst.tracker.TrackerObjectQuad; import boofcv.factory.tracker.FactoryTrackerObjectQuad; diff --git a/cineast-core/src/main/java/org/vitrivr/cineast/core/util/NeedlemanWunschMerge.java b/cineast-core/src/main/java/org/vitrivr/cineast/core/util/ocr/NeedlemanWunschMerge.java similarity index 98% rename from cineast-core/src/main/java/org/vitrivr/cineast/core/util/NeedlemanWunschMerge.java rename to cineast-core/src/main/java/org/vitrivr/cineast/core/util/ocr/NeedlemanWunschMerge.java index f99e7e3ca..532ca64ec 100644 --- a/cineast-core/src/main/java/org/vitrivr/cineast/core/util/NeedlemanWunschMerge.java +++ b/cineast-core/src/main/java/org/vitrivr/cineast/core/util/ocr/NeedlemanWunschMerge.java @@ -1,4 +1,4 @@ -package org.vitrivr.cineast.core.util; +package org.vitrivr.cineast.core.util.ocr; /** * NeedlemanWunschMerge takes two (ideally similar) strings and is able to return a substring which is similar in both strings diff --git a/cineast-core/src/main/java/org/vitrivr/cineast/core/util/ThreadLocalObjectCache.java b/cineast-core/src/main/java/org/vitrivr/cineast/core/util/ocr/ThreadLocalObjectCache.java similarity index 94% rename from cineast-core/src/main/java/org/vitrivr/cineast/core/util/ThreadLocalObjectCache.java rename to cineast-core/src/main/java/org/vitrivr/cineast/core/util/ocr/ThreadLocalObjectCache.java index 6a9a640b0..ddf64ef94 100644 --- a/cineast-core/src/main/java/org/vitrivr/cineast/core/util/ThreadLocalObjectCache.java +++ b/cineast-core/src/main/java/org/vitrivr/cineast/core/util/ocr/ThreadLocalObjectCache.java @@ -1,4 +1,4 @@ -package org.vitrivr.cineast.core.util; +package org.vitrivr.cineast.core.util.ocr; import com.google.common.cache.CacheBuilder; import com.google.common.cache.CacheLoader; diff --git a/cineast-core/src/test/java/org/vitrivr/cineast/core/db/DBBooleanIntegrationTest.java b/cineast-core/src/test/java/org/vitrivr/cineast/core/db/DBBooleanIntegrationTest.java index c01df330f..12dc1ae5c 100644 --- a/cineast-core/src/test/java/org/vitrivr/cineast/core/db/DBBooleanIntegrationTest.java +++ b/cineast-core/src/test/java/org/vitrivr/cineast/core/db/DBBooleanIntegrationTest.java @@ -1,7 +1,6 @@ package org.vitrivr.cineast.core.db; import static java.util.Arrays.asList; -import static org.hamcrest.CoreMatchers.hasItem; import static org.junit.jupiter.api.Assumptions.assumeTrue; import java.util.ArrayList; @@ -13,14 +12,11 @@ import org.apache.commons.lang3.tuple.Triple; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; -import org.hamcrest.MatcherAssert; -import org.junit.Ignore; import org.junit.jupiter.api.AfterAll; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.TestInstance; @@ -189,8 +185,9 @@ public void testInQuery() { values.add(PrimitiveTypeProvider.fromObject(-idToCheck)); values.add(PrimitiveTypeProvider.fromObject(-(idToCheck - 1))); List> result = selector.getRows(DATA_COL_NAME_2, values); - MatcherAssert.assertThat(result.stream().map(el -> el.get(ID_COL_NAME).getString()).collect(Collectors.toList()), hasItem(String.valueOf(idToCheck))); - MatcherAssert.assertThat(result.stream().map(el -> el.get(ID_COL_NAME).getString()).collect(Collectors.toList()), hasItem(String.valueOf(idToCheck - 1))); + var list = result.stream().map(el -> el.get(ID_COL_NAME).getString()).collect(Collectors.toList()); + Assertions.assertTrue(hasItem(list, String.valueOf(idToCheck))); + Assertions.assertTrue(hasItem(list, String.valueOf(idToCheck - 1))); } @Test @@ -202,8 +199,9 @@ public void testBetweenQuery() { values.add(PrimitiveTypeProvider.fromObject(-idToCheck)); values.add(PrimitiveTypeProvider.fromObject(-(idToCheck - 1))); final List> result = selector.getRows(DATA_COL_NAME_2, RelationalOperator.BETWEEN, values); - MatcherAssert.assertThat(result.stream().map(el -> el.get(ID_COL_NAME).getString()).collect(Collectors.toList()), hasItem(String.valueOf(idToCheck))); - MatcherAssert.assertThat(result.stream().map(el -> el.get(ID_COL_NAME).getString()).collect(Collectors.toList()), hasItem(String.valueOf(idToCheck - 1))); + var list = result.stream().map(el -> el.get(ID_COL_NAME).getString()).collect(Collectors.toList()); + Assertions.assertTrue(hasItem(list, String.valueOf(idToCheck))); + Assertions.assertTrue(hasItem(list, String.valueOf(idToCheck - 1))); } @Test @@ -211,11 +209,14 @@ public void testBetweenQuery() { public void testGreaterQuery() { this.selector.open(testTableName); int idToCheck = TABLE_CARD - 2; // query for greater than second-highest value - if (idToCheck < -1) Assertions.fail(); // cardinality should be higher than 2 + if (idToCheck < -1) { + Assertions.fail(); // cardinality should be higher than 2 + } final List values = new ArrayList<>(); values.add(PrimitiveTypeProvider.fromObject(idToCheck)); final List> result = selector.getRows(ID_COL_NAME, RelationalOperator.GREATER, values); - MatcherAssert.assertThat(result.stream().map(el -> el.get(ID_COL_NAME).getString()).collect(Collectors.toList()), hasItem(String.valueOf(TABLE_CARD - 1))); + var list = result.stream().map(el -> el.get(ID_COL_NAME).getString()).collect(Collectors.toList()); + Assertions.assertTrue(hasItem(list, String.valueOf(TABLE_CARD - 1))); } @Test @@ -226,7 +227,8 @@ public void testLessQuery() { final List values = new ArrayList<>(); values.add(PrimitiveTypeProvider.fromObject(idToCheck)); final List> result = selector.getRows(ID_COL_NAME, RelationalOperator.LESS, values); - MatcherAssert.assertThat(result.stream().map(el -> el.get(ID_COL_NAME).getString()).collect(Collectors.toList()), hasItem(String.valueOf(0))); + var list = result.stream().map(el -> el.get(ID_COL_NAME).getString()).collect(Collectors.toList()); + Assertions.assertTrue(hasItem(list, String.valueOf(0))); } @@ -249,8 +251,9 @@ public void testBetweenANDBetweenQuery() { final Triple> element2 = new ImmutableTriple<>(ID_COL_NAME, RelationalOperator.BETWEEN, values2); final List> result = selector.getRowsAND(asList(element1, element2), ID_COL_NAME, asList(ID_COL_NAME), null); + var list = result.stream().map(el -> el.get(ID_COL_NAME).getString()).collect(Collectors.toList()); + Assertions.assertTrue(hasItem(list, String.valueOf(idToCheck + 1))); - MatcherAssert.assertThat(result.stream().map(el -> el.get(ID_COL_NAME).getString()).collect(Collectors.toList()), hasItem(String.valueOf(idToCheck + 1))); Assertions.assertEquals(1, result.size()); } @@ -274,10 +277,14 @@ public void testBetweenANDInQuery() { final Triple> element2 = new ImmutableTriple<>(ID_COL_NAME, RelationalOperator.IN, values2); final List> result = selector.getRowsAND(asList(element1, element2), ID_COL_NAME, asList(ID_COL_NAME), null); - - MatcherAssert.assertThat(result.stream().map(el -> el.get(ID_COL_NAME).getString()).collect(Collectors.toList()), hasItem(String.valueOf(idToCheck - 1))); - MatcherAssert.assertThat(result.stream().map(el -> el.get(ID_COL_NAME).getString()).collect(Collectors.toList()), hasItem(String.valueOf(idToCheck + 1))); + var list = result.stream().map(el -> el.get(ID_COL_NAME).getString()).collect(Collectors.toList()); + Assertions.assertTrue(hasItem(list, String.valueOf(idToCheck - 1))); + Assertions.assertTrue(hasItem(list, String.valueOf(idToCheck + 1))); Assertions.assertEquals(2, result.size()); } + private boolean hasItem(List list, String s) { + return list.stream().anyMatch(e -> e.equals(s)); + } + } diff --git a/cineast-core/src/test/java/org/vitrivr/cineast/core/db/polyphenydb/PolyphenyBooleanIntegrationTest.java b/cineast-core/src/test/java/org/vitrivr/cineast/core/db/polyphenydb/PolyphenyBooleanIntegrationTest.java index c7b4f7a14..f837e0492 100644 --- a/cineast-core/src/test/java/org/vitrivr/cineast/core/db/polyphenydb/PolyphenyBooleanIntegrationTest.java +++ b/cineast-core/src/test/java/org/vitrivr/cineast/core/db/polyphenydb/PolyphenyBooleanIntegrationTest.java @@ -1,57 +1,51 @@ package org.vitrivr.cineast.core.db.polyphenydb; -import java.sql.PreparedStatement; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import org.junit.Test; -import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Disabled; -import org.junit.jupiter.api.DisplayName; -import org.vitrivr.cineast.core.data.providers.primitive.PrimitiveTypeProvider; +import org.junit.jupiter.api.Test; import org.vitrivr.cineast.core.db.DBBooleanIntegrationTest; import org.vitrivr.cineast.core.db.IntegrationDBProvider; -import org.vitrivr.cineast.core.db.cottontaildb.CottontailIntegrationDBProvider; import org.vitrivr.cineast.core.db.setup.AttributeDefinition; import org.vitrivr.cineast.core.db.setup.AttributeDefinition.AttributeType; -import org.vitrivr.cottontail.client.language.dml.Insert; + +import java.sql.PreparedStatement; +import java.util.HashMap; public class PolyphenyBooleanIntegrationTest extends DBBooleanIntegrationTest { - private final PolyphenyIntegrationDBProvider _provider; + private final PolyphenyIntegrationDBProvider _provider; + + public PolyphenyBooleanIntegrationTest() { + try { + _provider = new PolyphenyIntegrationDBProvider(); + } catch (Throwable e) { + LOGGER.error("Error occurred while starting and connecting to Polypheny: " + e.getMessage()); + throw e; + } + } + + /** + * Create table for boolean retrieval + */ + @Override + protected void createTables() { + final HashMap hints = new HashMap<>(); + hints.put("pk", "true"); + ec.createEntity(testTableName, new AttributeDefinition(ID_COL_NAME, AttributeType.INT, hints), new AttributeDefinition(DATA_COL_NAME_1, AttributeType.TEXT), new AttributeDefinition(DATA_COL_NAME_2, AttributeType.INT), new AttributeDefinition(DATA_COL_NAME_3, AttributeType.INT)); + } + + @Override + protected void finishSetup() { + } + + @Override + protected IntegrationDBProvider provider() { + return _provider; + } - public PolyphenyBooleanIntegrationTest() { - try { - _provider = new PolyphenyIntegrationDBProvider(); - } catch (Throwable e) { - LOGGER.error("Error occurred while starting and connecting to Polypheny: " + e.getMessage()); - throw e; + @Test + @Override + @Disabled + public void testFulltextQuery() { + /* TODO: Not supported on Polypheny DB yet. */ } - } - - /** - * Create table for boolean retrieval - */ - @Override - protected void createTables() { - final HashMap hints = new HashMap<>(); - hints.put("pk", "true"); - ec.createEntity(testTableName, new AttributeDefinition(ID_COL_NAME, AttributeType.INT, hints), new AttributeDefinition(DATA_COL_NAME_1, AttributeType.TEXT), new AttributeDefinition(DATA_COL_NAME_2, AttributeType.INT), new AttributeDefinition(DATA_COL_NAME_3, AttributeType.INT)); - } - - @Override - protected void finishSetup() { - } - - @Override - protected IntegrationDBProvider provider() { - return _provider; - } - - @Test - @Override - @Disabled - public void testFulltextQuery() { - /* TODO: Not supported on Polypheny DB yet. */ - } } diff --git a/cineast-runtime/src/main/java/org/vitrivr/cineast/standalone/cli/ImportCommand.java b/cineast-runtime/src/main/java/org/vitrivr/cineast/standalone/cli/ImportCommand.java index c437a7502..531c8a88f 100644 --- a/cineast-runtime/src/main/java/org/vitrivr/cineast/standalone/cli/ImportCommand.java +++ b/cineast-runtime/src/main/java/org/vitrivr/cineast/standalone/cli/ImportCommand.java @@ -3,34 +3,14 @@ import com.github.rvesse.airline.annotations.Command; import com.github.rvesse.airline.annotations.Option; import com.github.rvesse.airline.annotations.restrictions.Required; -import java.nio.file.Path; -import java.nio.file.Paths; -import java.util.ArrayList; -import java.util.List; import org.vitrivr.cineast.core.db.DataSource; import org.vitrivr.cineast.standalone.config.Config; -import org.vitrivr.cineast.standalone.importer.handlers.AsrDataImportHandler; import org.vitrivr.cineast.standalone.importer.handlers.DataImportHandler; import org.vitrivr.cineast.standalone.importer.handlers.JsonDataImportHandler; import org.vitrivr.cineast.standalone.importer.handlers.LIREImportHandler; -import org.vitrivr.cineast.standalone.importer.handlers.OcrDataImportHandler; -import org.vitrivr.cineast.standalone.importer.handlers.ProtoDataImportHandler; -import org.vitrivr.cineast.standalone.importer.lsc2020.CaptionImportHandler; -import org.vitrivr.cineast.standalone.importer.lsc2020.LSCAllTagsImportHandler; -import org.vitrivr.cineast.standalone.importer.lsc2020.MetaImportHandler; -import org.vitrivr.cineast.standalone.importer.lsc2020.MyscealTagImportHandler; -import org.vitrivr.cineast.standalone.importer.lsc2020.OCRImportHandler; -import org.vitrivr.cineast.standalone.importer.lsc2020.ProcessingMetaImportHandler; -import org.vitrivr.cineast.standalone.importer.lsc2020.ProcessingMetaImportHandler.Mode; -import org.vitrivr.cineast.standalone.importer.lsc2020.SpatialImportHandler; -import org.vitrivr.cineast.standalone.importer.lsc2020.VisualConceptTagImportHandler; -import org.vitrivr.cineast.standalone.importer.vbs2019.AudioTranscriptImportHandler; -import org.vitrivr.cineast.standalone.importer.vbs2019.CaptionTextImportHandler; -import org.vitrivr.cineast.standalone.importer.vbs2019.GoogleVisionImportHandler; -import org.vitrivr.cineast.standalone.importer.vbs2019.ObjectMetadataImportHandler; -import org.vitrivr.cineast.standalone.importer.vbs2019.TagImportHandler; -import org.vitrivr.cineast.standalone.importer.vbs2019.gvision.GoogleVisionCategory; -import org.vitrivr.cineast.standalone.importer.vbs2019.v3c1analysis.ColorlabelImportHandler; + +import java.nio.file.Path; +import java.nio.file.Paths; /** * A CLI command that can be used to start import of pre-extracted data. @@ -38,135 +18,65 @@ @Command(name = "import", description = "Starts import of pre-extracted data.") public class ImportCommand implements Runnable { - @Required - @Option(name = {"-t", "--type"}, description = "Type of data import that should be started.") - private String type; - - @Required - @Option(name = {"-i", "--input"}, description = "The source file or folder for data import. If a folder is specified, the entire content will be considered for import.") - private String input; + @Required + @Option(name = {"-t", "--type"}, description = "Type of data import that should be started.") + private String type; - @Option(name = {"--threads"}, description = "Level of parallelization for import") - private int threads = 2; + @Required + @Option(name = {"-i", "--input"}, description = "The source file or folder for data import. If a folder is specified, the entire content will be considered for import.") + private String input; - @Option(name = {"-b", "--batchsize"}, description = "The batch size used for the import. Imported data will be persisted in batches of the specified size.") - private int batchsize = 500; + @Option(name = {"--threads"}, description = "Level of parallelization for import") + private int threads = 2; - @Option(name = {"-c", "--clean"}, description = "Cleans, i.e. drops the tables before import. Use with caution, as the already imported data will be lost! Requires the import type to respect this option") - private boolean clean = false; + @Option(name = {"-b", "--batchsize"}, description = "The batch size used for the import. Imported data will be persisted in batches of the specified size.") + private int batchsize = 500; - @Option(name = {"--no-finalize"}, title = "Do Not Finalize", description = "If this flag is not set, automatically rebuilds indices & optimizes all entities when writing to cottontail after the import. Set this flag when you want more performance with external parallelism.") - private boolean doNotFinalize = false; + @Option(name = {"-c", "--clean"}, description = "Cleans, i.e. drops the tables before import. Use with caution, as the already imported data will be lost! Requires the import type to respect this option") + private boolean clean = false; - @Option(name = {"--no-transactions"}, title = "Do Not Use Transactions", description = "If this flag is not set, the default behavior is used which means transactions are enabled during import. Set this flag when you want more performance and manage transactional aspects yourself.") - private boolean noTransactions = false; + @Option(name = {"--no-finalize"}, title = "Do Not Finalize", description = "If this flag is not set, automatically rebuilds indices & optimizes all entities when writing to cottontail after the import. Set this flag when you want more performance with external parallelism.") + private boolean doNotFinalize = false; - @Override - public void run() { - System.out.printf("Starting import of type %s for '%s'. Batchsize %d, %d threads. Clean %b, no-finalize %b .%n", this.type, this.input, this.batchsize, this.threads, this.clean, this.doNotFinalize); - final Path path = Paths.get(this.input); - if(noTransactions){ - Config.sharedConfig().getDatabase().setUseTransactions(false); - } - final ImportType type = ImportType.valueOf(this.type.toUpperCase()); - DataImportHandler handler = null; - boolean isGoogleVision = false; - switch (type) { - case PROTO: - handler = new ProtoDataImportHandler(this.threads, this.batchsize); - break; - case JSON: - handler = new JsonDataImportHandler(this.threads, this.batchsize); - break; - case LIRE: - handler = new LIREImportHandler(this.threads, this.batchsize); - break; - case ASR: - handler = new AsrDataImportHandler(this.threads, this.batchsize); - break; - case OCR: - handler = new OcrDataImportHandler(this.threads, this.batchsize); - break; - case CAPTIONING: - handler = new CaptionTextImportHandler(this.threads, this.batchsize); - break; - case AUDIO: - handler = new AudioTranscriptImportHandler(this.threads, this.batchsize); - break; - case TAGS: - handler = new TagImportHandler(this.threads, this.batchsize); - break; - case METADATA: - handler = new ObjectMetadataImportHandler(this.threads, this.batchsize); - break; - case GOOGLEVISION: - doVisionImport(path); - isGoogleVision = true; - break; - case V3C1COLORLABELS: - /* Be aware that this is metadata which might already be comprised in merged vbs metadata */ - handler = new ColorlabelImportHandler(this.threads, this.batchsize); - break; - case LSCMETA: - handler = new MetaImportHandler(this.threads, this.batchsize, this.clean); - break; - case LSCCONCEPT: - handler = new VisualConceptTagImportHandler(this.threads, this.batchsize); - break; - case LSCCAPTION: - handler = new CaptionImportHandler(this.threads, this.batchsize); - break; - case LSCX: - handler = new ProcessingMetaImportHandler(this.threads, this.batchsize, Mode.TAGS, clean); - break; - case LSCTABLE: - handler = new ProcessingMetaImportHandler(this.threads, this.batchsize, Mode.TABLE, clean); - break; - case LSCTAGSALL: - handler = new LSCAllTagsImportHandler(this.threads, this.batchsize, clean); - break; - case LSCOCR: - handler = new OCRImportHandler(this.threads, this.batchsize, clean); - break; - case LSCSPATIAL: - handler = new SpatialImportHandler(this.threads, this.batchsize); - break; - case LSC21TAGS: - handler = new MyscealTagImportHandler(this.threads, this.batchsize); - break; - } - if (!isGoogleVision) { - if (handler == null) { - throw new RuntimeException("Cannot do import as the handler was not properly registered. Import type: " + type); - } else { - handler.doImport(path); - handler.waitForCompletion(); - } - } + @Option(name = {"--no-transactions"}, title = "Do Not Use Transactions", description = "If this flag is not set, the default behavior is used which means transactions are enabled during import. Set this flag when you want more performance and manage transactional aspects yourself.") + private boolean noTransactions = false; - /* Only attempt to optimize Cottontail entities if we were importing into Cottontail, otherwise an unavoidable error message would be displayed when importing elsewhere. */ - if (!doNotFinalize && Config.sharedConfig().getDatabase().getSelector() == DataSource.COTTONTAIL && Config.sharedConfig().getDatabase().getWriter() == DataSource.COTTONTAIL) { - OptimizeEntitiesCommand.optimizeAllCottontailEntities(); - } + @Override + public void run() { + System.out.printf("Starting import of type %s for '%s'. Batchsize %d, %d threads. Clean %b, no-finalize %b .%n", this.type, this.input, this.batchsize, this.threads, this.clean, this.doNotFinalize); + final Path path = Paths.get(this.input); + if (noTransactions) { + Config.sharedConfig().getDatabase().setUseTransactions(false); + } + final ImportType type = ImportType.valueOf(this.type.toUpperCase()); + DataImportHandler handler = null; + switch (type) { + case JSON: + handler = new JsonDataImportHandler(this.threads, this.batchsize); + break; + case LIRE: + handler = new LIREImportHandler(this.threads, this.batchsize); + break; + } + if (handler == null) { + throw new RuntimeException("Cannot do import as the handler was not properly registered. Import type: " + type); + } else { + handler.doImport(path); + handler.waitForCompletion(); + } - System.out.printf("Completed import of type %s for '%s'.%n", this.type, this.input); - } + /* Only attempt to optimize Cottontail entities if we were importing into Cottontail, otherwise an unavoidable error message would be displayed when importing elsewhere. */ + if (!doNotFinalize && Config.sharedConfig().getDatabase().getSelector() == DataSource.COTTONTAIL && Config.sharedConfig().getDatabase().getWriter() == DataSource.COTTONTAIL) { + OptimizeEntitiesCommand.optimizeAllCottontailEntities(); + } - /** - * From VBS 21+ on, in uniqueTagInstances.tsv we have all google vision tags deduplicated - */ - private void doVisionImport(Path path) { - List handlers = new ArrayList<>(); - GoogleVisionImportHandler _handler = new GoogleVisionImportHandler(this.threads, this.batchsize, GoogleVisionCategory.OCR, false); - _handler.doImport(path); - handlers.add(_handler); - handlers.forEach(GoogleVisionImportHandler::waitForCompletion); - } + System.out.printf("Completed import of type %s for '%s'.%n", this.type, this.input); + } - /** - * Enum of the available types of data imports. - */ - private enum ImportType { - PROTO, JSON, LIRE, ASR, OCR, AUDIO, TAGS, METADATA, CAPTIONING, GOOGLEVISION, V3C1COLORLABELS, LSCMETA, LSCCONCEPT, LSCCAPTION, LSCX, LSCTABLE, LSCTAGSALL, LSCOCR, LSCSPATIAL, LSC21TAGS - } + /** + * Enum of the available types of data imports. + */ + private enum ImportType { + JSON, LIRE + } } diff --git a/cineast-runtime/src/main/java/org/vitrivr/cineast/standalone/cli/RetrieveCommand.java b/cineast-runtime/src/main/java/org/vitrivr/cineast/standalone/cli/RetrieveCommand.java index 8ba89451e..b659e07e5 100644 --- a/cineast-runtime/src/main/java/org/vitrivr/cineast/standalone/cli/RetrieveCommand.java +++ b/cineast-runtime/src/main/java/org/vitrivr/cineast/standalone/cli/RetrieveCommand.java @@ -8,7 +8,6 @@ import org.vitrivr.cineast.core.data.score.SegmentScoreElement; import org.vitrivr.cineast.standalone.config.Config; import org.vitrivr.cineast.standalone.config.ConstrainedQueryConfig; -import org.vitrivr.cineast.standalone.listener.RetrievalResultCSVExporter; import org.vitrivr.cineast.standalone.util.ContinuousRetrievalLogic; @@ -21,17 +20,11 @@ public class RetrieveCommand implements Runnable { @Option(name = {"-c", "--category"}, title = "Category", description = "Name of the feature category to retrieve. By default, all categories are searched") private String category; - @Option(name = {"-e", "--export"}, title = "Export", description = "Indicates whether the results should be exported. Defaults to false.") - private boolean export = false; - @Option(name = {"-r", "--relevantSegments"}, title = "Relevant segments", description = "Comma separated list of segment IDs to which the query is to be limited.") private String relevantSegments; public void run() { final ContinuousRetrievalLogic retrieval = new ContinuousRetrievalLogic(Config.sharedConfig().getDatabase()); - if (export) { - retrieval.addRetrievalResultListener(new RetrievalResultCSVExporter(Config.sharedConfig().getDatabase())); - } QueryConfig qc = QueryConfig.newQueryConfigFromOther(new ConstrainedQueryConfig("cli-query", new ArrayList<>())); diff --git a/cineast-runtime/src/main/java/org/vitrivr/cineast/standalone/cli/TextRetrievalCommand.java b/cineast-runtime/src/main/java/org/vitrivr/cineast/standalone/cli/TextRetrievalCommand.java index 83354309f..a9c954726 100644 --- a/cineast-runtime/src/main/java/org/vitrivr/cineast/standalone/cli/TextRetrievalCommand.java +++ b/cineast-runtime/src/main/java/org/vitrivr/cineast/standalone/cli/TextRetrievalCommand.java @@ -34,7 +34,6 @@ public void run() { retrievers.add(new SubtitleFulltextSearch()); retrievers.add(new OCRSearch()); retrievers.add(new AudioTranscriptionSearch()); - retrievers.add(new DescriptionTextSearch()); CliUtils.retrieveAndLog(retrievers, retrieval, limit, printDetail, qc); System.out.println("Done"); } diff --git a/cineast-runtime/src/main/java/org/vitrivr/cineast/standalone/config/ExplorativeConfig.java b/cineast-runtime/src/main/java/org/vitrivr/cineast/standalone/config/ExplorativeConfig.java deleted file mode 100644 index 6a38662c5..000000000 --- a/cineast-runtime/src/main/java/org/vitrivr/cineast/standalone/config/ExplorativeConfig.java +++ /dev/null @@ -1,70 +0,0 @@ -package org.vitrivr.cineast.standalone.config; - -import com.fasterxml.jackson.annotation.JsonCreator; -import java.io.File; -import java.io.FileInputStream; -import java.util.Properties; - - -public class ExplorativeConfig { - - private static String csvPath = "/Users/silvanstich/Library/Containers/com.apple.mail/Data/Library/Mail Downloads/CA01A1C7-162D-454F-9645-8F9250035697/neuralnet_vgg16_fullvector"; - private static String featureName = "nn_vecotrs"; - private static String elementLimit = "1000"; - private static String dataFolder = "data/"; - private static String resultFolder = "results/html/experimental/"; - private static String treeSerializationFileName = "nn_serialized_tree.ser"; - private static String mode = "csv"; - - @JsonCreator - public ExplorativeConfig() { - - } - - public static void readConfig(String file) { - Properties properties = new Properties(); - File propertiesFile = new File(file); - try { - FileInputStream fileInputStream = new FileInputStream(propertiesFile); - properties.load(fileInputStream); - fileInputStream.close(); - } catch (java.io.IOException e) { - return; // use hard coded defaults defaults - } - csvPath = properties.getProperty("csvPath", csvPath); - featureName = properties.getProperty("featureName", featureName); - elementLimit = properties.getProperty("elementLimit", elementLimit); - dataFolder = properties.getProperty("dataFolder", dataFolder); - resultFolder = properties.getProperty("resultFolder", resultFolder); - treeSerializationFileName = properties.getProperty("treeSerializationFileName", treeSerializationFileName); - mode = properties.getProperty("mode", mode); - } - - public static String getCsvPath() { - return csvPath; - } - - public static String getFeatureName() { - return featureName; - } - - public static String getElementLimit() { - return elementLimit; - } - - public static String getDataFolder() { - return dataFolder; - } - - public static String getResultFolder() { - return resultFolder; - } - - public static String getTreeSerializationFileName() { - return treeSerializationFileName; - } - - public static String getMode() { - return mode; - } -} diff --git a/cineast-runtime/src/main/java/org/vitrivr/cineast/standalone/config/RetrievalRuntimeConfig.java b/cineast-runtime/src/main/java/org/vitrivr/cineast/standalone/config/RetrievalRuntimeConfig.java index a05fe5ffb..a2856a0a1 100644 --- a/cineast-runtime/src/main/java/org/vitrivr/cineast/standalone/config/RetrievalRuntimeConfig.java +++ b/cineast-runtime/src/main/java/org/vitrivr/cineast/standalone/config/RetrievalRuntimeConfig.java @@ -31,18 +31,9 @@ import org.vitrivr.cineast.core.features.MedianColorGrid8; import org.vitrivr.cineast.core.features.MedianColorRaster; import org.vitrivr.cineast.core.features.MedianFuzzyHist; -import org.vitrivr.cineast.core.features.MotionHistogram; import org.vitrivr.cineast.core.features.SaturationGrid8; import org.vitrivr.cineast.core.features.SubDivAverageFuzzyColor; import org.vitrivr.cineast.core.features.SubDivMedianFuzzyColor; -import org.vitrivr.cineast.core.features.SubDivMotionHistogram2; -import org.vitrivr.cineast.core.features.SubDivMotionHistogram3; -import org.vitrivr.cineast.core.features.SubDivMotionHistogram4; -import org.vitrivr.cineast.core.features.SubDivMotionHistogram5; -import org.vitrivr.cineast.core.features.SubDivMotionSum2; -import org.vitrivr.cineast.core.features.SubDivMotionSum3; -import org.vitrivr.cineast.core.features.SubDivMotionSum4; -import org.vitrivr.cineast.core.features.SubDivMotionSum5; import org.vitrivr.cineast.core.features.SubtitleFulltextSearch; import org.vitrivr.cineast.core.features.exporter.QueryImageExporter; import org.vitrivr.cineast.core.features.retriever.Retriever; @@ -97,18 +88,6 @@ public final class RetrievalRuntimeConfig { list.add(new RetrieverConfig(DominantEdgeGrid8.class, 1.4)); DEFAULT_RETRIEVER_CATEGORIES.put("edge", list); - list = new ArrayList<>(9); - list.add(new RetrieverConfig(MotionHistogram.class, 0.5)); - list.add(new RetrieverConfig(SubDivMotionHistogram2.class, 1.0)); - list.add(new RetrieverConfig(SubDivMotionHistogram3.class, 1.0)); - list.add(new RetrieverConfig(SubDivMotionHistogram4.class, 1.0)); - list.add(new RetrieverConfig(SubDivMotionHistogram5.class, 1.0)); - list.add(new RetrieverConfig(SubDivMotionSum2.class, 0.5)); - list.add(new RetrieverConfig(SubDivMotionSum3.class, 0.5)); - list.add(new RetrieverConfig(SubDivMotionSum4.class, 0.5)); - list.add(new RetrieverConfig(SubDivMotionSum5.class, 0.5)); - DEFAULT_RETRIEVER_CATEGORIES.put("motion", list); - list = new ArrayList<>(3); list.add(new RetrieverConfig(SubtitleFulltextSearch.class, 1.0)); list.add(new RetrieverConfig(DescriptionTextSearch.class, 1.0)); diff --git a/cineast-runtime/src/main/java/org/vitrivr/cineast/standalone/evaluation/EvaluationConfig.java b/cineast-runtime/src/main/java/org/vitrivr/cineast/standalone/evaluation/EvaluationConfig.java deleted file mode 100644 index d98a44cbe..000000000 --- a/cineast-runtime/src/main/java/org/vitrivr/cineast/standalone/evaluation/EvaluationConfig.java +++ /dev/null @@ -1,134 +0,0 @@ -package org.vitrivr.cineast.standalone.evaluation; - -import com.fasterxml.jackson.annotation.JsonProperty; -import java.nio.file.Path; -import java.nio.file.Paths; -import org.vitrivr.cineast.core.extraction.decode.general.Converter; -import org.vitrivr.cineast.core.util.ReflectionHelper; - - -public class EvaluationConfig { - - /** - * Evaluation mode determines how files should be selected; - COMPLETE: All files in the test files folder. - RANDOM: Random selection of files from the test files folder. - */ - public enum EvaluationMode { - COMPLETE, RANDOM - } - - /** - * Path to the folder containing the test files. - */ - private String testfiles; - - /** - * Path to the file hat describes the ground truth. - */ - private String classfile; - - /** - * Path to the folder where results should be written. - */ - private String results; - - /** - * The fully qualified name of the converter class used to convert test files to QueryContainers. - */ - private String converter; - - /** - * Delimiter used between columns in the text export. - */ - private String delimiter = ","; - - /** - * The query categories that should be tested. - */ - private String[] categories = new String[0]; - - /** - * The evaluation mode that should be used. - */ - private EvaluationMode mode = EvaluationMode.COMPLETE; - - /** - * The size of the test set (i.e. the number of elements in the database). - */ - private int size = 0; - - @JsonProperty - public Path getTestfiles() { - return Paths.get(testfiles); - } - - public void setTestfiles(String testfiles) { - this.testfiles = testfiles; - } - - @JsonProperty - public Path getClassfile() { - return Paths.get(this.classfile); - } - - public void setClassfile(String classfile) { - this.classfile = classfile; - } - - public Groundtruth getGroundtruth() throws EvaluationException { - return new Groundtruth(this.getClassfile()); - } - - @JsonProperty - public Path getResults() { - return Paths.get(this.results); - } - - public void setResults(String results) { - this.results = results; - } - - @JsonProperty - public Converter getConverter() { - return ReflectionHelper.newConverter(this.converter); - } - - public void setConverter(String converter) { - this.converter = converter; - } - - @JsonProperty - public String[] getCategories() { - return categories; - } - - public void setCategories(String[] categories) { - this.categories = categories; - } - - @JsonProperty - public int getSize() { - return size; - } - - public void setSize(int size) { - this.size = size; - } - - @JsonProperty - public String getDelimiter() { - return delimiter; - } - - public void setDelimiter(String delimiter) { - this.delimiter = delimiter; - } - - @JsonProperty - public EvaluationMode getMode() { - return mode; - } - - public void setMode(EvaluationMode mode) { - this.mode = mode; - } -} diff --git a/cineast-runtime/src/main/java/org/vitrivr/cineast/standalone/evaluation/EvaluationException.java b/cineast-runtime/src/main/java/org/vitrivr/cineast/standalone/evaluation/EvaluationException.java deleted file mode 100644 index aaace1242..000000000 --- a/cineast-runtime/src/main/java/org/vitrivr/cineast/standalone/evaluation/EvaluationException.java +++ /dev/null @@ -1,18 +0,0 @@ -package org.vitrivr.cineast.standalone.evaluation; - -/** - * An exception that indicates something went wrong during an Evaluation-Run. - */ -public class EvaluationException extends Exception { - - static final long serialVersionUID = 1L; - - /** - * Constructor for EvaluationException - * - * @param message Error message. - */ - EvaluationException(String message) { - super(message); - } -} diff --git a/cineast-runtime/src/main/java/org/vitrivr/cineast/standalone/evaluation/EvaluationResult.java b/cineast-runtime/src/main/java/org/vitrivr/cineast/standalone/evaluation/EvaluationResult.java deleted file mode 100644 index 003136681..000000000 --- a/cineast-runtime/src/main/java/org/vitrivr/cineast/standalone/evaluation/EvaluationResult.java +++ /dev/null @@ -1,164 +0,0 @@ -package org.vitrivr.cineast.standalone.evaluation; - -import java.util.ArrayList; -import java.util.List; -import org.apache.commons.lang3.tuple.ImmutableTriple; -import org.apache.commons.lang3.tuple.Triple; - -/** - * Helper class that can be used to track evaluation results. It tracks the total number of relevant documents per class, the number of retrieved documents and the number of hits at every rank k. - */ -public class EvaluationResult { - - /** - * ID of the reference document that was used to perform the query. - */ - private final String docID; - - /** - * Name of reference object's class labels. - */ - private final String cl; - - /** - * Number of relevant documents in the class according to the ground truth. - */ - private final int relevant; - - /** - * Number of retrieved results. - */ - private int retrieved = 0; - - /** - * Number of retrieved and relevant documents. - */ - private int intersection = 0; - - /** - * List of docID / precision / recall triples for each rank. - */ - private List> pk; - - /** - * Creates a new EvaluationResult object for the provided reference document - * - * @param docID ID of the reference document. - * @param groundtruth Ground truth object used to construct this evaluation result. - */ - public EvaluationResult(String docID, Groundtruth groundtruth) throws EvaluationException { - this.docID = docID; - this.cl = groundtruth.classForDocId(docID).orElseThrow(() -> new EvaluationException(String.format("The provided document ID '%s' is not registered in the ground truth.", docID))); - this.relevant = groundtruth.numberOfRelevant(this.cl); - this.pk = new ArrayList<>(); - } - - /** - * Registers a new document from the resultset alongside with the information whether it was a hit or not. Updates the retrieval statistics. - * - * @param docID ID of the document that was retrieved. - * @param k The rank of the retrieved document. - * @param relevant Boolean that indicates whether the document was relevant (true) or not (false). - */ - public final void documentAvailable(String docID, int k, boolean relevant) { - if (k < 1) { - throw new IllegalArgumentException(String.format("The value k must be greater than 0 (is: %d).", k)); - } - if (k < this.pk.size()) { - throw new IllegalArgumentException(String.format("The provided rank %d has already been evaluated.", k)); - } - if (relevant) { - this.intersection += 1; - } - this.retrieved += 1; - Triple triple = new ImmutableTriple<>(docID, (float) this.intersection / (float) k, (float) this.intersection / (float) this.relevant); - this.pk.add(triple); - } - - /** - * Getter for query object ID. - */ - public final String getDocId() { - return this.docID; - } - - /** - * Getter for query object class. - */ - public final String getCl() { - return cl; - } - - /** - * Getter for relevant. - * - * @return Number of relevant documents as per ground truth. - */ - public int getRelevant() { - return relevant; - } - - /** - * Getter for retrieved. - * - * @return Number of retrieved documents. - */ - public final int getRetrieved() { - return retrieved; - } - - /** - * Getter for intersection - * - * @return Number of retrieved & relevant documents. - */ - public final int getIntersection() { - return intersection; - } - - /** - * Returns true, if the number of retrieved & relevant documents equals the total number of relevant documents. - */ - public boolean done() { - return this.intersection == this.relevant; - } - - public final String toString(String delimiter) { - StringBuilder builder = new StringBuilder(); - - /* Create header. */ - builder.append("ID"); - builder.append(delimiter); - builder.append("Hit"); - builder.append(delimiter); - builder.append("Precision"); - builder.append(delimiter); - builder.append("Recall"); - builder.append("\n"); - - int i = 0; - /* Append data. */ - for (Triple triple : this.pk) { - builder.append(triple.getLeft()); - builder.append(delimiter); - - /* Check if entry was a documentAvailable. */ - boolean hit = false; - if (i == 0 && triple.getRight() > 0) { - hit = true; - } else if (i > 0 && triple.getRight() > this.pk.get(i - 1).getRight()) { - hit = true; - } - builder.append(hit ? 1 : 0); - builder.append(delimiter); - - builder.append(triple.getMiddle()); - builder.append(delimiter); - builder.append(triple.getRight()); - builder.append("\n"); - i++; - } - - return builder.toString(); - } -} diff --git a/cineast-runtime/src/main/java/org/vitrivr/cineast/standalone/evaluation/EvaluationRuntime.java b/cineast-runtime/src/main/java/org/vitrivr/cineast/standalone/evaluation/EvaluationRuntime.java deleted file mode 100644 index 9b4203ef5..000000000 --- a/cineast-runtime/src/main/java/org/vitrivr/cineast/standalone/evaluation/EvaluationRuntime.java +++ /dev/null @@ -1,246 +0,0 @@ -package org.vitrivr.cineast.standalone.evaluation; - -import java.io.BufferedWriter; -import java.io.IOException; -import java.nio.file.Files; -import java.nio.file.Path; -import java.nio.file.StandardOpenOption; -import java.util.HashMap; -import java.util.Iterator; -import java.util.List; -import java.util.Optional; -import java.util.Random; -import java.util.concurrent.Callable; -import org.apache.commons.lang3.tuple.ImmutableTriple; -import org.apache.commons.lang3.tuple.Triple; -import org.apache.logging.log4j.LogManager; -import org.apache.logging.log4j.Logger; -import org.vitrivr.cineast.core.config.DatabaseConfig; -import org.vitrivr.cineast.core.config.ReadableQueryConfig; -import org.vitrivr.cineast.core.data.entities.MediaObjectDescriptor; -import org.vitrivr.cineast.core.data.entities.MediaSegmentDescriptor; -import org.vitrivr.cineast.core.data.query.containers.AbstractQueryTermContainer; -import org.vitrivr.cineast.core.data.score.SegmentScoreElement; -import org.vitrivr.cineast.core.db.dao.reader.MediaObjectReader; -import org.vitrivr.cineast.core.db.dao.reader.MediaSegmentReader; -import org.vitrivr.cineast.core.extraction.decode.general.Converter; -import org.vitrivr.cineast.core.util.LogHelper; -import org.vitrivr.cineast.core.util.json.JacksonJsonProvider; -import org.vitrivr.cineast.core.util.json.JsonReader; -import org.vitrivr.cineast.standalone.config.Config; -import org.vitrivr.cineast.standalone.util.ContinuousRetrievalLogic; - - -public class -EvaluationRuntime implements Callable { - - private static final Logger LOGGER = LogManager.getLogger(); - - /** - * MediaSegmentReader instance used to read segments from the storage layer. - */ - private final MediaSegmentReader mediaSegmentReader; - - /** - * MediaObjectReader instance used to read multimedia objects from the storage layer. - */ - private final MediaObjectReader mediaObjectReader; - - /** - * Instance of EvaluationConfig that is used with this runtime. - */ - private final EvaluationConfig config; - - /** - * Caching structure used to cache MultimediaObjectDescriptors. - */ - private final HashMap cache; - - /** - * Number of files that were processed successfully. - */ - private int processed = 0; - - /** - * Number of files that were skipped deliberately. - */ - private int skipped = 0; - - /** - * Number of files that were skipped due to processing errors. - */ - private int error = 0; - - private final ContinuousRetrievalLogic retrievalLogic; - - - public EvaluationRuntime(Path configPath, DatabaseConfig dbConfig) { - JsonReader reader = new JacksonJsonProvider(); - this.config = reader.toObject(configPath.toFile(), EvaluationConfig.class); - this.cache = new HashMap<>(this.config.getSize()); - this.mediaSegmentReader = new MediaSegmentReader(dbConfig.getSelectorSupplier().get()); - this.mediaObjectReader = new MediaObjectReader(dbConfig.getSelectorSupplier().get()); - this.retrievalLogic = new ContinuousRetrievalLogic(dbConfig); - } - - /** - * Executes the evaluation and returns a Triple that contains the number of files that were processed, skipped due to errors and skipped deliberately. The actual evaluation results are written to files. - * - * @return computed result - * @throws EvaluationException if unable to compute a result - * @see EvaluationConfig - */ - @Override - public Triple call() throws EvaluationException, IOException { - /* Tries to instantiate the converter. */ - final Converter converter = this.config.getConverter(); - if (converter == null) { - throw new EvaluationException("Failed to instantiate the converter class."); - } - - /* Instantiates the groundtruth and checks if it contains classes. */ - final Groundtruth gt = this.config.getGroundtruth(); - if (gt.numberOfClasses() == 0) { - throw new EvaluationException(String.format("The specified ground truth '%s' does not contain any classes.", this.config.getClassfile())); - } - - /* Updates the retrieval configuration. */ - Config.sharedConfig().getRetriever().setMaxResults(this.config.getSize()); - Config.sharedConfig().getRetriever().setResultsPerModule(this.config.getSize()); - - /* Prepares the iterator for the test files. */ - final Iterator testfilesIterator; - try { - testfilesIterator = Files.walk(this.config.getTestfiles()).filter(p -> { - try { - return Files.exists(p) && Files.isRegularFile(p) && !Files.isHidden(p) && Files.isReadable(p); - } catch (IOException e) { - LOGGER.error("An IO exception occurred while testing the media file at '{}'.", p.toString(), LogHelper.getStackTrace(e)); - return false; - } - }).iterator(); - } catch (IOException exception) { - throw new EvaluationException(String.format("Could not obtain test files under the specified path '%s'.", this.config.getTestfiles())); - } - - /* Prepare folder structure per category. */ - for (String category : this.config.getCategories()) { - Files.createDirectories(this.config.getResults().resolve(category)); - } - - /* Prepare a placeholder query-config. */ - final ReadableQueryConfig queryConfig = new ReadableQueryConfig(null); - - /* Prepare a random number generator that decides if a file should be used for evaluation or not. */ - final Random random = new Random(); - - /* Perform evaluation for every file. */ - Path path; - while (testfilesIterator.hasNext()) { - path = testfilesIterator.next(); - if (random.nextBoolean() && config.getMode() == EvaluationConfig.EvaluationMode.RANDOM) { - LOGGER.info("Randomly skipping file {}.", path); - this.skipped += 1; - continue; - } - - /* Try to create a QueryContainer. If this fails, the file is skipped. */ - final AbstractQueryTermContainer container = converter.convert(path); - if (container == null) { - LOGGER.warn("Failed to convert the file {}. File is being skipped...", path.getFileName()); - this.error += 1; - continue; - } - - LOGGER.info("Starting evaluation for {}", path); - for (String category : this.config.getCategories()) { - List scores = this.retrievalLogic.retrieve(container, category, queryConfig); - EvaluationResult result = this.performEvaluation(scores, path, gt); - this.writeToFile(category, result); - } - - this.processed += 1; - } - - return new ImmutableTriple<>(this.processed, this.error, this.skipped); - } - - - /** - * Writes the results for a feature category to a CSV file. If a file with that name already exists, the existing file is overwritten! - * - * @param category The feature category of the file. - * @param result The evaluation results. - * @throws IOException If writing of file fails. - */ - private void writeToFile(String category, EvaluationResult result) throws IOException { - BufferedWriter writer = Files.newBufferedWriter(this.config.getResults().resolve(category).resolve(result.getDocId() + "-" + result.getCl() + "-results.csv"), StandardOpenOption.CREATE, StandardOpenOption.WRITE, StandardOpenOption.TRUNCATE_EXISTING); - writer.append(result.toString(this.config.getDelimiter())); - writer.newLine(); - writer.close(); - } - - /** - * Performs the actual evaluation for a result set and reference document. Now iterate through the list of retrieved documents and decides for each entry if its class is equal to the class of the reference document (i.e. if it is relevant or not). Based on the outcome, the EvaluationResult is updated. - * - * @param scores The result set - list of SegmentScoreElements. - * @param path Path to the reference document file. Its filename is used as docID - * @param gt Ground truth object used for evaluation. - * @return EvaluationResult - * @throws EvaluationException If something goes wrong during evaluation, e.g. reference document has no class or a item in the result set has no class - */ - private EvaluationResult performEvaluation(List scores, Path path, Groundtruth gt) throws EvaluationException { - /* Constructs a document ID from the filename and fetches the file's class from the ground truth. */ - String docID = path.getFileName().toString(); - String fileClass = gt.classForDocId(docID).orElseThrow(() -> new EvaluationException(String.format("The provided test file %s does not have a class associated with it.", path.getFileName()))); - - /* Prepare empty evaluation results. */ - EvaluationResult result = new EvaluationResult(docID, gt); - - /* - * Now iterate through the list of retrieved documents and decide for each entry if it relevant according to its class. - */ - for (int k = 1; k <= scores.size(); k++) { - SegmentScoreElement score = scores.get(k - 1); - MediaObjectDescriptor object = this.objectDescriptorForId(score.getSegmentId()); - if (object != null) { - if (gt.classForDocId(object.getName()).orElse("").equals(fileClass)) { - result.documentAvailable(object.getName(), k, true); - } else { - result.documentAvailable(object.getName(), k, false); - } - if (result.done()) { - LOGGER.info("All relevant objects were retrieved. Starting next round...", score.getSegmentId()); - break; - } - } else { - throw new EvaluationException(String.format("The provided test file %s does not have a class associated with it.", score.getSegmentId())); - } - } - - return result; - } - - /** - * Returns a MediaObjectDescriptor for the provided docID. This method uses a cache to speedup lookup of objects. - * - * @param docID ID of the segment for which the MediaObjectDescriptor is required. - * @return MediaObjectDescriptor - */ - private MediaObjectDescriptor objectDescriptorForId(String docID) { - if (this.cache.containsKey(docID)) { - return this.cache.get(docID); - } - Optional descriptor = this.mediaSegmentReader.lookUpSegment(docID); - if (descriptor.isPresent()) { - MediaObjectDescriptor object = this.mediaObjectReader.lookUpObjectById(descriptor.get().getObjectId()); - this.cache.put(docID, object); - return object; - } else { - return null; - } - } -} - - - diff --git a/cineast-runtime/src/main/java/org/vitrivr/cineast/standalone/evaluation/Groundtruth.java b/cineast-runtime/src/main/java/org/vitrivr/cineast/standalone/evaluation/Groundtruth.java deleted file mode 100644 index 42980fdbe..000000000 --- a/cineast-runtime/src/main/java/org/vitrivr/cineast/standalone/evaluation/Groundtruth.java +++ /dev/null @@ -1,134 +0,0 @@ -package org.vitrivr.cineast.standalone.evaluation; - -import com.fasterxml.jackson.databind.JsonNode; -import com.fasterxml.jackson.databind.ObjectMapper; -import java.io.IOException; -import java.nio.file.Path; -import java.util.Collections; -import java.util.HashMap; -import java.util.HashSet; -import java.util.Iterator; -import java.util.Optional; -import java.util.Set; - -/** - * Represents a ground truth data collection that assigns IDs of test objects to arbitrary classes and vice versa. This class can be constructed from a simple JSON file. - */ -public class Groundtruth { - - private static final ObjectMapper MAPPER = new ObjectMapper(); - - /** - * Maps class labels to document IDs. - */ - private HashMap> map; - - /** - * Maps documentIDs class labels. - */ - private HashMap inverseMap; - - /** - * Constructor for Groundtruth from a file. - * - * @param path Path to file from which to read the ground truth. - */ - public Groundtruth(Path path) throws EvaluationException { - this.map = new HashMap<>(); - this.inverseMap = new HashMap<>(); - try { - JsonNode node = MAPPER.readTree(path.toFile()); - if (node == null) { - throw new EvaluationException("Could not read the ground truth file from the specified path '%s'. File seems to be empty."); - } - this.readFromJsonNode(node); - } catch (IOException e) { - throw new EvaluationException(String.format("Could not read the ground truth file from the specified path '%s' due to an IOException.", path.toString())); - } - } - - /** - * Constructor for Groundtruth from a JsonNode. - * - * @param node JsonNode from which to read the ground truth. - */ - public Groundtruth(JsonNode node) throws EvaluationException { - this.map = new HashMap<>(); - this.inverseMap = new HashMap<>(); - this.readFromJsonNode(node); - } - - /** - * Returns the class label for the provided ID or an empty Optional, if no class has been defined for the provided ID. - * - * @return String class label for the provided ID. - */ - public final Optional classForDocId(String id) { - return Optional.ofNullable(this.inverseMap.get(id)); - } - - /** - * Returns the IDs saved under the provided class according to the ground truth. The return set is empty if the class does not exist. - * - * @return Set of IDs for the provided class. - */ - public final Set docIdsForClass(String c) { - return Collections.unmodifiableSet(this.map.getOrDefault(c, new HashSet<>(0))); - } - - /** - * Returns the number of classes registered in the Groundtruth. - * - * @return Number of classes. - */ - public final int numberOfClasses() { - return this.map.size(); - } - - - /** - * Returns the number of relevant documents for the provided class label. - * - * @param cl Class label. - * @return Number of relevant documents in that class. - */ - public final int numberOfRelevant(String cl) { - if (this.map.containsKey(cl)) { - return this.map.get(cl).size(); - } else { - return 0; - } - } - - /** - * This method reads ground truth data from a JSON file. - * - * @param node JsonNode from which to read the ground truth. - */ - private void readFromJsonNode(JsonNode node) throws EvaluationException { - Iterator classes = node.fieldNames(); - while (classes.hasNext()) { - String cl = classes.next(); - JsonNode ids = node.get(cl); - - if (ids == null) { - continue; - } - - /* Add class label to map if it's not already there. */ - if (!this.map.containsKey(cl)) { - this.map.put(cl, new HashSet<>()); - } - - if (ids.isArray()) { - for (JsonNode item : ids) { - if (this.inverseMap.containsKey(cl)) { - throw new EvaluationException("Could not create ground truth due to a structural error: An ID must not belong to more than one class."); - } - this.map.get(cl).add(item.textValue()); - this.inverseMap.put(item.textValue(), cl); - } - } - } - } -} diff --git a/cineast-runtime/src/main/java/org/vitrivr/cineast/standalone/importer/PlainTextImporter.java b/cineast-runtime/src/main/java/org/vitrivr/cineast/standalone/importer/PlainTextImporter.java deleted file mode 100644 index e0a1e791f..000000000 --- a/cineast-runtime/src/main/java/org/vitrivr/cineast/standalone/importer/PlainTextImporter.java +++ /dev/null @@ -1,63 +0,0 @@ -package org.vitrivr.cineast.standalone.importer; - -import java.io.IOException; -import java.nio.file.Files; -import java.nio.file.Path; -import java.util.HashMap; -import java.util.Iterator; -import java.util.Map; -import org.vitrivr.cineast.core.data.Pair; -import org.vitrivr.cineast.core.data.providers.primitive.PrimitiveTypeProvider; -import org.vitrivr.cineast.core.importer.Importer; - -public class PlainTextImporter implements Importer> { - - /** - * Iterator over the files that should be imported. - */ - private final Iterator files; - - /** - * Constructor for {@link PlainTextImporter}. - * - * @param input Path to the input file or folder. - */ - public PlainTextImporter(Path input) throws IOException { - this.files = Files.walk(input, 2).filter(s -> s.toString().endsWith(".txt")).iterator(); - } - - /** - * Returns the ID and the content of the next text file. - * - * @return Pair mapping an ID (from the filename) to the content of the file (text). - */ - @Override - public Pair readNext() { - try { - if (this.files.hasNext()) { - final Path path = this.files.next(); - final String segmentId = path.getFileName().toString().replace(".txt", ""); - final String text = new String(Files.readAllBytes(path)); - return new Pair<>(segmentId, text); - } else { - return null; - } - } catch (IOException e) { - return null; - } - } - - /** - * Converts a mapping from ID to text content to a HashMap representation that can be used by the {@link Copier} class - * - * @param data Pair mapping an ID to a text. - * @return HashMap containing the data. - */ - @Override - public Map convert(Pair data) { - final HashMap map = new HashMap<>(2); - map.put("id", PrimitiveTypeProvider.fromObject(data.first)); - map.put("feature", PrimitiveTypeProvider.fromObject(data.second)); - return map; - } -} diff --git a/cineast-runtime/src/main/java/org/vitrivr/cineast/standalone/importer/TagsFulltextImporter.java b/cineast-runtime/src/main/java/org/vitrivr/cineast/standalone/importer/TagsFulltextImporter.java deleted file mode 100644 index a1d9da549..000000000 --- a/cineast-runtime/src/main/java/org/vitrivr/cineast/standalone/importer/TagsFulltextImporter.java +++ /dev/null @@ -1,66 +0,0 @@ -package org.vitrivr.cineast.standalone.importer; - -import java.io.IOException; -import java.nio.file.Files; -import java.nio.file.Path; -import java.util.HashMap; -import java.util.Iterator; -import java.util.Map; -import org.vitrivr.cineast.core.data.Pair; -import org.vitrivr.cineast.core.data.providers.primitive.PrimitiveTypeProvider; -import org.vitrivr.cineast.core.importer.Importer; - -/** - * Imports the tag files files generated for the collection for the VBS challenge to an entity for fulltext retrieval. - */ -public class TagsFulltextImporter implements Importer> { - - /** - * Iterator over the files that should be imported. - */ - private final Iterator files; - - /** - * Constructor for {@link PlainTextImporter}. - * - * @param input Path to the input file or folder. - */ - public TagsFulltextImporter(Path input) throws IOException { - this.files = Files.walk(input, 2).filter(s -> s.toString().endsWith(".txt")).iterator(); - } - - /** - * Returns the ID and the content of the next text file. - * - * @return Pair mapping an ID (from the filename) to the content of the file (text). - */ - @Override - public Pair readNext() { - try { - if (this.files.hasNext()) { - final Path path = this.files.next(); - final String segmentId = path.getFileName().toString().replace(".txt", ""); - final String text = new String(Files.readAllBytes(path)).replaceAll("\\s+", " ").trim(); - return new Pair<>(segmentId, text); - } else { - return null; - } - } catch (IOException e) { - return null; - } - } - - /** - * Converts a mapping from ID to text content to a HashMap representation that can be used by the {@link Copier} class - * - * @param data Pair mapping an ID to a text. - * @return HashMap containing the data. - */ - @Override - public Map convert(Pair data) { - final HashMap map = new HashMap<>(2); - map.put("id", PrimitiveTypeProvider.fromObject(data.first)); - map.put("feature", PrimitiveTypeProvider.fromObject(data.second)); - return map; - } -} \ No newline at end of file diff --git a/cineast-runtime/src/main/java/org/vitrivr/cineast/standalone/importer/VbsMetaImporter.java b/cineast-runtime/src/main/java/org/vitrivr/cineast/standalone/importer/VbsMetaImporter.java deleted file mode 100644 index 21ed8c545..000000000 --- a/cineast-runtime/src/main/java/org/vitrivr/cineast/standalone/importer/VbsMetaImporter.java +++ /dev/null @@ -1,69 +0,0 @@ -package org.vitrivr.cineast.standalone.importer; - -import java.io.IOException; -import java.nio.file.Files; -import java.nio.file.Path; -import java.util.HashMap; -import java.util.Iterator; -import java.util.Map; -import org.vitrivr.cineast.core.data.Pair; -import org.vitrivr.cineast.core.data.providers.primitive.PrimitiveTypeProvider; -import org.vitrivr.cineast.core.importer.Importer; - -/** - * Imports the XML metadata files bundled with the collection for the VBS challenge to an entity for fulltext retrieval. The XML structure in the files is completely ommited and only text is imported. - */ -public class VbsMetaImporter implements Importer> { - - /** - * Iterator over the files that should be imported. - */ - private final Iterator files; - - /** - * Constructor for {@link PlainTextImporter}. - * - * @param input Path to the input file or folder. - */ - public VbsMetaImporter(Path input) throws IOException { - this.files = Files.walk(input, 2).filter(s -> s.toString().endsWith(".xml")).iterator(); - } - - /** - * Returns the ID and the content of the next XML file. - * - * @return Pair mapping an ID (from the filename) to the content of the file (text). - */ - @Override - public Pair readNext() { - try { - if (this.files.hasNext()) { - final Path path = this.files.next(); - final String objectId = path.getFileName().toString().replace(".xml", ""); - final String text = new String(Files.readAllBytes(path)) - .replaceAll("<[^>]+>", "\n") - .replaceAll("\\s+", " ") - .trim(); - return new Pair<>(objectId, text); - } else { - return null; - } - } catch (IOException e) { - return null; - } - } - - /** - * Converts a mapping from ID to text content to a HashMap representation that can be used by the {@link Copier} class - * - * @param data Pair mapping an ID to a text. - * @return HashMap containing the data. - */ - @Override - public Map convert(Pair data) { - final HashMap map = new HashMap<>(2); - map.put("id", PrimitiveTypeProvider.fromObject(data.first)); - map.put("feature", PrimitiveTypeProvider.fromObject(data.second)); - return map; - } -} diff --git a/cineast-runtime/src/main/java/org/vitrivr/cineast/standalone/importer/handlers/AsrDataImportHandler.java b/cineast-runtime/src/main/java/org/vitrivr/cineast/standalone/importer/handlers/AsrDataImportHandler.java deleted file mode 100644 index bb5291c85..000000000 --- a/cineast-runtime/src/main/java/org/vitrivr/cineast/standalone/importer/handlers/AsrDataImportHandler.java +++ /dev/null @@ -1,26 +0,0 @@ -package org.vitrivr.cineast.standalone.importer.handlers; - -import java.io.IOException; -import java.nio.file.Path; -import org.apache.logging.log4j.LogManager; -import org.apache.logging.log4j.Logger; -import org.vitrivr.cineast.core.util.LogHelper; -import org.vitrivr.cineast.standalone.importer.PlainTextImporter; - -public class AsrDataImportHandler extends DataImportHandler { - - private static final Logger LOGGER = LogManager.getLogger(); - - public AsrDataImportHandler(int threads, int batchsize) { - super(threads, batchsize); - } - - @Override - public void doImport(Path path) { - try { - this.futures.add(this.service.submit(new DataImportRunner(new PlainTextImporter(path), "features_asr", "asr"))); - } catch (IOException e) { - LOGGER.error("Could not start data import process with path '{}' due to an IOException: {}. Aborting...", path.toString(), LogHelper.getStackTrace(e)); - } - } -} diff --git a/cineast-runtime/src/main/java/org/vitrivr/cineast/standalone/importer/handlers/OcrDataImportHandler.java b/cineast-runtime/src/main/java/org/vitrivr/cineast/standalone/importer/handlers/OcrDataImportHandler.java deleted file mode 100644 index 1dbf72573..000000000 --- a/cineast-runtime/src/main/java/org/vitrivr/cineast/standalone/importer/handlers/OcrDataImportHandler.java +++ /dev/null @@ -1,30 +0,0 @@ -package org.vitrivr.cineast.standalone.importer.handlers; - -import java.io.IOException; -import java.nio.file.Path; -import org.apache.logging.log4j.LogManager; -import org.apache.logging.log4j.Logger; -import org.vitrivr.cineast.core.features.OCRSearch; -import org.vitrivr.cineast.core.util.LogHelper; -import org.vitrivr.cineast.standalone.importer.PlainTextImporter; - -public class OcrDataImportHandler extends DataImportHandler { - - /** - * - */ - private static final Logger LOGGER = LogManager.getLogger(); - - public OcrDataImportHandler(int threads, int batchsize) { - super(threads, batchsize); - } - - @Override - public void doImport(Path path) { - try { - this.futures.add(this.service.submit(new DataImportRunner(new PlainTextImporter(path), OCRSearch.OCR_TABLE_NAME, "ocr"))); - } catch (IOException e) { - LOGGER.error("Could not start data import process with path '{}' due to an IOException: {}. Aborting...", path.toString(), LogHelper.getStackTrace(e)); - } - } -} diff --git a/cineast-runtime/src/main/java/org/vitrivr/cineast/standalone/importer/handlers/ProtoDataImportHandler.java b/cineast-runtime/src/main/java/org/vitrivr/cineast/standalone/importer/handlers/ProtoDataImportHandler.java deleted file mode 100644 index 6f53f4e4c..000000000 --- a/cineast-runtime/src/main/java/org/vitrivr/cineast/standalone/importer/handlers/ProtoDataImportHandler.java +++ /dev/null @@ -1,42 +0,0 @@ -package org.vitrivr.cineast.standalone.importer.handlers; - -import java.io.FileNotFoundException; -import java.io.IOException; -import java.nio.file.Files; -import java.nio.file.Path; -import org.apache.logging.log4j.LogManager; -import org.apache.logging.log4j.Logger; -import org.vitrivr.cineast.core.importer.TupleInsertMessageImporter; - -public class ProtoDataImportHandler extends DataImportHandler { - - private static final Logger LOGGER = LogManager.getLogger(); - - public ProtoDataImportHandler(int threads, int batchsize) { - super(threads, batchsize); - } - - - /** - * Starts data import process using PROTO files. The method can either be used with a single file or a folder containing PROTO files. - * - * @param path Path to the PROTO file or a folder containing PROTO files. - */ - @Override - public void doImport(Path path) { - try { - LOGGER.info("Starting data import with PROTO files in: {}", path.toString()); - Files.walk(path, 2).filter(p -> p.toString().toLowerCase().endsWith(".bin")).forEach(p -> { - final String filename = p.getFileName().toString(); - final String suffix = filename.substring(filename.lastIndexOf(".")); - try { - this.futures.add(this.service.submit(new DataImportRunner(new TupleInsertMessageImporter(p.toFile()), filename.replace(suffix, ""), "proto_" + filename.replace(suffix, "")))); - } catch (FileNotFoundException e) { - LOGGER.error("Could not start data import for file '{}'. Skipping...?", filename); - } - }); - } catch (IOException e) { - LOGGER.error("Could not start data import process with path '{}' due to an IOException. Aborting...", path.toString()); - } - } -} diff --git a/cineast-runtime/src/main/java/org/vitrivr/cineast/standalone/importer/lsc2020/CaptionImportHandler.java b/cineast-runtime/src/main/java/org/vitrivr/cineast/standalone/importer/lsc2020/CaptionImportHandler.java deleted file mode 100644 index 6bf6ca965..000000000 --- a/cineast-runtime/src/main/java/org/vitrivr/cineast/standalone/importer/lsc2020/CaptionImportHandler.java +++ /dev/null @@ -1,28 +0,0 @@ -package org.vitrivr.cineast.standalone.importer.lsc2020; - -import java.nio.file.Path; -import org.apache.logging.log4j.LogManager; -import org.apache.logging.log4j.Logger; -import org.vitrivr.cineast.core.features.DescriptionTextSearch; -import org.vitrivr.cineast.standalone.importer.handlers.DataImportHandler; - -public class CaptionImportHandler extends DataImportHandler { - - private static final Logger LOGGER = LogManager.getLogger(CaptionImportHandler.class); - - /** - * Constructor; creates a new DataImportHandler with specified number of threads and batchsize. - * - * @param threads Number of threads to use for data import. - * @param batchsize Size of data batches that are sent to the persistence layer. - */ - public CaptionImportHandler(int threads, int batchsize) { - super(threads, batchsize); - } - - @Override - public void doImport(Path path) { - LOGGER.info("Starting caption import"); - this.futures.add(this.service.submit(new DataImportRunner(new CaptionImporter(path), DescriptionTextSearch.DESCRIPTION_TEXT_TABLE_NAME, "lsc-caption"))); - } -} diff --git a/cineast-runtime/src/main/java/org/vitrivr/cineast/standalone/importer/lsc2020/CaptionImporter.java b/cineast-runtime/src/main/java/org/vitrivr/cineast/standalone/importer/lsc2020/CaptionImporter.java deleted file mode 100644 index 4d82d1cc4..000000000 --- a/cineast-runtime/src/main/java/org/vitrivr/cineast/standalone/importer/lsc2020/CaptionImporter.java +++ /dev/null @@ -1,72 +0,0 @@ -package org.vitrivr.cineast.standalone.importer.lsc2020; - -import com.opencsv.CSVReader; -import com.opencsv.exceptions.CsvException; -import java.io.IOException; -import java.nio.charset.StandardCharsets; -import java.nio.file.Files; -import java.nio.file.Path; -import java.util.HashMap; -import java.util.Iterator; -import java.util.List; -import java.util.Map; -import org.apache.logging.log4j.Level; -import org.apache.logging.log4j.LogManager; -import org.apache.logging.log4j.Logger; -import org.vitrivr.cineast.core.data.entities.SimpleFulltextFeatureDescriptor; -import org.vitrivr.cineast.core.data.providers.primitive.PrimitiveTypeProvider; -import org.vitrivr.cineast.core.importer.Importer; - -public class CaptionImporter implements Importer> { - - - private static final Logger LOGGER = LogManager.getLogger(CaptionImporter.class); - - public static final String CAPTIONS_FILE_NAME = "lsc2020-captions.csv"; - - public static final int ID_COLUMN = 1; - public static final int CAPTION_COLUMN = 2; - - private Path root; - - public CaptionImporter(Path root) { - this.root = root; - try { - prepareFile(); - } catch (IOException | CsvException e) { - throw LOGGER.throwing(Level.ERROR, new RuntimeException("Could not preprae", e)); - } - } - - private Iterator iterator; - - private void prepareFile() throws IOException, CsvException { - long start = System.currentTimeMillis(); - Path file = root.resolve(CAPTIONS_FILE_NAME); - CSVReader csv = new CSVReader(Files.newBufferedReader(file, StandardCharsets.UTF_8)); - List metadataFileContents = csv.readAll(); - metadataFileContents.remove(0); // Headers not required - iterator = metadataFileContents.iterator(); - LOGGER.info("Preparation done in {}ms", (System.currentTimeMillis() - start)); - } - - private Map parseLine(String[] line) { - final HashMap map = new HashMap<>(2); - map.put(SimpleFulltextFeatureDescriptor.FIELDNAMES[0], PrimitiveTypeProvider.fromObject(LSCUtilities.pathToSegmentId(line[ID_COLUMN]))); - map.put(SimpleFulltextFeatureDescriptor.FIELDNAMES[1], PrimitiveTypeProvider.fromObject(line[CAPTION_COLUMN])); - return map; - } - - @Override - public Map readNext() { - if (iterator.hasNext()) { - return parseLine(iterator.next()); - } - return null; - } - - @Override - public Map convert(Map data) { - return data; - } -} diff --git a/cineast-runtime/src/main/java/org/vitrivr/cineast/standalone/importer/lsc2020/JsonTagReader.java b/cineast-runtime/src/main/java/org/vitrivr/cineast/standalone/importer/lsc2020/JsonTagReader.java deleted file mode 100644 index fb7023255..000000000 --- a/cineast-runtime/src/main/java/org/vitrivr/cineast/standalone/importer/lsc2020/JsonTagReader.java +++ /dev/null @@ -1,77 +0,0 @@ -package org.vitrivr.cineast.standalone.importer.lsc2020; - -import com.fasterxml.jackson.databind.JsonNode; -import com.fasterxml.jackson.databind.ObjectMapper; -import java.io.IOException; -import java.nio.file.Path; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.HashSet; -import java.util.List; -import org.apache.logging.log4j.LogManager; -import org.apache.logging.log4j.Logger; -import org.vitrivr.cineast.core.data.Pair; - - -/** - * Reader for the tag format of tags, published by the MySceal Team in 2021. - *

- * Requires a JSON file (published in 2021 at http://lsc.dcu.ie/resources/microsoft_tags.json - *

- * Format: - * - * - * { "item1":{ "tag1": score, "tag2": score }, "item2":{ "tag1":score, "tag2":score } } - * - *

- * {@code item} is formatted as filename, which {@link LSCUtilities#pathToSegmentId(String)} translates into vitrivr id - */ -public class JsonTagReader { - - - private static final Logger LOGGER = LogManager.getLogger(JsonTagReader.class); - - private final Path file; - - private final HashSet uniqueTags = new HashSet<>(); - private final HashMap>> tagEntries = new HashMap<>(); - - public JsonTagReader(Path file) throws IOException { - this.file = file; - readEntries(); - } - - private void readEntries() throws IOException { - LOGGER.info("Reading JSON File. This may take a while..."); - ObjectMapper mapper = new ObjectMapper(); - JsonNode rootNode = mapper.readTree(file.toFile()); - LOGGER.info("Completed reading JSON file. Processing now..."); - - rootNode.fields().forEachRemaining(entry -> { - String segmentId = LSCUtilities.pathToSegmentId(entry.getKey()); - JsonNode tags = entry.getValue(); - List> segmentTags = new ArrayList<>(); - if (!tags.isEmpty()) { - tags.fields().forEachRemaining(tagEntry -> { - if (tagEntry.getValue().isFloatingPointNumber()) { - segmentTags.add(new Pair<>(tagEntry.getKey(), tagEntry.getValue().floatValue())); - } - uniqueTags.add(tagEntry.getKey()); - }); - } - tagEntries.put(segmentId, segmentTags); - }); - - LOGGER.info("Successfully processed all tags"); - } - - public HashSet getUniqueTags() { - return uniqueTags; - } - - public HashMap>> getTagScoreMap() { - return tagEntries; - } - - -} diff --git a/cineast-runtime/src/main/java/org/vitrivr/cineast/standalone/importer/lsc2020/LSCAllTagsImportHandler.java b/cineast-runtime/src/main/java/org/vitrivr/cineast/standalone/importer/lsc2020/LSCAllTagsImportHandler.java deleted file mode 100644 index a462182de..000000000 --- a/cineast-runtime/src/main/java/org/vitrivr/cineast/standalone/importer/lsc2020/LSCAllTagsImportHandler.java +++ /dev/null @@ -1,67 +0,0 @@ -package org.vitrivr.cineast.standalone.importer.lsc2020; - -import com.opencsv.exceptions.CsvException; -import java.io.IOException; -import java.nio.file.Path; -import java.nio.file.Paths; -import org.apache.logging.log4j.LogManager; -import org.apache.logging.log4j.Logger; -import org.vitrivr.cineast.core.db.dao.reader.TagReader; -import org.vitrivr.cineast.core.features.SegmentTags; -import org.vitrivr.cineast.standalone.importer.handlers.DataImportHandler; - -public class LSCAllTagsImportHandler extends DataImportHandler { - - public static final String TASK_NAME = "lsc-tags-all"; - public static final String TASK_NAME_LOOKUP_SUFFIX = "-lookup"; - public static final String TASK_NAME_LOOKUP = TASK_NAME + TASK_NAME_LOOKUP_SUFFIX; - private static final Logger LOGGER = LogManager.getLogger(); - private final boolean clean; - - /** - * Constructor; creates a new DataImportHandler with specified number of threads and batchsize. - * - * @param threads Number of threads to use for data import. - * @param batchsize Size of data batches that are sent to the persistence layer. - */ - public LSCAllTagsImportHandler(int threads, int batchsize, boolean clean) { - super(threads, batchsize); - this.clean = clean; - } - - @Override - public void doImport(Path path) { - LOGGER.info("Starting {} import in {}", TASK_NAME, path); - if (clean) { - DataImportHandler.cleanOnDemand(TagReader.TAG_ENTITY_NAME, TASK_NAME_LOOKUP); - DataImportHandler.cleanOnDemand(SegmentTags.SEGMENT_TAGS_TABLE_NAME, TASK_NAME); - } - - try { - LSCUtilities.create(path); - LSCUtilities.getInstance().initMetadata(); - } catch (IOException | CsvException e) { - LOGGER.error("Cannot do import as initialization failed.", e); - return; - } - // Meta As Tag - this.futures.add(this.service.submit(new DataImportRunner( - new ProcessingMetaImporter(path, ProcessingMetaImporter.Type.TAG_LOOKUP), - TagReader.TAG_ENTITY_NAME, "lsc-metaAsTagsLookup"))); - this.futures.add(this.service.submit( - new DataImportRunner(new ProcessingMetaImporter(path, ProcessingMetaImporter.Type.TAG), - SegmentTags.SEGMENT_TAGS_TABLE_NAME, "lsc-metaAsTags"))); - // Official Concepts - this.futures.add(this.service.submit( - new DataImportRunner(new VisualConceptTagImporter(path, true), TagReader.TAG_ENTITY_NAME, - "lsc-visualConceptsTagsLookup"))); - this.futures.add(this.service.submit(new DataImportRunner(new VisualConceptTagImporter(path), - SegmentTags.SEGMENT_TAGS_TABLE_NAME, "lsc-visualConceptsTags"))); - // Mysceal lsc21 tags - this.futures.add(this.service.submit(new DataImportRunner(new MyscealTagImporter( - Paths.get(path.toString(), "mysceal-tags.json"), true), - TagReader.TAG_ENTITY_NAME, "lsc-mysceal-tags-unique"))); - this.futures.add(this.service.submit(new DataImportRunner(new MyscealTagImporter(Paths.get(path.toString(), "mysceal-tags.json"), false), - SegmentTags.SEGMENT_TAGS_TABLE_NAME, "lsc-mysceal-tags-segment"))); - } -} diff --git a/cineast-runtime/src/main/java/org/vitrivr/cineast/standalone/importer/lsc2020/LSCUtilities.java b/cineast-runtime/src/main/java/org/vitrivr/cineast/standalone/importer/lsc2020/LSCUtilities.java deleted file mode 100644 index 7f37d68fa..000000000 --- a/cineast-runtime/src/main/java/org/vitrivr/cineast/standalone/importer/lsc2020/LSCUtilities.java +++ /dev/null @@ -1,457 +0,0 @@ -package org.vitrivr.cineast.standalone.importer.lsc2020; - -import com.google.common.collect.Lists; -import com.opencsv.CSVReader; -import com.opencsv.exceptions.CsvException; -import java.io.IOException; -import java.nio.charset.StandardCharsets; -import java.nio.file.Files; -import java.nio.file.Path; -import java.nio.file.StandardOpenOption; -import java.time.DateTimeException; -import java.time.Instant; -import java.time.LocalDateTime; -import java.time.ZoneId; -import java.time.ZoneOffset; -import java.time.ZonedDateTime; -import java.util.Collections; -import java.util.HashMap; -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.Optional; -import java.util.Set; -import org.apache.commons.lang3.StringUtils; -import org.apache.logging.log4j.LogManager; -import org.apache.logging.log4j.Logger; - -public class LSCUtilities { - - public static final String LSC_REPORT_VALID_FILNE_NAME = "report-valid.txt"; - public static final String METADATA_FILE_NAME = "lsc2021-metadata.csv"; - public static final String CONCEPTS_FILE_NAME = "lsc2021-visual-concepts.csv"; - public static final String META_NO_PATH_FILE = "meta-no-path.txt"; - public static final String WRITTEN_FILE = "written.txt"; - public static final String KEY_MINUTEID = "minute_id"; - public static final int CONCEPTS_MINUTEID_COL = 0; - public static final int CONCEPTS_IMAGEPATH_COL = 2; - //minute_id,utc_time,local_time,timezone,lat,lon,semantic_name,elevation,speed,heart,calories,activity_type,steps - /* - minute_id, - utc_time, - local_time, - timezone, - lat, - lon, - semantic_name, - elevation, - speed, - heart, - calories, - activity_type, - steps - */ - public static final int META_MIN_COL = 0; - public static final String META_MIN_NAME = "minute_id"; - public static final int META_UTC_COL = 1; - public static final String META_UTC_NAME = "utc_time"; - public static final int META_LOCAL_COL = 2; - public static final String META_LOCAL_NAME = "local_time"; - public static final int META_TIMEZONE_COL = 3; - public static final String META_TIMEZONE_NAME = "timezone"; - public static final int META_LAT_COL = 4; - public static final String META_LAT_NAME = "lat"; - public static final int META_LON_COL = 5; - public static final String META_LON_NAME = "lon"; - public static final int META_SEMANTIC_COL = 6; - public static final String META_SEMANTIC_NAME = "semantic_name"; - public static final int META_ELEVATION_COL = 7; - public static final String META_ELEVATION_NAME = "elevation"; - public static final int META_SPEED_COL = 8; - public static final String META_SPEED_NAME = "speed"; - public static final int META_HEART_COL = 9; - public static final String META_HEART_NAME = "heart"; - public static final int META_CALORIES_COL = 10; - public static final String META_CALORIES_NAME = "calories"; - public static final int META_ACTIVITY_COL = 11; - public static final String META_ACTIVITY_NAME = "activity_type"; - public static final int META_STEPS_COL = 12; - public static final String META_STEPS_NAME = "steps"; - //minute_id,utc_time,local_time,timezone,lat,lon,semantic_name,elevation,speed,heart,calories,activity_type,steps - public static final String[] META_NAMES = new String[]{META_MIN_NAME, META_UTC_NAME, META_LOCAL_NAME, META_TIMEZONE_NAME, META_LAT_NAME, META_LON_NAME, META_SEMANTIC_NAME, META_ELEVATION_NAME, META_SPEED_NAME, META_HEART_NAME, META_CALORIES_NAME, META_ACTIVITY_NAME, META_STEPS_NAME - }; - public static final Set META_COLUMNS_IN_USE = new HashSet<>(Lists.newArrayList(META_MIN_COL, META_UTC_COL, META_LOCAL_COL, META_LAT_COL, META_LON_COL, META_TIMEZONE_COL, META_SEMANTIC_COL, META_ACTIVITY_COL)); - public static final String DEFAULT_DOMAIN = "LSCMETA"; - public static final String LOCATION_DOMAIN = "LOCATION"; - public static final String DATETIME_DOMAIN = "TIME"; - public static final String LSC_UTC_PREFIX = "UTC_"; - public static final String LSC_FORMAT = "yyyy-MM-dd_hh:mm"; - - public static final String PROCESSED_META_UTC = "p_utc_standard"; - public static final String PROCESSED_META_LOCAL = "p_local_standard"; - public static final String PROCESSED_META_DATETIME = "p_datetime"; // based on filename, utc - public static final String PROCESSED_META_DAY_OF_WEEK = "p_day_of_week"; - public static final String PROCESSED_META_PHASE_OF_DAY = "p_phase_of_day"; - public static final String PROCESSED_META_HOUR_OF_DAY = "p_hour"; - public static final String PROCESSED_META_MONTH = "p_month"; - public static final String PROCESSED_META_YEAR = "p_year"; - public static final String PROCESSED_META_DAY = "p_day"; - - - private static final Logger LOGGER = LogManager.getLogger(LSCUtilities.class); - - - private static LSCUtilities instance = null; - private final Path root; - private List headerlessMetaContents; - - @Deprecated - private HashMap minuteIdPathMap = new HashMap<>(); - - private HashMap filenameToMinuteIdMap = new HashMap<>(); - private HashMap metaPerMinute = new HashMap<>(); - - private LSCUtilities(final Path root) throws IOException, CsvException { - this.root = root; - // this.initLookup(minuteIdPathMap, root); - LOGGER.info("Initialising lookup..."); - this.initMap(this.readListOfFiles(root)); - LOGGER.info("Initialisation done."); - // headerlessMetaContents = readFile(root); - } - - public static LSCUtilities create(final Path root) throws IOException, CsvException { - if (instance == null) { - instance = new LSCUtilities(root); - } else if (!root.equals(instance.root)) { - return instance; - } else { - LOGGER.warn("Instance already created with path {}. Returning this one", instance.root); - } - return instance; - } - - public static LSCUtilities getInstance() { - if (instance != null) { - return instance; - } else { - throw new IllegalStateException("There's no instance, use LSCUtilities.create first"); - } - } - - /** - * Writes the list as individual lines in a textfile. The file must already be created - * - * @param directory The directory the file resides in - * @param file The file to write into - * @param lines The lines to write - * @throws IOException If something goes wrong. Possibly due to the file not being created beforehand - */ - public static void writeLines(Path directory, String file, List lines) throws IOException { - final Path p = directory.resolve(file); - Files.write(p, lines, StandardOpenOption.TRUNCATE_EXISTING); - } - - /** - * Converts an imagepath to a corresponding segmentId. - *
- * In the LSC2020 dataset, image paths (from file lsc2020-visual-concepts.csv) do contain more than the actual (image) file, hence some conversion is required - *
- * Prepends is_, removes anything before a slash ("/"), if present, and after a dot (".") (i.e., file extension), if present - * - * @param path - * @return - */ - public static String pathToSegmentId(String path) { - final int beginIdx = path.contains("/") ? path.lastIndexOf("/") + 1 : 0; - final int endIdx = path.contains(".") ? path.lastIndexOf(".") : path.length(); - final String prefix = path.startsWith("is_") ? "" : "is_"; - return prefix + path.substring(beginIdx, endIdx); - } - - public static String cleanImagePath(String path) { - if (path.startsWith("DATASETS/LSC2020/")) { - return path.substring("DATASETS/LSC2020/".length() + 1); - } else { - return path; - } - } - - /** - * Two potential naming formats:
Simple Format: {@code YYYMMDD_HHMMSS_000.ext} and
Extended Format: {@code prefix001_prefix_YYYMMDD_HHMMSS*.ext} Extension is jpg - *

- * Example of Simple: {@code 20160914_192303_000.jpg}
Example of Extended: {@code B00006542_21I6X0_20180505_140053E.JPG} - * - *

- */ - public static Optional filenameToMinuteId(String filename) { - String[] parts = filename.split("_"); - switch (parts.length) { - case 3: // simple - return Optional.of(filename.substring(0, filename.lastIndexOf("_") - 2)); - case 4: // Extended - String date = parts[2]; - String time = parts[3]; - return Optional.of(date + "_" + time.substring(0, 4)); - default: - return Optional.empty(); - } - } - - /** - * Removes all but after the last "/" - */ - public static String sanitizeFilename(String path) { - int i = path.lastIndexOf("/"); - if (i > 0) { - return path.substring(i + 1); - } else { - return path; - } - } - - public static String sanitizeFilename(Path path) { - return sanitizeFilename(path.toString()); - } - - - /** - * Converts a lscUtcTime format {@code UTC_yyyy-MM-dd_hh:mm} datetime to a {@link LocalDateTime} {@link LocalDateTime} is used, due to its definition of 'local time in ISO-8601 standard without time zone info'. - * - * @param lscUtcFormat The LSC UTC Timestamp in the format {@code UTC_yyyy-MM-dd_hh:mm} - */ - public static LocalDateTime convertUtc(String lscUtcFormat) { - return LocalDateTime.ofEpochSecond(convert(lscUtcFormat, true, null), 0, ZoneOffset.UTC); - } - - /** - * Converts a lscUtcTime format {@code yyyy-MM-dd_hh:mm} datetime to a {@link ZonedDateTime} - * - * @param lscFormat The LSC UTC Timestamp in the format {@code yyyy-MM-dd_hh:mm} - * @param zone A zoneid in format {@code Area/Region}, see {@linkplain ZoneId} - */ - public static ZonedDateTime convertLocal(String lscFormat, String zone) { - final long epochSec = convert(lscFormat, false, zone); - return ZonedDateTime.ofInstant(Instant.ofEpochSecond(epochSec), ZoneId.of(zone)); // Zone is parseable, otherwise not reached here - } - - public static String extractPhaseOfDay(ZonedDateTime dateTime) { - final int hour = dateTime.getHour(); - String tag; - if (hour > 7 && hour < 11) { - tag = "MORNING"; - } else if (hour >= 11 && hour < 14) { - tag = "NOON"; - } else if (hour >= 14 && hour < 17) { - tag = "AFTERNOON"; - } else if (hour >= 17 && hour < 22) { - tag = "EVENING"; - } else { - tag = "NIGHT"; - } - return tag; - } - - public static int extractYear(LocalDateTime time) { - return time.getYear(); - } - - public static int extractDay(LocalDateTime time) { - return time.getDayOfMonth(); - } - - public static String extractMonth(LocalDateTime time) { - return time.getMonth().name(); - } - - public static int extractHour(LocalDateTime utc) { - return utc.getHour(); - } - - public static String extractHourStr(LocalDateTime utc) { - return String.valueOf(extractHour(utc)); - } - - public static String extractYearStr(LocalDateTime utc) { - return String.valueOf(extractYear(utc)); - } - - public static String extractDayStr(LocalDateTime utc) { - return String.valueOf(extractHour(utc)); - } - - private static String getLscFormat(boolean utc) { - return (utc ? LSC_UTC_PREFIX : "") + LSC_FORMAT; - } - - private static long convert(String lscFormat, boolean utc, String zone) { - if (StringUtils.isBlank(lscFormat) || "NULL".equalsIgnoreCase(lscFormat)) { - throw new IllegalArgumentException("Cannot parse due to not in lscUtcFormat. Expected format: " + getLscFormat(utc) + ". Reason: BLANK. Given: " + lscFormat); - } - if (utc && !lscFormat.startsWith("UTC")) { - throw new IllegalArgumentException("Cannot parse due to not in lscUtcFormat. Expected format: " + getLscFormat(utc) + ". Reason: START. Given: " + lscFormat); - } else if (!utc && StringUtils.isBlank(zone)) { - throw new IllegalArgumentException("Cannot parse due to not in lscUtcFormat. Expected format: " + getLscFormat(utc) + ". Reason: ZONEBLANK. Given: " + lscFormat); - } - ZoneId zoneId = null; - try { - if (!utc) { - zoneId = ZoneId.of(zone); - } - } catch (DateTimeException e) { - throw new IllegalArgumentException("Cannot parse due to not in lscUtcFormat. Expected format: " + getLscFormat(utc) + ". Reason: ZONE. Given: " + lscFormat, e); - } - final String[] parts = lscFormat.split("_"); // ["UTC", "yyyy-mm-dd", "hh:mm"] - final int nbParts = utc ? 3 : 2; - if (parts.length < nbParts) { - throw new IllegalArgumentException("Cannot parse due to not in lscUtcFormat. Expected format: " + getLscFormat(utc) + ". Reason: DATE. Given: " + lscFormat); - } - final int dateIdx = utc ? 1 : 0; - final String[] date = parts[dateIdx].split("-"); // ["yyyy", "mm", "dd"] - if (date.length < 3) { - throw new IllegalArgumentException("Cannot parse due to not in lscUtcFormat. Expected format: " + getLscFormat(utc) + ". Reason: TIME. Given: " + lscFormat); - } - final int timeIdx = utc ? 2 : 1; - final String[] time = parts[timeIdx].split(":"); // ["hh", "mm"] - if (time.length < 2) { - throw new IllegalArgumentException("Cannot parse due to not in lscUtcFormat. Expected format: " + getLscFormat(utc) + ". Reason: TIME. Given: " + lscFormat); - } - try { - final int year = Integer.parseInt(date[0]); - final int month = Integer.parseInt(date[1]); - final int day = Integer.parseInt(date[2]); - final int hour = Integer.parseInt(time[0]); - final int minute = Integer.parseInt(time[1]); - if (utc) { - return LocalDateTime.of(year, month, day, hour, minute).toEpochSecond(ZoneOffset.UTC); - } else { - return ZonedDateTime.of(year, month, day, hour, minute, 0, 0, zoneId).toEpochSecond(); - } - } catch (NumberFormatException e) { - throw new IllegalArgumentException("Cannot parse due to not in lscUtcFormat. Expected format: " + getLscFormat(utc) + ". Reason: NUMBERFORMAT. Given: " + lscFormat, e); - } - } - - /** - * Parses a minuteId {@code YYYYMMDD_HH:mm} to a {@link LocalDateTime}. The result is to be treated as UTC timestamp - */ - public static LocalDateTime fromMinuteId(String minuteId) { - // YYYYMMDD_HHMM - // 0123456789012 - try { - final int endStrIdx = Math.min(minuteId.length(), 13); - final int year = Integer.parseInt(minuteId.substring(0, 4)); - final int month = Integer.parseInt(minuteId.substring(4, 6)); - final int day = Integer.parseInt(minuteId.substring(6, 8)); - final int hour = Integer.parseInt(minuteId.substring(9, 11)); - final int minute = Integer.parseInt(minuteId.substring(11, endStrIdx)); - return LocalDateTime.of(year, month, day, hour, minute); - } catch (NumberFormatException e) { - throw new IllegalArgumentException("Cannot parse due to invalid number format in minuteId"); - } - } - - public static boolean isMetaBlank(String meta) { - return StringUtils.isBlank(meta) || "NULL".equalsIgnoreCase(meta); - } - - public static boolean isAnyMetaBlank(String... meta) { - for (String m : meta) { - if (isMetaBlank(m)) { - return true; - } - } - return false; - } - - - private void readMetadata() throws IOException, CsvException { - LOGGER.info("Reading metadata file..."); - headerlessMetaContents = readFile(root); - LOGGER.info("Read metadata file"); - } - - private void initLookup(HashMap minuteIdPathMap, Path root) throws IOException { - long start = System.nanoTime(); - Path file = root.resolve(CONCEPTS_FILE_NAME); - LOGGER.info("Initialising Lookup from {}", file); - List contents = Files.readAllLines(file, StandardCharsets.UTF_8); - contents.stream().forEach(s -> { - if (!s.startsWith(KEY_MINUTEID)) { - // Catch the header line, which is not important - String[] items = s.split(","); // Csv - String minuteId = items[CONCEPTS_MINUTEID_COL]; - String imagePath = cleanImagePath(items[CONCEPTS_IMAGEPATH_COL]); - LOGGER.trace("Adding to lookup: {} <-> {}", minuteId, imagePath); - minuteIdPathMap.put(minuteId, imagePath); - } - }); - long time = (System.nanoTime() - start) / 1000000L; - LOGGER.info("Successfully initialised the lookup with {} entries in {}ms", minuteIdPathMap.size(), time); - } - - private List readListOfFiles(Path root) throws IOException, CsvException { - Path file = root.resolve(LSC_REPORT_VALID_FILNE_NAME); - CSVReader csv = new CSVReader(Files.newBufferedReader(file, StandardCharsets.UTF_8)); - List lookupContents = csv.readAll(); - lookupContents.remove(0); // Remove header - return lookupContents; - } - - private void initMap(List listOfFiles) { - listOfFiles.stream().forEach(s -> { - final String sanitizeFilename = sanitizeFilename(s[0]); - final Optional minuteId = filenameToMinuteId(sanitizeFilename); - minuteId.ifPresent(value -> filenameToMinuteIdMap.put(sanitizeFilename, value)); - }); - } - - public void initMetadata() throws IOException, CsvException { - LOGGER.info("Initialising metadata lookup..."); - readMetadata(); - initMetaPerMinuteId(); - LOGGER.info("Initialised metadata lookup."); - } - - private void initMetaPerMinuteId() { - headerlessMetaContents.stream().forEach(items -> { - metaPerMinute.put(items[META_MIN_COL], items); - }); - } - - private List readFile(Path root) throws IOException, CsvException { - Path file = root.resolve(METADATA_FILE_NAME); - - CSVReader csv = new CSVReader(Files.newBufferedReader(file, StandardCharsets.UTF_8)); - List metadataFileContents = csv.readAll(); - metadataFileContents.remove(0); // remove header - return metadataFileContents; - } - - /** - * Immutable - */ - @Deprecated - public List getHeaderlessMetaContents() { - return Collections.unmodifiableList(headerlessMetaContents); - } - - public Map getMetaPerMinuteId() { - return Collections.unmodifiableMap(metaPerMinute); - } - - public Map getFilenameToMinuteIdLookUp() { - return Collections.unmodifiableMap(filenameToMinuteIdMap); - } - - /** - * Immutable - */ - @Deprecated - public Map getMinuteIdPathMap() { - return Collections.unmodifiableMap(minuteIdPathMap); - } - -} - - diff --git a/cineast-runtime/src/main/java/org/vitrivr/cineast/standalone/importer/lsc2020/MetaImportHandler.java b/cineast-runtime/src/main/java/org/vitrivr/cineast/standalone/importer/lsc2020/MetaImportHandler.java deleted file mode 100644 index 692f5c694..000000000 --- a/cineast-runtime/src/main/java/org/vitrivr/cineast/standalone/importer/lsc2020/MetaImportHandler.java +++ /dev/null @@ -1,46 +0,0 @@ -package org.vitrivr.cineast.standalone.importer.lsc2020; - -import com.opencsv.exceptions.CsvException; -import java.io.IOException; -import java.nio.file.Path; -import org.apache.logging.log4j.LogManager; -import org.apache.logging.log4j.Logger; -import org.vitrivr.cineast.core.data.entities.MediaSegmentMetadataDescriptor; -import org.vitrivr.cineast.core.db.setup.EntityCreator; -import org.vitrivr.cineast.standalone.config.Config; -import org.vitrivr.cineast.standalone.importer.handlers.DataImportHandler; - -public class MetaImportHandler extends DataImportHandler { - - private static final Logger LOGGER = LogManager.getLogger(MetaImportHandler.class); - - private final boolean clean; - - public MetaImportHandler(int threads, int batchSize, boolean clean) { - super(threads, batchSize); - this.clean = clean; - final EntityCreator ec = Config.sharedConfig().getDatabase().getEntityCreatorSupplier().get(); - /* Beware, this drops the table */ - if (clean) { - LOGGER.info("Dropping table ..."); - ec.dropSegmentMetadataEntity(); - LOGGER.info("Finished dropping table for entity "); - ec.createSegmentMetadataEntity(); - LOGGER.info("Re-created SegmentMetaData entity"); - ec.close(); - } - } - - @Override - public void doImport(Path path) { - try { - LSCUtilities.create(path); - } catch (IOException | CsvException e) { - LOGGER.fatal("Error in initialisation", e); - LOGGER.fatal("Crashing now"); - return; - } - LOGGER.info("Starting LSC metadata import from folder {}", path); - this.futures.add(this.service.submit(new DataImportRunner(new MetaImporter(path), MediaSegmentMetadataDescriptor.ENTITY, "lsc-metadata", clean))); - } -} diff --git a/cineast-runtime/src/main/java/org/vitrivr/cineast/standalone/importer/lsc2020/MetaImporter.java b/cineast-runtime/src/main/java/org/vitrivr/cineast/standalone/importer/lsc2020/MetaImporter.java deleted file mode 100644 index b01dfc2ef..000000000 --- a/cineast-runtime/src/main/java/org/vitrivr/cineast/standalone/importer/lsc2020/MetaImporter.java +++ /dev/null @@ -1,204 +0,0 @@ -package org.vitrivr.cineast.standalone.importer.lsc2020; - -import com.opencsv.exceptions.CsvException; -import java.io.IOException; -import java.nio.file.Files; -import java.nio.file.Path; -import java.nio.file.StandardOpenOption; -import java.time.LocalDateTime; -import java.time.ZonedDateTime; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.Iterator; -import java.util.List; -import java.util.Map; -import java.util.Optional; -import org.apache.commons.lang3.StringUtils; -import org.apache.logging.log4j.LogManager; -import org.apache.logging.log4j.Logger; -import org.vitrivr.cineast.core.data.entities.MediaSegmentMetadataDescriptor; -import org.vitrivr.cineast.core.data.providers.primitive.PrimitiveTypeProvider; -import org.vitrivr.cineast.core.importer.Importer; - -/** - * Importer for the LSC 2020 metadata, delivered with the dataset. - */ -public class MetaImporter implements Importer> { - - private static final Logger LOGGER = LogManager.getLogger(MetaImporter.class); - private final Map metadataMap; - private final boolean logsEnabled = Boolean.parseBoolean(System.getProperty("org.vitrivr.cineast.standalone.importer.lsc2020.MetaImporter.logsEnabled", "false")); - private final int logCadence = Integer.parseInt(System.getProperty("org.vitrivr.cineast.standalone.importer.lsc2020.MetaImporter.logCadence", "1000")); - private Map filenameToMinuteId; - private List metaNoPath = new ArrayList<>(); - private List written = new ArrayList<>(); - private Path root; - private Iterator> currentDataIterator = null; - private Iterator> iterator; - private int nextsSinceLastDump = 0; - - public MetaImporter(Path path) { - this.root = path; - try { - LSCUtilities lsc = LSCUtilities.create(path); - lsc.initMetadata(); - filenameToMinuteId = lsc.getFilenameToMinuteIdLookUp(); - metadataMap = lsc.getMetaPerMinuteId(); - iterator = filenameToMinuteId.entrySet().iterator(); - } catch (IOException | CsvException e) { - LOGGER.error("Failed to prepare metadata readout due to {}", e, e); - throw new RuntimeException("Failed to prepare metadata readout", e); - } - - createLogFiles(); - LOGGER.info("Finished setup of Importer. Importing now..."); - } - - static HashMap meta(String filename, String domain, String name, - String value) { - final HashMap map = new HashMap<>(); - // "id" - map.put(MediaSegmentMetadataDescriptor.FIELDNAMES[0], - PrimitiveTypeProvider.fromObject(LSCUtilities.pathToSegmentId(filename))); - // domain - map.put(MediaSegmentMetadataDescriptor.FIELDNAMES[1], PrimitiveTypeProvider.fromObject(domain)); - // key - map.put(MediaSegmentMetadataDescriptor.FIELDNAMES[2], PrimitiveTypeProvider.fromObject(name)); - // value - map.put(MediaSegmentMetadataDescriptor.FIELDNAMES[3], PrimitiveTypeProvider.fromObject(value)); - return map; - } - - /** - * Will create (and delete if pre-existing) log files. Only executed if logs are enabled - */ - private void createLogFiles() { - if (logsEnabled) { - try { - Path noPathFile = root.resolve(LSCUtilities.META_NO_PATH_FILE); - Path processedFile = root.resolve(LSCUtilities.WRITTEN_FILE); - Files.deleteIfExists(noPathFile); - Files.deleteIfExists(processedFile); - Files.createFile(processedFile); - } catch (IOException e) { - LOGGER.error("Could not open important housekeeping files", e); - } - } - } - - private Optional>> parseLine(String filename, - String[] items) { - if (items.length != LSCUtilities.META_NAMES.length) { - LOGGER.error("The line's number of entries is illegal. Expected={}, Found={}. Line={}", - LSCUtilities.META_NAMES.length, items.length, items); - throw new RuntimeException("Too few metadata entries."); - } - String minuteId = LSCUtilities.filenameToMinuteId(filename).get(); - List> list = new ArrayList<>(); - for (int i = 0; i < LSCUtilities.META_NAMES.length; i++) { - if (LSCUtilities.META_COLUMNS_IN_USE.contains(i)) { - if (items[i].equalsIgnoreCase("null")) { - continue; - } - list.add(parseMeta(filename, items, i)); - } - } - // Processed temporal metadata, based on filename - final LocalDateTime dt = LSCUtilities.fromMinuteId(minuteId); - list.add(meta(filename, LSCUtilities.DEFAULT_DOMAIN, LSCUtilities.PROCESSED_META_DATETIME, - dt.toString())); - list.add(meta(filename, LSCUtilities.DEFAULT_DOMAIN, LSCUtilities.PROCESSED_META_DAY_OF_WEEK, - String.valueOf(dt.getDayOfWeek()))); - list.add(meta(filename, LSCUtilities.DEFAULT_DOMAIN, LSCUtilities.PROCESSED_META_MONTH, - LSCUtilities.extractMonth(dt))); - list.add(meta(filename, LSCUtilities.DEFAULT_DOMAIN, LSCUtilities.PROCESSED_META_DAY, - LSCUtilities.extractDayStr(dt))); - list.add(meta(filename, LSCUtilities.DEFAULT_DOMAIN, LSCUtilities.PROCESSED_META_YEAR, - LSCUtilities.extractYearStr(dt))); - list.add(meta(filename, LSCUtilities.DEFAULT_DOMAIN, LSCUtilities.PROCESSED_META_HOUR_OF_DAY, - LSCUtilities.extractHourStr(dt))); - if (StringUtils.isNotBlank(items[LSCUtilities.META_UTC_COL]) - && !items[LSCUtilities.META_UTC_COL].equalsIgnoreCase("null")) { - list.add(meta(filename, LSCUtilities.DEFAULT_DOMAIN, LSCUtilities.PROCESSED_META_UTC, - LSCUtilities.convertUtc(items[LSCUtilities.META_UTC_COL]).toString())); - } - // Processed temporal metadata, based on metadata file - if ((StringUtils.isNotBlank(items[LSCUtilities.META_LOCAL_COL]) - && !items[LSCUtilities.META_LOCAL_COL].equalsIgnoreCase("null")) - && (StringUtils.isNotBlank(items[LSCUtilities.META_TIMEZONE_COL]) - && !items[LSCUtilities.META_TIMEZONE_COL].equalsIgnoreCase("null"))) { - final ZonedDateTime zdt = LSCUtilities - .convertLocal(items[LSCUtilities.META_LOCAL_COL], items[LSCUtilities.META_TIMEZONE_COL]); - list.add(meta(filename, LSCUtilities.DEFAULT_DOMAIN, LSCUtilities.PROCESSED_META_LOCAL, - zdt.toString())); - list.add(meta(filename, LSCUtilities.DEFAULT_DOMAIN, LSCUtilities.PROCESSED_META_PHASE_OF_DAY, - LSCUtilities.extractPhaseOfDay(zdt))); - } - written.add(minuteId); - return Optional.of(list); - } - - private HashMap parseMeta(String path, String[] items, int index) { - String name = LSCUtilities.META_NAMES[index]; - if (name.equalsIgnoreCase(LSCUtilities.META_LAT_NAME) || name - .equalsIgnoreCase(LSCUtilities.META_LON_NAME)) { - return meta(path, "LOCATION" /*SpatialDistance.METADATA_DOMAIN*/, - LSCUtilities.META_NAMES[index], items[index]); - } else { - return meta(path, LSCUtilities.DEFAULT_DOMAIN, LSCUtilities.META_NAMES[index], items[index]); - } - } - - @Override - public Map readNext() { - // Has to read new line - do { - if (this.currentDataIterator == null && this.iterator.hasNext()) { - //LOGGER.trace("Init / Next: dataIt==null && it.hasNext"); - Map.Entry entry = iterator.next(); - Optional>> parsed = parseLine(entry.getKey(), - metadataMap.get(entry.getValue())); - parsed.ifPresent(maps -> this.currentDataIterator = maps.iterator()); - } - if (this.currentDataIterator != null && this.currentDataIterator.hasNext()) { - //LOGGER.trace("dataNext: dataIt.hasNext"); - Map out = this.currentDataIterator.next(); - if (!currentDataIterator.hasNext()) { - // reset, so Init / Next occurs - currentDataIterator = null; - } - //LOGGER.trace("Returning metadata: {}", out); - writeLogs(); - return out; - } - } while (this.currentDataIterator == null && this.iterator.hasNext()); - LOGGER.info("No more to read. Stopping"); - writeLogs(); - return null; - } - - private void writeLogs() { - if (!logsEnabled) { - return; - } - if (nextsSinceLastDump++ > logCadence) { - try { - writeLines(LSCUtilities.META_NO_PATH_FILE, metaNoPath); - writeLines(LSCUtilities.WRITTEN_FILE, written); - } catch (IOException e) { - LOGGER.error("Could not write crucial housekeeping info. Continuing", e); - } - nextsSinceLastDump = 0; - } - } - - private void writeLines(String file, List lines) throws IOException { - Path p = this.root.resolve(file); - Files.write(p, lines, StandardOpenOption.TRUNCATE_EXISTING); - } - - @Override - public Map convert(Map data) { - return data; // See ObjectMetadataImporter -- not sure why - } -} diff --git a/cineast-runtime/src/main/java/org/vitrivr/cineast/standalone/importer/lsc2020/MyscealTagImportHandler.java b/cineast-runtime/src/main/java/org/vitrivr/cineast/standalone/importer/lsc2020/MyscealTagImportHandler.java deleted file mode 100644 index 89d411803..000000000 --- a/cineast-runtime/src/main/java/org/vitrivr/cineast/standalone/importer/lsc2020/MyscealTagImportHandler.java +++ /dev/null @@ -1,26 +0,0 @@ -package org.vitrivr.cineast.standalone.importer.lsc2020; - -import java.nio.file.Path; -import org.apache.logging.log4j.LogManager; -import org.apache.logging.log4j.Logger; -import org.vitrivr.cineast.core.db.dao.reader.TagReader; -import org.vitrivr.cineast.core.features.SegmentTags; -import org.vitrivr.cineast.standalone.importer.handlers.DataImportHandler; - -public class MyscealTagImportHandler extends DataImportHandler { - - private static final Logger LOGGER = LogManager.getLogger(); - - public MyscealTagImportHandler(int threads, int batchsize) { - super(threads, batchsize); - } - - @Override - public void doImport(Path path) { - LOGGER.info("Starting mysceal tag import from {}", path); - this.futures.add(this.service.submit(new DataImportRunner(new MyscealTagImporter(path, true), - TagReader.TAG_ENTITY_NAME, "lsc-mysceal-tags-unique"))); - this.futures.add(this.service.submit(new DataImportRunner(new MyscealTagImporter(path, false), - SegmentTags.SEGMENT_TAGS_TABLE_NAME, "lsc-mysceal-tags-segment"))); - } -} diff --git a/cineast-runtime/src/main/java/org/vitrivr/cineast/standalone/importer/lsc2020/MyscealTagImporter.java b/cineast-runtime/src/main/java/org/vitrivr/cineast/standalone/importer/lsc2020/MyscealTagImporter.java deleted file mode 100644 index e0bef9f41..000000000 --- a/cineast-runtime/src/main/java/org/vitrivr/cineast/standalone/importer/lsc2020/MyscealTagImporter.java +++ /dev/null @@ -1,112 +0,0 @@ -package org.vitrivr.cineast.standalone.importer.lsc2020; - -import java.io.IOException; -import java.nio.file.Path; -import java.util.HashMap; -import java.util.Iterator; -import java.util.List; -import java.util.Map; -import java.util.Map.Entry; -import org.apache.logging.log4j.LogManager; -import org.apache.logging.log4j.Logger; -import org.vitrivr.cineast.core.data.Pair; -import org.vitrivr.cineast.core.data.providers.primitive.PrimitiveTypeProvider; -import org.vitrivr.cineast.core.db.dao.reader.TagReader; -import org.vitrivr.cineast.core.importer.Importer; -import org.vitrivr.cineast.standalone.config.Config; - -public class MyscealTagImporter implements Importer> { - - private static final Logger LOGGER = LogManager.getLogger(MyscealTagImporter.class); - - private final Path file; - - private volatile Iterator uniqueTagIterator; - private volatile Iterator>>> tagScoreIterator; - private volatile String currentSegmentId; - private volatile Iterator> currentIterator; - - private final boolean tagLookup; - - private final TagReader tagReader; - - /** - * @param file - The JSON file with the tags - * @param tagLookup - Whether the import is for the taglookup or actual tags with scores (true for lookup) - */ - public MyscealTagImporter(final Path file, boolean tagLookup) { - this.file = file; - this.tagLookup = tagLookup; - try { - final JsonTagReader reader = new JsonTagReader(file); - uniqueTagIterator = reader.getUniqueTags().stream().iterator(); - tagScoreIterator = reader.getTagScoreMap().entrySet().iterator(); - if (tagLookup) { - tagReader = new TagReader(Config.sharedConfig().getDatabase().getSelectorSupplier().get()); - } else { - tagReader = null; - } - } catch (IOException e) { - throw new RuntimeException("Could not parse json file", e); - } - } - - @Override - public Map readNext() { - if (this.tagLookup) { - return readNextTagLookup(); - } else { - return readNextTagScore(); - } - } - - /** - * Returns the next tag score element. In other words, this returns the next triple segmentId, tagId, score als long as there are these triples. Those triples are constructed by first getting the current segmentId and then iterating over this segment's tags until they are all processed - */ - private Map readNextTagScore() { - do { - if (currentSegmentId == null && tagScoreIterator.hasNext()) { - /* Get current segment id and iterator */ - final Map.Entry>> entry = tagScoreIterator.next(); - currentSegmentId = entry.getKey(); - currentIterator = entry.getValue().iterator(); - } - if (currentIterator.hasNext()) { - /* Commit current segment tag with score */ - final Pair segmentTag = currentIterator.next(); - final Map map = new HashMap<>(); - map.put("id", PrimitiveTypeProvider.fromObject(currentSegmentId)); - map.put("tagid", PrimitiveTypeProvider.fromObject(segmentTag.first)); - map.put("score", PrimitiveTypeProvider.fromObject(segmentTag.second)); - return map; - } else { - /* Reset current iterator & segmentId */ - currentIterator = null; - currentSegmentId = null; - } - } while (currentIterator == null && tagScoreIterator.hasNext()); - return null; - } - - private Map readNextTagLookup() { - if (this.uniqueTagIterator.hasNext()) { - final String next = this.uniqueTagIterator.next(); - // Only add new tags to the system - if (tagReader.getTagById(next) != null) { - final Map map = new HashMap<>(); - map.put(TagReader.TAG_ID_COLUMNNAME, PrimitiveTypeProvider.fromObject(next)); - map.put(TagReader.TAG_NAME_COLUMNNAME, PrimitiveTypeProvider.fromObject(next)); - map.put(TagReader.TAG_DESCRIPTION_COLUMNNAME, PrimitiveTypeProvider - .fromObject(next)); // LSC Context: No description available. Use label instead - return map; - } - } - return null; - } - - @Override - public Map convert(Map data) { - return data; - } - -} diff --git a/cineast-runtime/src/main/java/org/vitrivr/cineast/standalone/importer/lsc2020/OCRImportHandler.java b/cineast-runtime/src/main/java/org/vitrivr/cineast/standalone/importer/lsc2020/OCRImportHandler.java deleted file mode 100644 index 5b5322719..000000000 --- a/cineast-runtime/src/main/java/org/vitrivr/cineast/standalone/importer/lsc2020/OCRImportHandler.java +++ /dev/null @@ -1,38 +0,0 @@ -package org.vitrivr.cineast.standalone.importer.lsc2020; - -import com.opencsv.exceptions.CsvException; -import java.io.IOException; -import java.nio.file.Path; -import org.apache.logging.log4j.LogManager; -import org.apache.logging.log4j.Logger; -import org.vitrivr.cineast.core.features.OCRSearch; -import org.vitrivr.cineast.standalone.importer.handlers.DataImportHandler; - -public class OCRImportHandler extends DataImportHandler { - - private static final Logger LOGGER = LogManager.getLogger(OCRImportHandler.class); - private final boolean clean; - - /** - * Constructor; creates a new DataImportHandler with specified number of threads and batchsize. - * - * @param threads Number of threads to use for data import. - * @param batchsize Size of data batches that are sent to the persistence layer. - */ - public OCRImportHandler(int threads, int batchsize, boolean clean) { - super(threads, batchsize); - this.clean = clean; - } - - @Override - public void doImport(Path path) { - try { - LSCUtilities.create(path); - } catch (IOException | CsvException e) { - LOGGER.fatal("Error in init", e); - return; - } - LOGGER.info("Starting LSC OCR import from {}", path); - this.futures.add(this.service.submit(new DataImportRunner(new OCRImporter(path), OCRSearch.OCR_TABLE_NAME, "lsc-ocr", clean))); - } -} diff --git a/cineast-runtime/src/main/java/org/vitrivr/cineast/standalone/importer/lsc2020/OCRImporter.java b/cineast-runtime/src/main/java/org/vitrivr/cineast/standalone/importer/lsc2020/OCRImporter.java deleted file mode 100644 index 6d0cd3ede..000000000 --- a/cineast-runtime/src/main/java/org/vitrivr/cineast/standalone/importer/lsc2020/OCRImporter.java +++ /dev/null @@ -1,60 +0,0 @@ -package org.vitrivr.cineast.standalone.importer.lsc2020; - -import com.opencsv.CSVReader; -import com.opencsv.exceptions.CsvException; -import java.io.IOException; -import java.nio.file.Files; -import java.nio.file.Path; -import java.util.HashMap; -import java.util.Iterator; -import java.util.Map; -import org.apache.logging.log4j.LogManager; -import org.apache.logging.log4j.Logger; -import org.vitrivr.cineast.core.data.entities.SimpleFulltextFeatureDescriptor; -import org.vitrivr.cineast.core.data.providers.primitive.PrimitiveTypeProvider; -import org.vitrivr.cineast.core.importer.Importer; - -/** - * Headerless csv file. column 0 is filename, column 1 is OCR - * B00000890_21I6X0_20180514_082338E,patages,"tensor(9.1535e-05, device='cuda:0')" - */ -public class OCRImporter implements Importer> { - - private static final Logger LOGGER = LogManager.getLogger(OCRImporter.class); - - private final Path root; - - private Iterator> iterator; - - public OCRImporter(Path root) { - this.root = root; - try { - CSVReader reader = new CSVReader(Files.newBufferedReader(root.resolve("OCR_result.csv"))); - iterator = reader.readAll().stream().map(line -> { - String segment = LSCUtilities.pathToSegmentId(line[0]); - PrimitiveTypeProvider value = PrimitiveTypeProvider.fromObject(line[1]); - HashMap map = new HashMap<>(2); - map.put(SimpleFulltextFeatureDescriptor.FIELDNAMES[0], PrimitiveTypeProvider.fromObject(segment)); - map.put(SimpleFulltextFeatureDescriptor.FIELDNAMES[1], value); - return (Map) map; // Apparently, without explicit casting the compiler is a sad panda - }).iterator(); - LOGGER.info("Successfully read and parsed the import file"); - } catch (IOException | CsvException e) { - LOGGER.fatal("Could not read importfile", e); - } - } - - @Override - public Map readNext() { - if (iterator != null && iterator.hasNext()) { - return iterator.next(); - } else { - return null; - } - } - - @Override - public Map convert(Map data) { - return data; - } -} diff --git a/cineast-runtime/src/main/java/org/vitrivr/cineast/standalone/importer/lsc2020/ProcessingMetaImportHandler.java b/cineast-runtime/src/main/java/org/vitrivr/cineast/standalone/importer/lsc2020/ProcessingMetaImportHandler.java deleted file mode 100644 index cfec16e86..000000000 --- a/cineast-runtime/src/main/java/org/vitrivr/cineast/standalone/importer/lsc2020/ProcessingMetaImportHandler.java +++ /dev/null @@ -1,133 +0,0 @@ -package org.vitrivr.cineast.standalone.importer.lsc2020; - -import com.opencsv.exceptions.CsvException; -import java.io.IOException; -import java.nio.file.Path; -import java.util.HashMap; -import java.util.Map; -import org.apache.logging.log4j.LogManager; -import org.apache.logging.log4j.Logger; -import org.vitrivr.cineast.core.db.cottontaildb.CottontailEntityCreator; -import org.vitrivr.cineast.core.db.dao.reader.TagReader; -import org.vitrivr.cineast.core.db.setup.AttributeDefinition; -import org.vitrivr.cineast.core.db.setup.EntityCreator; -import org.vitrivr.cineast.core.db.setup.EntityDefinition; -import org.vitrivr.cineast.core.features.SegmentTags; -import org.vitrivr.cineast.standalone.config.Config; -import org.vitrivr.cineast.standalone.importer.handlers.DataImportHandler; -import org.vitrivr.cottontail.grpc.CottontailGrpc; - -public class ProcessingMetaImportHandler extends DataImportHandler { - - private static final Logger LOGGER = LogManager.getLogger(); - private static final String TABLE_NAME = "features_table_lsc20meta"; // Features is misleading, in future LSC / VBS use different one - private static final EntityDefinition METADATA_TABLE = new EntityDefinition.EntityDefinitionBuilder( - TABLE_NAME) - .withAttributes( - new AttributeDefinition("id", AttributeDefinition.AttributeType.STRING, - createHintsForId()), - new AttributeDefinition("minute_id", AttributeDefinition.AttributeType.STRING), - new AttributeDefinition("utc_time", AttributeDefinition.AttributeType.STRING), - new AttributeDefinition("local_time", AttributeDefinition.AttributeType.STRING), - new AttributeDefinition("timezone", AttributeDefinition.AttributeType.STRING), - new AttributeDefinition("lat", AttributeDefinition.AttributeType.DOUBLE), - new AttributeDefinition("lon", AttributeDefinition.AttributeType.DOUBLE), - new AttributeDefinition("semantic_name", AttributeDefinition.AttributeType.STRING), - new AttributeDefinition("elevation", AttributeDefinition.AttributeType.STRING), - new AttributeDefinition("speed", AttributeDefinition.AttributeType.STRING), - new AttributeDefinition("heart", AttributeDefinition.AttributeType.STRING), - new AttributeDefinition("calories", AttributeDefinition.AttributeType.STRING), - new AttributeDefinition("activity_type", AttributeDefinition.AttributeType.STRING), - new AttributeDefinition("steps", AttributeDefinition.AttributeType.STRING), - new AttributeDefinition("p_utc_standard", AttributeDefinition.AttributeType.STRING), - new AttributeDefinition("p_local_standard", AttributeDefinition.AttributeType.STRING), - new AttributeDefinition("p_day_of_week", AttributeDefinition.AttributeType.STRING), - new AttributeDefinition("p_phase_of_day", AttributeDefinition.AttributeType.STRING), - new AttributeDefinition("p_year", AttributeDefinition.AttributeType.INT), - new AttributeDefinition("p_month", AttributeDefinition.AttributeType.STRING), - new AttributeDefinition("p_hour", AttributeDefinition.AttributeType.INT), - new AttributeDefinition("p_datetime", AttributeDefinition.AttributeType.STRING), - new AttributeDefinition("p_day", AttributeDefinition.AttributeType.INT) - ) - .build(); - private final boolean metaAsTable; - - /** - * Constructor; creates a new DataImportHandler with specified number of threads and batchsize. - * - * @param threads Number of threads to use for data import. - * @param batchsize Size of data batches that are sent to the persistence layer. - * @param mode The mode of the import - * @param clean Whether to clean the data before import. has no impact on tag import - */ - public ProcessingMetaImportHandler(int threads, int batchsize, Mode mode, boolean clean) { - super(threads, batchsize); - if (mode == Mode.TABLE) { - metaAsTable = true; - } else { - metaAsTable = false; - } - if (clean) { - createEntityForced(); - } - } - - private static Map createHintsForId() { - Map map = new HashMap<>(); - map.put(CottontailEntityCreator.INDEX_HINT, CottontailGrpc.IndexType.HASH.name()); - return map; - } - - public static void createEntityForced() { - createEntity(true); - } - - public static void createEntity(boolean deleteBeforeCreate) { - final EntityCreator ec = Config.sharedConfig().getDatabase().getEntityCreatorSupplier().get(); - if (ec != null) { - if (deleteBeforeCreate && ec.existsEntity(TABLE_NAME)) { - ec.dropEntity(TABLE_NAME); - } - ec.createEntity(METADATA_TABLE); - } - } - - @Override - public void doImport(Path path) { - LOGGER.info("Starting " + (metaAsTable ? "meta-as-table" : "meta-as-tag") + " import in {}", - path); - try { - LSCUtilities.create(path); - LSCUtilities.getInstance().initMetadata(); - } catch (IOException | CsvException e) { - LOGGER.error("Cannot do import as initialization failed.", e); - return; - } - if (metaAsTable) { - this.futures.add(this.service.submit(new DataImportRunner( - new ProcessingMetaImporter(path, ProcessingMetaImporter.Type.META_AS_TABLE), - "features_table_lsc20meta", "lsc-metaAsTable"))); - } else { - this.futures.add(this.service.submit(new DataImportRunner( - new ProcessingMetaImporter(path, ProcessingMetaImporter.Type.TAG_LOOKUP), - TagReader.TAG_ENTITY_NAME, "lsc-metaAsTagsLookup"))); - this.futures.add(this.service.submit( - new DataImportRunner(new ProcessingMetaImporter(path, ProcessingMetaImporter.Type.TAG), - SegmentTags.SEGMENT_TAGS_TABLE_NAME, "lsc-metaAsTags"))); - } - } - - /** - * The mode specifies how the {@link ProcessingMetaImporter} actually imports the data - */ - public enum Mode { - /** - * Required for boolean retrieval on the data, it stores the data in a -dedicated- entity - */ - TABLE, - /** - * Imports tags - */ - TAGS - } -} diff --git a/cineast-runtime/src/main/java/org/vitrivr/cineast/standalone/importer/lsc2020/ProcessingMetaImporter.java b/cineast-runtime/src/main/java/org/vitrivr/cineast/standalone/importer/lsc2020/ProcessingMetaImporter.java deleted file mode 100644 index 3f03d853e..000000000 --- a/cineast-runtime/src/main/java/org/vitrivr/cineast/standalone/importer/lsc2020/ProcessingMetaImporter.java +++ /dev/null @@ -1,340 +0,0 @@ -package org.vitrivr.cineast.standalone.importer.lsc2020; - -import java.nio.file.Path; -import java.time.LocalDateTime; -import java.time.ZonedDateTime; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.HashMap; -import java.util.HashSet; -import java.util.Iterator; -import java.util.List; -import java.util.Map; -import java.util.Optional; -import org.apache.commons.lang3.StringUtils; -import org.apache.logging.log4j.LogManager; -import org.apache.logging.log4j.Logger; -import org.vitrivr.cineast.core.data.providers.primitive.PrimitiveTypeProvider; -import org.vitrivr.cineast.core.db.dao.reader.TagReader; -import org.vitrivr.cineast.core.importer.Importer; - -public class ProcessingMetaImporter implements Importer> { - - public static final List TAG_CANDIDATES = Arrays.asList(LSCUtilities.META_SEMANTIC_COL, LSCUtilities.META_ACTIVITY_COL, LSCUtilities.META_TIMEZONE_COL, LSCUtilities.META_UTC_COL, LSCUtilities.META_LOCAL_COL); - private static final Logger LOGGER = LogManager.getLogger(ProcessingMetaImporter.class); - private final Type type; - private final Map metaPerMinuteId; - private final Map filenameToMinuteIdLookUp; - private Iterator> currentDataIterator = null; - private Iterator> iterator; - private Map minuteIdPathMap = new HashMap<>(); - private HashSet uniqueList = new HashSet<>(); - private HashSet uniqueTemporalMetadata = new HashSet<>(); - - public ProcessingMetaImporter(final Path path, final Type type) { - this.type = type; - - // We do not initialise LSCUtilities, as they are created outside. - LSCUtilities lsc = LSCUtilities.getInstance(); - filenameToMinuteIdLookUp = lsc.getFilenameToMinuteIdLookUp(); - metaPerMinuteId = lsc.getMetaPerMinuteId(); - iterator = filenameToMinuteIdLookUp.entrySet().iterator(); - LOGGER.info("Finished setup of Importer. Importing now..."); - } - - private Optional>> parseLine(String path, String[] items) { - String minuteId = items[LSCUtilities.META_MIN_COL]; - if (path == null) { - // cannot resolve - return Optional.empty(); - } - String segmentId = LSCUtilities.cleanImagePath(path); - segmentId = LSCUtilities.pathToSegmentId(segmentId); - List> list = new ArrayList<>(); - switch (this.type) { - case TAG: - case TAG_LOOKUP: - Optional>> maps = parseAsTag(segmentId, path, items); - maps.ifPresent(list::addAll); - - break; - case META_AS_TABLE: - list.add(parseAsMeta(segmentId, path, items)); - break; - } - return Optional.of(list); - } - - private Map parseAsMeta(String segmentId, String path, String[] items) { - final HashMap map = new HashMap<>(items.length + 9); - - map.put("id", PrimitiveTypeProvider.fromObject(segmentId)); - for (int i = 0; i < items.length; i++) { - switch (i) { - case LSCUtilities.META_LAT_COL: - case LSCUtilities.META_LON_COL: - if (StringUtils.isNotBlank(items[i]) && !items[i].equalsIgnoreCase("null")) { - // Only add if useful - - map.put(LSCUtilities.META_NAMES[i], PrimitiveTypeProvider.fromObject(Double.parseDouble(items[i]))); - } else { - LOGGER.trace("Did not include " + segmentId + " :" + LSCUtilities.META_NAMES[i] + ", beacuse its blank or null:" + items[i]); - map.put(LSCUtilities.META_NAMES[i], PrimitiveTypeProvider.fromObject(Double.NaN)); - } - break; - default: - map.put(LSCUtilities.META_NAMES[i], PrimitiveTypeProvider.fromObject(items[i])); - break; - } - } - final String minuteId = LSCUtilities.filenameToMinuteId(path).get(); // Purposely no isPresent check, because it should not be possible - final LocalDateTime dt = LSCUtilities.fromMinuteId(minuteId); - map.put(LSCUtilities.PROCESSED_META_DATETIME, PrimitiveTypeProvider.fromObject(dt.toString())); - map.put(LSCUtilities.PROCESSED_META_DAY_OF_WEEK, PrimitiveTypeProvider.fromObject(String.valueOf(dt.getDayOfWeek()))); - map.put(LSCUtilities.PROCESSED_META_MONTH, PrimitiveTypeProvider.fromObject(LSCUtilities.extractMonth(dt))); - // Numeric values - map.put(LSCUtilities.PROCESSED_META_DAY, PrimitiveTypeProvider.fromObject(LSCUtilities.extractDay(dt))); - map.put(LSCUtilities.PROCESSED_META_YEAR, PrimitiveTypeProvider.fromObject(LSCUtilities.extractYear(dt))); - map.put(LSCUtilities.PROCESSED_META_HOUR_OF_DAY, PrimitiveTypeProvider.fromObject(LSCUtilities.extractHour(dt))); - if (StringUtils.isNotBlank(items[LSCUtilities.META_UTC_COL]) && !items[LSCUtilities.META_UTC_COL].equalsIgnoreCase("null")) { - map.put(LSCUtilities.PROCESSED_META_UTC, PrimitiveTypeProvider.fromObject(LSCUtilities.convertUtc(items[LSCUtilities.META_UTC_COL]).toString())); - } - // Processed temporal metadata, based on metadata file - if ((StringUtils.isNotBlank(items[LSCUtilities.META_LOCAL_COL]) && !items[LSCUtilities.META_LOCAL_COL].equalsIgnoreCase("null")) - && (StringUtils.isNotBlank(items[LSCUtilities.META_TIMEZONE_COL]) && !items[LSCUtilities.META_TIMEZONE_COL].equalsIgnoreCase("null"))) { - final ZonedDateTime zdt = LSCUtilities.convertLocal(items[LSCUtilities.META_LOCAL_COL], items[LSCUtilities.META_TIMEZONE_COL]); - map.put(LSCUtilities.PROCESSED_META_LOCAL, PrimitiveTypeProvider.fromObject(zdt.toString())); - map.put(LSCUtilities.PROCESSED_META_PHASE_OF_DAY, PrimitiveTypeProvider.fromObject(LSCUtilities.extractPhaseOfDay(zdt))); - } else { - map.put(LSCUtilities.PROCESSED_META_LOCAL, PrimitiveTypeProvider.fromObject(null)); - map.put(LSCUtilities.PROCESSED_META_PHASE_OF_DAY, PrimitiveTypeProvider.fromObject(null)); - } - - return map; - } - - private Optional>> parseAsTag(String segmentid, String path, String[] items) { - List> list = new ArrayList<>(); - for (int i = 0; i < LSCUtilities.META_NAMES.length; i++) { - if (items[i].equalsIgnoreCase("null")) { - continue; - } - Optional> data = parse(segmentid, path, items, i); - if (!data.isPresent()) { - continue; - } else { - list.add(data.get()); - } - } - // Additionally processed meta as tags: DayOfWeek, Month, Day, Year, HourOfDay - final String minuteId = LSCUtilities.filenameToMinuteId(path).get(); // Purposely no isPresent check, because it should not be possible - final LocalDateTime dt = LSCUtilities.fromMinuteId(minuteId); - BiProducer> parser; - if (type == Type.TAG) { - parser = this::toTag; - } else if (type == Type.TAG_LOOKUP) { - parser = this::toTagLookup; - } else { - parser = null; // To willfully throw NPE - } - String dow = String.valueOf(dt.getDayOfWeek()); - String month = LSCUtilities.extractMonth(dt); - String year = LSCUtilities.extractYearStr(dt); - String day = LSCUtilities.extractDayStr(dt); - String hod = LSCUtilities.extractHourStr(dt); - - // Day of week - if (onlyUnique()) { - // tag lookup, it must be unique - if (isUniqueTemporalContext(dow)) { - list.add(parser.produce(segmentid, dow)); - } - } else { - list.add(parser.produce(segmentid, dow)); - } - // Month - if (onlyUnique()) { - if (isUniqueTemporalContext(month)) { - list.add(parser.produce(segmentid, month)); - } - } else { - list.add(parser.produce(segmentid, month)); - } - // Year - if (onlyUnique()) { - if (isUniqueTemporalContext(year)) { - list.add(parser.produce(segmentid, year)); - } - } else { - list.add(parser.produce(segmentid, year)); - } - // Day - if (onlyUnique()) { - if (isUniqueTemporalContext(day)) { - list.add(parser.produce(segmentid, day)); - } - } else { - list.add(parser.produce(segmentid, day)); - } - // HourOfDay - if (onlyUnique()) { - if (isUniqueTemporalContext(hod)) { - list.add(parser.produce(segmentid, hod)); - } - } else { - list.add(parser.produce(segmentid, hod)); - } - if (list.isEmpty()) { - return Optional.empty(); - } else { - return Optional.of(list); - } - } - - private Optional> parse(String segmentid, String path, String[] items, int index) { - switch (this.type) { - case TAG: - return parseTag(segmentid, path, items, index); - case TAG_LOOKUP: - return parseTagForLookup(segmentid, path, items, index); - default: - return Optional.empty(); - } - } - - private Optional> parseTag(String segmentid, String path, String[] items, int index) { - if (TAG_CANDIDATES.contains(index)) { - final String tag = metaAsTag(items, index); - return Optional.of(toTag(segmentid, tag)); - } else { - return Optional.empty(); - } - } - - private Map toTag(String segmentid, String tag) { - return toTag(segmentid, tag, 1); - } - - private Map toTag(String segmentid, String tag, int score) { - final HashMap map = new HashMap<>(3); - map.put("id", PrimitiveTypeProvider.fromObject(segmentid)); - map.put("tagid", PrimitiveTypeProvider.fromObject(tag)); - map.put("score", PrimitiveTypeProvider.fromObject(score)); - return map; - } - - /** - * Must only be called with index values for valid tags tags: id === name, description is empty (no tag expansion done) - */ - private Optional> parseTagForLookup(String segmentid, String path, String[] items, int index) { - if (TAG_CANDIDATES.contains(index)) { - final String tag = metaAsTag(items, index); - if (onlyUnique()) { - if (!isUnique(tag)) { - return Optional.empty(); - } - } - return Optional.of(toTagLookup(segmentid, tag)); - } else { - return Optional.empty(); - } - } - - private Map toTagLookup(String segmentid, String tag) { - final HashMap map = new HashMap<>(3); - map.put(TagReader.TAG_ID_COLUMNNAME, PrimitiveTypeProvider.fromObject(tag)); - map.put(TagReader.TAG_NAME_COLUMNNAME, PrimitiveTypeProvider.fromObject(tag)); - map.put(TagReader.TAG_DESCRIPTION_COLUMNNAME, PrimitiveTypeProvider.fromObject(tag)); // LSC Context no description of tags available. Use tag name as "description" - return map; - } - - - private String metaAsTag(String[] items, int index) { - String tag; - if (index == LSCUtilities.META_UTC_COL) { - tag = LSCUtilities.convertUtc(items[index]).getDayOfWeek().toString(); - } else if (index == LSCUtilities.META_LOCAL_COL) { - String zone = items[LSCUtilities.META_TIMEZONE_COL]; - tag = LSCUtilities.extractPhaseOfDay(LSCUtilities.convertLocal(items[index], zone)); - } else { - tag = items[index]; - } - return tag; - } - - @Override - public Map readNext() { - // Has to read new line - do { - if (this.currentDataIterator == null && this.iterator.hasNext()) { - // LOGGER.trace("Init / Next: dataIt==null && it.hasNext"); - Map.Entry next = this.iterator.next(); - Optional>> parsed = parseLine(next.getKey(), metaPerMinuteId.get(next.getValue())); - parsed.ifPresent(maps -> this.currentDataIterator = maps.iterator()); - } - if (this.currentDataIterator != null && this.currentDataIterator.hasNext()) { - // LOGGER.trace("dataNext: dataIt.hasNext"); - Map out = this.currentDataIterator.next(); - if (!currentDataIterator.hasNext()) { - // reset, so Init / Next occurs - currentDataIterator = null; - } - // LOGGER.trace("Returning metadata: {}", out); - return out; - } - } while (this.currentDataIterator == null && this.iterator.hasNext()); - LOGGER.info("No more to read. Stopping"); - return null; - } - - /** - * Checks if the needle is in the unique set. If so, it's not unique. Otherwise, it's unique and added to the list - */ - private boolean isUnique(String needle) { - boolean found = uniqueList.contains(needle); - if (!found) { - uniqueList.add(needle); - } - return !found; - } - - private boolean isUniqueTemporalContext(String temp) { - boolean found = uniqueTemporalMetadata.contains(temp); - if (!found) { - uniqueTemporalMetadata.add(temp); - } - return !found; - } - - private boolean onlyUnique() { - return type == Type.TAG_LOOKUP; - } - - - @Override - public Map convert(Map data) { - return data; - } - - public enum Type { - /** - * Tags for retrieval - */ - TAG, - /** - * Tags for tag lookup (i.e. autocomplete in vitrivr-ng - */ - TAG_LOOKUP, - /** - * Meta as is and certain processed metadata in a conventional table. - */ - META_AS_TABLE - } - - @FunctionalInterface - public interface BiProducer { - - O produce(I1 i1, I2 i2); - } - -} diff --git a/cineast-runtime/src/main/java/org/vitrivr/cineast/standalone/importer/lsc2020/SpatialImportHandler.java b/cineast-runtime/src/main/java/org/vitrivr/cineast/standalone/importer/lsc2020/SpatialImportHandler.java deleted file mode 100644 index db1f158a9..000000000 --- a/cineast-runtime/src/main/java/org/vitrivr/cineast/standalone/importer/lsc2020/SpatialImportHandler.java +++ /dev/null @@ -1,35 +0,0 @@ -package org.vitrivr.cineast.standalone.importer.lsc2020; - -import com.opencsv.exceptions.CsvException; -import java.io.IOException; -import java.nio.file.Path; -import org.apache.logging.log4j.LogManager; -import org.apache.logging.log4j.Logger; -import org.vitrivr.cineast.standalone.importer.handlers.DataImportHandler; - -/** - * Handler of spatial imports. - */ -public class SpatialImportHandler extends DataImportHandler { - - public static final Logger LOGGER = LogManager.getLogger(SpatialImportHandler.class); - - - public SpatialImportHandler(int threads, int batchSize) { - super(threads, batchSize); - } - - @Override - public void doImport(Path path) { - try { - LSCUtilities.create(path); - } catch (IOException | CsvException e) { - LOGGER.fatal("Error in initialisation", e); - LOGGER.fatal("Crashing now"); - return; - } - LOGGER.info("Starting LSC Spatial metadata as feature import from folder {}", path); - this.futures.add(this.service.submit(new DataImportRunner(new SpatialImporter(path), - "features_SpatialDistance"/*SpatialDistance.ENTITY*/, "lsc-spatialfeature", false))); - } -} diff --git a/cineast-runtime/src/main/java/org/vitrivr/cineast/standalone/importer/lsc2020/SpatialImporter.java b/cineast-runtime/src/main/java/org/vitrivr/cineast/standalone/importer/lsc2020/SpatialImporter.java deleted file mode 100644 index c41e9fd43..000000000 --- a/cineast-runtime/src/main/java/org/vitrivr/cineast/standalone/importer/lsc2020/SpatialImporter.java +++ /dev/null @@ -1,106 +0,0 @@ -package org.vitrivr.cineast.standalone.importer.lsc2020; - -import com.opencsv.exceptions.CsvException; -import java.io.IOException; -import java.nio.file.Path; -import java.util.HashMap; -import java.util.Iterator; -import java.util.Map; -import java.util.Map.Entry; -import java.util.Optional; -import org.apache.logging.log4j.LogManager; -import org.apache.logging.log4j.Logger; -import org.vitrivr.cineast.core.data.Location; -import org.vitrivr.cineast.core.data.ReadableFloatVector; -import org.vitrivr.cineast.core.data.providers.primitive.FloatArrayTypeProvider; -import org.vitrivr.cineast.core.data.providers.primitive.PrimitiveTypeProvider; -import org.vitrivr.cineast.core.importer.Importer; - -/** - * FloatVector: [lat,lon]. Column name is feature and entity name is SpatialDistance::entityName == features_SpatialDistance - */ -public class SpatialImporter implements Importer> { - - private static final Logger LOGGER = LogManager.getLogger(SpatialImporter.class); - - private final Map metadataMap; - private final Map filenameToMinuteIdMap; - - private final Iterator> iterator; - - private final Path root; - - public SpatialImporter(Path path) { - this.root = path; - - try { - LSCUtilities lsc = LSCUtilities.create(path); - lsc.initMetadata(); - filenameToMinuteIdMap = lsc.getFilenameToMinuteIdLookUp(); - metadataMap = lsc.getMetaPerMinuteId(); - iterator = filenameToMinuteIdMap.entrySet().iterator(); - } catch (IOException | CsvException e) { - LOGGER.error("Failed to prepare metadata readout due to {}", e, e); - throw new RuntimeException("Failed to prepare metadata readout", e); - } - LOGGER.info("Initialisation finished successfully. Starting import..."); - } - - private Optional> parseEntry(String key, String[] data) { - String lat = data[LSCUtilities.META_LAT_COL]; - String lon = data[LSCUtilities.META_LON_COL]; - - if (LSCUtilities.isAnyMetaBlank(lat, lon)) { - LOGGER.warn("Either lat or long for {} is blank. Ignoring.", key); - return Optional.empty(); - } - - boolean ignore = false; - float fLat = Float.NaN, fLon = Float.NaN; - try { - fLat = Float.parseFloat(lat); - } catch (NumberFormatException e) { - LOGGER.warn("Could not parse latitute for {}, as it was {}", key, lat, e); - ignore = true; - } - try { - fLon = Float.parseFloat(lon); - } catch (NumberFormatException e) { - LOGGER.warn("Could not parse longitutde for {}, as it was {}", key, lon, e); - ignore = true; - } - if (ignore) { - return Optional.empty(); - } - - Location location = Location.of(fLat, fLon); - FloatArrayTypeProvider vector = new FloatArrayTypeProvider(ReadableFloatVector.toArray(location)); - - final HashMap map = new HashMap<>(); - // id - map.put("id", PrimitiveTypeProvider.fromObject(LSCUtilities.pathToSegmentId(key))); - // feature - map.put("feature", vector); - return Optional.of(map); - } - - - @Override - public Map readNext() { - while (iterator.hasNext()) { - Entry next = iterator.next(); - Optional> parsed = parseEntry(next.getKey(), metadataMap.get(next.getValue())); - if (parsed.isPresent()) { - return parsed.get(); - } - } - return null; - } - - - @Override - public Map convert(Map data) { - return data; - } - -} diff --git a/cineast-runtime/src/main/java/org/vitrivr/cineast/standalone/importer/lsc2020/TemporalImportHandler.java b/cineast-runtime/src/main/java/org/vitrivr/cineast/standalone/importer/lsc2020/TemporalImportHandler.java deleted file mode 100644 index 8d21037f4..000000000 --- a/cineast-runtime/src/main/java/org/vitrivr/cineast/standalone/importer/lsc2020/TemporalImportHandler.java +++ /dev/null @@ -1,42 +0,0 @@ -package org.vitrivr.cineast.standalone.importer.lsc2020; - -import com.opencsv.exceptions.CsvException; -import java.io.IOException; -import java.nio.file.Path; -import org.apache.logging.log4j.LogManager; -import org.apache.logging.log4j.Logger; -import org.vitrivr.cineast.core.data.entities.MediaSegmentDescriptor; -import org.vitrivr.cineast.standalone.importer.handlers.DataImportHandler; - -/** - * Handler of temporal imports. Basically uses file (i.e. segment id) information to populate segmentstart and segmentend fields - */ -public class TemporalImportHandler extends DataImportHandler { - - public static final Logger LOGGER = LogManager.getLogger(TemporalImportHandler.class); - - /** - * Constructor; creates a new DataImportHandler with specified number of threads and batchsize. - * - * @param threads Number of threads to use for data import. - * @param batchsize Size of data batches that are sent to the persistence layer. - */ - public TemporalImportHandler(int threads, int batchsize) { - super(threads, batchsize); - } - - - @Override - public void doImport(final Path path) { - try { - LSCUtilities.create(path); - } catch (IOException | CsvException e) { - LOGGER.fatal("Error during initialisation:", e); - LOGGER.fatal("Stopping immediately."); - return; - } - LOGGER.info("Starting LSC Temporal import: Populate segmentstart and segmentend from folder {}", path); - this.futures.add(this.service.submit(new DataImportRunner(new TemporalImporter(path), - MediaSegmentDescriptor.ENTITY, "lsc-temporal", false))); - } -} diff --git a/cineast-runtime/src/main/java/org/vitrivr/cineast/standalone/importer/lsc2020/TemporalImporter.java b/cineast-runtime/src/main/java/org/vitrivr/cineast/standalone/importer/lsc2020/TemporalImporter.java deleted file mode 100644 index 07de1ab6a..000000000 --- a/cineast-runtime/src/main/java/org/vitrivr/cineast/standalone/importer/lsc2020/TemporalImporter.java +++ /dev/null @@ -1,82 +0,0 @@ -package org.vitrivr.cineast.standalone.importer.lsc2020; - -import com.opencsv.exceptions.CsvException; -import java.io.IOException; -import java.nio.file.Path; -import java.time.LocalDateTime; -import java.time.ZoneOffset; -import java.util.HashMap; -import java.util.Iterator; -import java.util.Map; -import java.util.Map.Entry; -import java.util.Optional; -import org.apache.logging.log4j.LogManager; -import org.apache.logging.log4j.Logger; -import org.vitrivr.cineast.core.data.providers.primitive.PrimitiveTypeProvider; -import org.vitrivr.cineast.core.importer.Importer; - -public class TemporalImporter implements Importer> { - - public static final Logger LOGGER = LogManager.getLogger(TemporalImporter.class); - - private final Map metadataMap; - private final Map filenameToMinuteIdMap; - - private final Iterator> iterator; - - private final Path root; - - public TemporalImporter(final Path path) { - this.root = path; - - try { - final LSCUtilities lsc = LSCUtilities.create(path); - lsc.initMetadata(); - filenameToMinuteIdMap = lsc.getFilenameToMinuteIdLookUp(); - metadataMap = lsc.getMetaPerMinuteId(); - iterator = filenameToMinuteIdMap.entrySet().iterator(); - } catch (IOException | CsvException e) { - LOGGER.error("Failed to prepare metadata readout due to {}", e, e); - throw new RuntimeException("Failed to prepare metadata readout", e); - } - LOGGER.info("Initialisation finished successfully. Starting import now"); - } - - private long toEpochMillis(String minuteId) { - final LocalDateTime date = LSCUtilities.fromMinuteId(minuteId); - return date.toInstant(ZoneOffset.UTC).toEpochMilli(); - } - - private Optional> parseEntry(String key, String[] data) { - final long ms = toEpochMillis(filenameToMinuteIdMap.get(key)); - final PrimitiveTypeProvider msProvider = PrimitiveTypeProvider.fromObject(ms); - final HashMap map = new HashMap<>(); - // id - map.put("id", PrimitiveTypeProvider.fromObject(LSCUtilities.pathToSegmentId(key))); - // temporal info - map.put("segmentstart", msProvider); - map.put("segmentend", PrimitiveTypeProvider.fromObject(ms + 1)); // Segment ends one millis later - map.put("startabs", msProvider); - - return Optional.of(map); - } - - - @Override - public Map readNext() { - while (iterator.hasNext()) { - Entry next = iterator.next(); - Optional> parsed = parseEntry(next.getKey(), metadataMap.get(next.getValue())); - if (parsed.isPresent()) { - return parsed.get(); - } - } - return null; - } - - @Override - public Map convert( - Map map) { - return map; - } -} diff --git a/cineast-runtime/src/main/java/org/vitrivr/cineast/standalone/importer/lsc2020/VisualConceptTagImportHandler.java b/cineast-runtime/src/main/java/org/vitrivr/cineast/standalone/importer/lsc2020/VisualConceptTagImportHandler.java deleted file mode 100644 index fb2ec9730..000000000 --- a/cineast-runtime/src/main/java/org/vitrivr/cineast/standalone/importer/lsc2020/VisualConceptTagImportHandler.java +++ /dev/null @@ -1,30 +0,0 @@ -package org.vitrivr.cineast.standalone.importer.lsc2020; - -import java.nio.file.Path; -import org.apache.logging.log4j.LogManager; -import org.apache.logging.log4j.Logger; -import org.vitrivr.cineast.core.db.dao.reader.TagReader; -import org.vitrivr.cineast.core.features.SegmentTags; -import org.vitrivr.cineast.standalone.importer.handlers.DataImportHandler; - -public class VisualConceptTagImportHandler extends DataImportHandler { - - private static final Logger LOGGER = LogManager.getLogger(); - - /** - * Constructor; creates a new DataImportHandler with specified number of threads and batchsize. - * - * @param threads Number of threads to use for data import. - * @param batchsize Size of data batches that are sent to the persistence layer. - */ - public VisualConceptTagImportHandler(int threads, int batchsize) { - super(threads, batchsize); - } - - @Override - public void doImport(Path path) { - LOGGER.info("Starting visual concept import for tags in {}", path); - this.futures.add(this.service.submit(new DataImportRunner(new VisualConceptTagImporter(path, true), TagReader.TAG_ENTITY_NAME, "lsc-uniqueTags"))); - this.futures.add(this.service.submit(new DataImportRunner(new VisualConceptTagImporter(path), SegmentTags.SEGMENT_TAGS_TABLE_NAME, "lsc-visualConceptsTags"))); - } -} diff --git a/cineast-runtime/src/main/java/org/vitrivr/cineast/standalone/importer/lsc2020/VisualConceptTagImporter.java b/cineast-runtime/src/main/java/org/vitrivr/cineast/standalone/importer/lsc2020/VisualConceptTagImporter.java deleted file mode 100644 index 966d7eba0..000000000 --- a/cineast-runtime/src/main/java/org/vitrivr/cineast/standalone/importer/lsc2020/VisualConceptTagImporter.java +++ /dev/null @@ -1,198 +0,0 @@ -package org.vitrivr.cineast.standalone.importer.lsc2020; - -import com.opencsv.CSVReader; -import com.opencsv.exceptions.CsvException; -import java.io.IOException; -import java.nio.charset.StandardCharsets; -import java.nio.file.Files; -import java.nio.file.Path; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.HashSet; -import java.util.Iterator; -import java.util.List; -import java.util.Map; -import java.util.Set; -import org.apache.logging.log4j.LogManager; -import org.apache.logging.log4j.Logger; -import org.vitrivr.cineast.core.data.providers.primitive.PrimitiveTypeProvider; -import org.vitrivr.cineast.core.db.dao.reader.TagReader; -import org.vitrivr.cineast.core.importer.Importer; - -public class VisualConceptTagImporter implements Importer { - - public static final Logger LOGGER = LogManager.getLogger(); - - public static final String BBOX_IGNORE = "bbox"; - private Iterator content; - private Set uniqueTags; - - private static boolean ignoreColumn(String colName) { - return colName.contains(BBOX_IGNORE) || colName.contains("score") || colName.equals(LSCUtilities.KEY_MINUTEID) || colName.contains("path"); - } - - private static String scoreForCategory(String cat) { - return cat + "_score"; - } - - private static String scoreForConcept(String concept) { - return concept.replace("class", "score"); - } - - private final Path root; - - private String[] headers; - - private final boolean tagReaderOnly; - - private Iterator tagIterator; - - public VisualConceptTagImporter(Path root) { - this(root, false); - } - - public VisualConceptTagImporter(Path root, boolean tagReaderOnly) { - this.root = root; - this.tagReaderOnly = tagReaderOnly; - LOGGER.info("Initializing LSC Visual Concept Importer " + (tagReaderOnly ? "Tag Lookup" : "Tag Import")); - try { - readFile(); - if (tagReaderOnly) { - readTags(); - } else { - readFileTagsPerSegment(); - } - LOGGER.info("Finished initialization."); - } catch (CsvException | IOException e) { - LOGGER.fatal("Error in reading file", e); - LOGGER.throwing(new RuntimeException("Could not initialise importer due to exception in startup", e)); - } - } - - private void readFile() throws IOException, CsvException { - LOGGER.info("Reading concepts file..."); - long start = System.currentTimeMillis(); - Path file = root.resolve(LSCUtilities.CONCEPTS_FILE_NAME); - CSVReader csvReader = new CSVReader(Files.newBufferedReader(file, StandardCharsets.UTF_8)); - content = csvReader.iterator(); - /* get headers */ - headers = content.next(); - LOGGER.info("Finished reading in " + (System.currentTimeMillis() - start) + "ms"); - } - - private void readFileTagsPerSegment() { - LOGGER.info("Parsing tags per segment"); - long start = System.currentTimeMillis(); - Map> map = new HashMap<>(); - while (content.hasNext()) { - String[] line = content.next(); - String imgPath = line[LSCUtilities.CONCEPTS_IMAGEPATH_COL]; - String id = LSCUtilities.pathToSegmentId(LSCUtilities.cleanImagePath(imgPath)); - for (int i = 3; i < line.length; i++) { - if (ignoreContent(line[i])) { - continue; - } - String colName = headers[i]; - if (!ignoreColumn(colName)) { - if (map.containsKey(id)) { - map.get(id).add(line[i]); - } else { - map.put(id, new ArrayList<>()); - } - } - } - } - mapIterator = map.entrySet().iterator(); - LOGGER.info("Finished parsing tags per segment in " + (System.currentTimeMillis() - start) + "ms"); - } - - private static boolean ignoreContent(String tag) { - return tag == null || tag.isEmpty() || tag.equals("NULL"); - } - - private void readTags() { - LOGGER.info("Parsing tags..."); - long start = System.currentTimeMillis(); - uniqueTags = new HashSet<>(); - - while (content.hasNext()) { - String[] l = content.next(); - for (int i = 3; i < l.length; i++) { - if (ignoreColumn(headers[i])) { - continue; - } else { - if (!ignoreContent(l[i])) { - uniqueTags.add(l[i]); - } - } - } - } - tagIterator = uniqueTags.iterator(); - LOGGER.info("Finished parsing tags in " + (System.currentTimeMillis() - start) + "ms"); - } - - private volatile Iterator>> mapIterator; - private volatile String currentId; - private volatile Iterator currentIterator; - - - private String[] readNextPerSegment() { - do { - if (currentId == null && mapIterator.hasNext()) { - Map.Entry> entry = mapIterator.next(); - currentId = entry.getKey(); - currentIterator = entry.getValue().iterator(); - } - if (currentIterator.hasNext()) { - return new String[]{currentId, currentIterator.next()}; - } else { - currentIterator = null; - currentId = null; - } - } while (currentIterator == null && mapIterator.hasNext()); - return null; - } - - private String[] readNextTag() { - if (tagIterator.hasNext()) { - String tag = tagIterator.next(); - return new String[]{tag, tag, ""}; // id, name, desc - } else { - return null; - } - } - - @Override - public String[] readNext() { - if (tagReaderOnly) { - return readNextTag(); - } else { - return readNextPerSegment(); - } - } - - private Map convertPerSegment(String[] data) { - Map map = new HashMap<>(); - map.put("id", PrimitiveTypeProvider.fromObject(data[0])); - map.put("tagid", PrimitiveTypeProvider.fromObject(data[1])); - map.put("score", PrimitiveTypeProvider.fromObject(1)); - return map; - } - - private Map convertAsTag(String[] data) { - Map map = new HashMap<>(); - map.put(TagReader.TAG_ID_COLUMNNAME, PrimitiveTypeProvider.fromObject(data[0])); - map.put(TagReader.TAG_NAME_COLUMNNAME, PrimitiveTypeProvider.fromObject(data[1])); - map.put(TagReader.TAG_DESCRIPTION_COLUMNNAME, PrimitiveTypeProvider.fromObject(data[1])); // LSC Context: No description available. Use label instead - return map; - } - - @Override - public Map convert(String[] data) { - if (tagReaderOnly) { - return convertAsTag(data); - } else { - return convertPerSegment(data); - } - } -} diff --git a/cineast-runtime/src/main/java/org/vitrivr/cineast/standalone/importer/vbs2019/AudioTranscriptImportHandler.java b/cineast-runtime/src/main/java/org/vitrivr/cineast/standalone/importer/vbs2019/AudioTranscriptImportHandler.java deleted file mode 100644 index ce0e5420e..000000000 --- a/cineast-runtime/src/main/java/org/vitrivr/cineast/standalone/importer/vbs2019/AudioTranscriptImportHandler.java +++ /dev/null @@ -1,36 +0,0 @@ -package org.vitrivr.cineast.standalone.importer.vbs2019; - -import java.io.IOException; -import java.nio.file.Files; -import java.nio.file.Path; -import org.apache.logging.log4j.LogManager; -import org.apache.logging.log4j.Logger; -import org.vitrivr.cineast.core.features.AudioTranscriptionSearch; -import org.vitrivr.cineast.core.util.LogHelper; -import org.vitrivr.cineast.standalone.importer.handlers.DataImportHandler; - -public class AudioTranscriptImportHandler extends DataImportHandler { - - private static final Logger LOGGER = LogManager.getLogger(); - - public AudioTranscriptImportHandler(int threads, int batchsize) { - super(threads, batchsize); - } - - @Override - public void doImport(Path root) { - try { - LOGGER.info("Starting data import for caption files in: {}", root.toString()); - Files.walk(root, 2).filter(p -> p.toString().toLowerCase().endsWith(".json")).forEach(p -> { - try { - this.futures.add(this.service.submit(new DataImportRunner(new AudioTranscriptionImporter(p), AudioTranscriptionSearch.AUDIO_TRANSCRIPTION_TABLE_NAME, "audio file"))); - } catch (IOException e) { - LOGGER.fatal("Failed to open path at {} ", p); - throw new RuntimeException(e); - } - }); - } catch (IOException e) { - LOGGER.error("Could not start data import process with path '{}' due to an IOException: {}. Aborting...", root.toString(), LogHelper.getStackTrace(e)); - } - } -} diff --git a/cineast-runtime/src/main/java/org/vitrivr/cineast/standalone/importer/vbs2019/AudioTranscriptionImporter.java b/cineast-runtime/src/main/java/org/vitrivr/cineast/standalone/importer/vbs2019/AudioTranscriptionImporter.java deleted file mode 100644 index 64e22a7eb..000000000 --- a/cineast-runtime/src/main/java/org/vitrivr/cineast/standalone/importer/vbs2019/AudioTranscriptionImporter.java +++ /dev/null @@ -1,85 +0,0 @@ -package org.vitrivr.cineast.standalone.importer.vbs2019; - -import com.fasterxml.jackson.core.JsonParser; -import com.fasterxml.jackson.core.JsonToken; -import com.fasterxml.jackson.databind.JsonNode; -import com.fasterxml.jackson.databind.ObjectMapper; -import com.fasterxml.jackson.databind.node.ObjectNode; -import java.io.IOException; -import java.nio.file.Path; -import java.util.HashMap; -import java.util.Iterator; -import java.util.Map; -import java.util.Map.Entry; -import java.util.Optional; -import org.apache.logging.log4j.LogManager; -import org.apache.logging.log4j.Logger; -import org.vitrivr.cineast.core.data.Pair; -import org.vitrivr.cineast.core.data.entities.SimpleFulltextFeatureDescriptor; -import org.vitrivr.cineast.core.data.providers.primitive.PrimitiveTypeProvider; -import org.vitrivr.cineast.core.importer.Importer; - -public class AudioTranscriptionImporter implements Importer> { - - private static final Logger LOGGER = LogManager.getLogger(); - private final JsonParser parser; - private final ObjectMapper mapper; - private Iterator> elements; - - public AudioTranscriptionImporter(Path input) throws IOException { - mapper = new ObjectMapper(); - parser = mapper.getFactory().createParser(input.toFile()); - if (parser.nextToken() == JsonToken.START_ARRAY) { - if (parser.nextToken() == JsonToken.START_OBJECT) { - ObjectNode node = mapper.readTree(parser); - elements = node.fields(); - } - if (elements == null) { - throw new IOException("Empty file"); - } - } else { - throw new IOException("Empty file"); - } - } - - private synchronized Optional> nextPair() { - if (!elements.hasNext()) { - do { - try { - if (parser.nextToken() == JsonToken.START_OBJECT) { - ObjectNode nextMovie = mapper.readTree(parser); - if (nextMovie == null) { - LOGGER.info("Audiofile is done"); - return Optional.empty(); - } - elements = nextMovie.fields(); - } else { - LOGGER.info("File done"); - return Optional.empty(); - } - } catch (IOException e) { - throw new RuntimeException(e); - } - } while (!elements.hasNext()); - } - Entry next = elements.next(); - return Optional.of(new Pair<>(next.getKey(), next.getValue().asText())); - } - - /** - * @return Pair mapping a segmentID to a List of Descriptions - */ - @Override - public Pair readNext() { - Optional> node = nextPair(); - return node.orElse(null); - } - - @Override - public Map convert(Pair data) { - final HashMap map = new HashMap<>(2); - map.put(SimpleFulltextFeatureDescriptor.FIELDNAMES[0], PrimitiveTypeProvider.fromObject(data.first)); - map.put(SimpleFulltextFeatureDescriptor.FIELDNAMES[1], PrimitiveTypeProvider.fromObject(data.second)); - return map; - } -} diff --git a/cineast-runtime/src/main/java/org/vitrivr/cineast/standalone/importer/vbs2019/CaptionTextImportHandler.java b/cineast-runtime/src/main/java/org/vitrivr/cineast/standalone/importer/vbs2019/CaptionTextImportHandler.java deleted file mode 100644 index 0048a3975..000000000 --- a/cineast-runtime/src/main/java/org/vitrivr/cineast/standalone/importer/vbs2019/CaptionTextImportHandler.java +++ /dev/null @@ -1,36 +0,0 @@ -package org.vitrivr.cineast.standalone.importer.vbs2019; - -import java.io.IOException; -import java.nio.file.Files; -import java.nio.file.Path; -import org.apache.logging.log4j.LogManager; -import org.apache.logging.log4j.Logger; -import org.vitrivr.cineast.core.features.DescriptionTextSearch; -import org.vitrivr.cineast.core.util.LogHelper; -import org.vitrivr.cineast.standalone.importer.handlers.DataImportHandler; - -public class CaptionTextImportHandler extends DataImportHandler { - - private static final Logger LOGGER = LogManager.getLogger(); - - public CaptionTextImportHandler(int threads, int batchsize) { - super(threads, batchsize); - } - - @Override - public void doImport(Path root) { - try { - LOGGER.info("Starting data import for caption files in: {}", root.toString()); - Files.walk(root, 2).filter(p -> p.toString().toLowerCase().endsWith(".json")).forEach(p -> { - try { - this.futures.add(this.service.submit(new DataImportRunner(new CaptionTextImporter(p), DescriptionTextSearch.DESCRIPTION_TEXT_TABLE_NAME, "caption file"))); - } catch (IOException e) { - LOGGER.fatal("Failed to open path at {} ", p); - throw new RuntimeException(e); - } - }); - } catch (IOException e) { - LOGGER.error("Could not start data import process with path '{}' due to an IOException: {}. Aborting...", root.toString(), LogHelper.getStackTrace(e)); - } - } -} diff --git a/cineast-runtime/src/main/java/org/vitrivr/cineast/standalone/importer/vbs2019/CaptionTextImporter.java b/cineast-runtime/src/main/java/org/vitrivr/cineast/standalone/importer/vbs2019/CaptionTextImporter.java deleted file mode 100644 index cccd2b642..000000000 --- a/cineast-runtime/src/main/java/org/vitrivr/cineast/standalone/importer/vbs2019/CaptionTextImporter.java +++ /dev/null @@ -1,84 +0,0 @@ -package org.vitrivr.cineast.standalone.importer.vbs2019; - -import com.fasterxml.jackson.core.JsonParser; -import com.fasterxml.jackson.core.JsonToken; -import com.fasterxml.jackson.databind.JsonNode; -import com.fasterxml.jackson.databind.ObjectMapper; -import com.fasterxml.jackson.databind.node.ObjectNode; -import java.io.IOException; -import java.nio.file.Path; -import java.util.HashMap; -import java.util.Iterator; -import java.util.Map; -import java.util.Map.Entry; -import java.util.NoSuchElementException; -import java.util.Optional; -import org.apache.commons.lang3.tuple.Triple; -import org.apache.logging.log4j.LogManager; -import org.apache.logging.log4j.Logger; -import org.vitrivr.cineast.core.data.entities.SimpleFulltextFeatureDescriptor; -import org.vitrivr.cineast.core.data.providers.primitive.PrimitiveTypeProvider; -import org.vitrivr.cineast.core.importer.Importer; - -public class CaptionTextImporter implements Importer> { - - private final Iterator> videos; - private static final Logger LOGGER = LogManager.getLogger(); - private Iterator> currentSegments; - private Iterator currentDescriptions; - private String currentSegmentID; - private String currentVideoID; - - public CaptionTextImporter(Path input) throws IOException { - ObjectMapper mapper = new ObjectMapper(); - JsonParser parser = mapper.getFactory().createParser(input.toFile()); - if (parser.nextToken() == JsonToken.START_OBJECT) { - ObjectNode node = mapper.readTree(parser); - videos = node.fields(); - if (videos == null) { - throw new IOException("Empty file"); - } - } else { - throw new IOException("Empty file"); - } - } - - private synchronized Optional> nextPair() { - while (currentSegments == null || !currentSegments.hasNext()) { - Entry next = videos.next(); - currentVideoID = next.getKey(); - currentSegments = next.getValue().fields(); - } - while (currentDescriptions == null || !currentDescriptions.hasNext()) { - Entry next = currentSegments.next(); - currentSegmentID = next.getKey(); - currentDescriptions = next.getValue().iterator(); - } - return Optional.of(Triple.of(currentVideoID, currentSegmentID, currentDescriptions.next().asText())); - } - - /** - * @return Pair mapping a segmentID to a List of Descriptions - */ - @Override - public Triple readNext() { - try { - Optional> node = nextPair(); - if (!node.isPresent()) { - return null; - } - return node.get(); - } catch (NoSuchElementException e) { - return null; - } - } - - @Override - public Map convert(Triple data) { - final HashMap map = new HashMap<>(2); - String id = "v_" + data.getLeft() + "_" + data.getMiddle(); - map.put(SimpleFulltextFeatureDescriptor.FIELDNAMES[0], PrimitiveTypeProvider.fromObject(id)); - map.put(SimpleFulltextFeatureDescriptor.FIELDNAMES[1], PrimitiveTypeProvider.fromObject(data.getRight())); - return map; - } -} diff --git a/cineast-runtime/src/main/java/org/vitrivr/cineast/standalone/importer/vbs2019/GoogleVisionImportHandler.java b/cineast-runtime/src/main/java/org/vitrivr/cineast/standalone/importer/vbs2019/GoogleVisionImportHandler.java deleted file mode 100644 index 8e9d6663d..000000000 --- a/cineast-runtime/src/main/java/org/vitrivr/cineast/standalone/importer/vbs2019/GoogleVisionImportHandler.java +++ /dev/null @@ -1,47 +0,0 @@ -package org.vitrivr.cineast.standalone.importer.vbs2019; - -import java.io.IOException; -import java.nio.file.Files; -import java.nio.file.Path; -import org.apache.logging.log4j.LogManager; -import org.apache.logging.log4j.Logger; -import org.vitrivr.cineast.core.features.TagsFtSearch; -import org.vitrivr.cineast.core.util.LogHelper; -import org.vitrivr.cineast.standalone.importer.handlers.DataImportHandler; -import org.vitrivr.cineast.standalone.importer.vbs2019.gvision.GoogleVisionCategory; - -public class GoogleVisionImportHandler extends DataImportHandler { - - private static final Logger LOGGER = LogManager.getLogger(); - private final GoogleVisionCategory category; - private final boolean importTagsFt; - - public GoogleVisionImportHandler(int threads, int batchsize, GoogleVisionCategory category, - boolean importTagsFt) { - super(threads, batchsize); - this.category = category; - this.importTagsFt = importTagsFt; - } - - @Override - public void doImport(Path root) { - try { - LOGGER.info("Starting import on path {}", root.toAbsolutePath()); - Files.walk(root, 2).filter(p -> p.toString().toLowerCase().endsWith(".json")).forEach(p -> { - try { - this.futures.add(this.service.submit( - new DataImportRunner(new GoogleVisionImporter(p, category, importTagsFt), - importTagsFt ? TagsFtSearch.TAGS_FT_TABLE_NAME : category.tableName, - "gvision-" + category + "-" + importTagsFt + "-file"))); - } catch (IOException e) { - LOGGER.fatal("Failed to open path at {} ", p); - throw new RuntimeException(e); - } - }); - } catch (IOException e) { - LOGGER.error( - "Could not start data import process with path '{}' due to an IOException: {}. Aborting...", - root.toString(), LogHelper.getStackTrace(e)); - } - } -} diff --git a/cineast-runtime/src/main/java/org/vitrivr/cineast/standalone/importer/vbs2019/GoogleVisionImporter.java b/cineast-runtime/src/main/java/org/vitrivr/cineast/standalone/importer/vbs2019/GoogleVisionImporter.java deleted file mode 100644 index 20491a0f7..000000000 --- a/cineast-runtime/src/main/java/org/vitrivr/cineast/standalone/importer/vbs2019/GoogleVisionImporter.java +++ /dev/null @@ -1,248 +0,0 @@ -package org.vitrivr.cineast.standalone.importer.vbs2019; - -import com.fasterxml.jackson.core.JsonParser; -import com.fasterxml.jackson.core.JsonToken; -import com.fasterxml.jackson.databind.JsonNode; -import com.fasterxml.jackson.databind.ObjectMapper; -import com.fasterxml.jackson.databind.node.ObjectNode; -import java.io.IOException; -import java.nio.file.Path; -import java.util.HashMap; -import java.util.Iterator; -import java.util.Map; -import java.util.Map.Entry; -import java.util.NoSuchElementException; -import java.util.Optional; -import org.apache.logging.log4j.LogManager; -import org.apache.logging.log4j.Logger; -import org.vitrivr.cineast.core.data.entities.SimpleFulltextFeatureDescriptor; -import org.vitrivr.cineast.core.data.providers.primitive.PrimitiveTypeProvider; -import org.vitrivr.cineast.core.data.tag.CompleteTag; -import org.vitrivr.cineast.core.data.tag.Tag; -import org.vitrivr.cineast.core.features.TagsFtSearch; -import org.vitrivr.cineast.core.importer.Importer; -import org.vitrivr.cineast.standalone.importer.vbs2019.gvision.GoogleVisionCategory; -import org.vitrivr.cineast.standalone.importer.vbs2019.gvision.GoogleVisionTuple; - -/** - * Import code for the google vision export of the V3C1 Dataset. - *

- * Format is as follows: [ // whole dataset { // video "segmentid": { "web": [ //list of concepts "id": "/m/...", "decription" (not a typo): "Human-readable description, capitalized" "score:" score (can be above 1) ], "ocr": [ "id": "", "decription": "text", "score": 0.0 ], "labels": [ "id": "/m/...", "decription": "human-readable description, non-capitalized" "score": score between 0 and 1 ] }, // list of segments }, // list of videos - */ -public class GoogleVisionImporter implements Importer { - - private JsonParser parser; - private ObjectMapper mapper; - private final String fileName; - private final Path input; - private Iterator> _segments; - private Iterator> _categories; - private static final Logger LOGGER = LogManager.getLogger(); - private String _completeID; - private final GoogleVisionCategory targetCategory; - private Iterator _categoryValues; - private GoogleVisionCategory _category; - private final boolean importTagsFt; - private boolean initialized = false; - - /** - * @param importTagsFt whether tags should be imported into {@link TagsFtSearch} or {@link GoogleVisionCategory#tableName} - * @param targetCategory only tuples of this kind are imported - */ - public GoogleVisionImporter(Path input, GoogleVisionCategory targetCategory, boolean importTagsFt) throws IOException { - this.input = input; - this.fileName = input.getFileName().toString(); - this.importTagsFt = importTagsFt; - this.targetCategory = targetCategory; - } - - /** - * Generate a {@link GoogleVisionTuple} from the current state - */ - private Optional generateTuple() { - JsonNode next = _categoryValues.next(); - try { - return Optional.of(GoogleVisionTuple.of(targetCategory, next, _completeID)); - } catch (UnsupportedOperationException e) { - LOGGER.trace("Cannot generate tuple for category {} and tuple {}", targetCategory, next); - return Optional.empty(); - } - } - - /** - * Search for the next valid {@link GoogleVisionTuple} in the current segment - */ - private Optional searchWithinSegment() { - //First, check if there's still a value left in the current array - if (_category == targetCategory && _categoryValues.hasNext()) { - return generateTuple(); - } - - //if not, check if we can get values for the target category in the given segment - while (_categories != null && _category != targetCategory && _categories.hasNext()) { - Entry nextCategory = _categories.next(); - _category = GoogleVisionCategory.valueOf(nextCategory.getKey().toUpperCase()); - _categoryValues = nextCategory.getValue().iterator(); - } - - //If we succeeded in the previous loop, we should be at the target category and still have a value left to hand out. - if (_category == targetCategory && _categoryValues.hasNext()) { - return generateTuple(); - } - //else we have nothing in this category - return Optional.empty(); - } - - private Optional searchWithinMovie() { - do { - Optional tuple = searchWithinSegment(); - if (tuple.isPresent()) { - return tuple; - } - //we need to move on to the next segment - if (!_segments.hasNext()) { - return Optional.empty(); - } - Entry nextSegment = _segments.next(); - _completeID = nextSegment.getKey(); - _categories = nextSegment.getValue().fields(); - //Initialize category values - Entry nextCategory = _categories.next(); - _category = GoogleVisionCategory.valueOf(nextCategory.getKey().toUpperCase()); - _categoryValues = nextCategory.getValue().iterator(); - } while (_segments.hasNext()); - return Optional.empty(); - } - - /** - * Gets the next {@link GoogleVisionTuple} to Import. - */ - private synchronized Optional nextTuple() { - //Check first if there are tuples left within the current movie / aggregation of segments - Optional tuple = searchWithinMovie(); - if (tuple.isPresent()) { - return tuple; - } -//if the current movie has no tuples left to import, we need to go to the next movie until we find a tuple - do { - //we need to go to the next movie - try { - if (parser.nextToken() == JsonToken.START_OBJECT) { - ObjectNode nextMovie = mapper.readTree(parser); - if (nextMovie == null) { - LOGGER.info("File for category {} is done", targetCategory); - return Optional.empty(); - } - _segments = nextMovie.fields(); - tuple = searchWithinMovie(); - if (tuple.isPresent()) { - return tuple; - } - } else { - LOGGER.info("File {} done", this.fileName); - return Optional.empty(); - } - } catch (IOException e) { - throw new RuntimeException(e); - } - } while (true); - } - - private synchronized void init() throws IOException { - if (initialized) { - LOGGER.warn("Importer for path {} was already initalized", input); - return; - } - initialized = true; - LOGGER.info("Starting Importer for path {}, category {} and importTags {}", input, targetCategory, importTagsFt); - mapper = new ObjectMapper(); - parser = mapper.getFactory().createParser(input.toFile()); - if (parser.nextToken() == JsonToken.START_ARRAY) { - if (parser.nextToken() == JsonToken.START_OBJECT) { - ObjectNode node = mapper.readTree(parser); - _segments = node.fields(); - } - if (_segments == null) { - throw new IOException("Empty file"); - } - } else { - throw new IOException("Empty file"); - } - } - - /** - * @return Pair mapping a segmentID to a List of Descriptions - */ - @Override - public GoogleVisionTuple readNext() { - try { - if (!initialized) { - init(); - } - Optional node = nextTuple(); - if (!node.isPresent()) { - return null; - } - return node.get(); - } catch (NoSuchElementException | IOException e) { - e.printStackTrace(); - return null; - } - } - - /** - * Converts the given {@link GoogleVisionTuple} to a representation appropriate to the given feature. - * - * @param data the tuple to be converted to a tuple in the feature table - * @return a map where the key corresponds to the column-name and the value to the value to be inserted in that column for the given tuple - */ - @Override - public Map convert(GoogleVisionTuple data) { - final HashMap map = new HashMap<>(2); - Optional tag = Optional.empty(); - PrimitiveTypeProvider id = PrimitiveTypeProvider.fromObject(data.completeID); - switch (data.category) { - case PARTIALLY_MATCHING_IMAGES: - throw new UnsupportedOperationException(); - case WEB: - if (importTagsFt) { - map.put(SimpleFulltextFeatureDescriptor.FIELDNAMES[0], id); - map.put(SimpleFulltextFeatureDescriptor.FIELDNAMES[1], PrimitiveTypeProvider.fromObject(data.web.get().description)); - } else { - map.put("id", id); - map.put("tagid", PrimitiveTypeProvider.fromObject(data.web.get().labelId)); - map.put("score", PrimitiveTypeProvider.fromObject(Math.min(1, data.web.get().score))); - try { - tag = Optional.of(new CompleteTag(data.web.get().labelId, data.web.get().description, data.web.get().description)); - } catch (IllegalArgumentException e) { - LOGGER.trace("Error while initalizing tag {}", e.getMessage()); - } - } - break; - case PAGES_MATCHING_IMAGES: - throw new UnsupportedOperationException(); - case FULLY_MATCHING_IMAGES: - throw new UnsupportedOperationException(); - case LABELS: - if (importTagsFt) { - map.put(SimpleFulltextFeatureDescriptor.FIELDNAMES[0], id); - map.put(SimpleFulltextFeatureDescriptor.FIELDNAMES[1], PrimitiveTypeProvider.fromObject(data.label.get().description)); - } else { - map.put("id", id); - map.put("tagid", PrimitiveTypeProvider.fromObject(data.label.get().labelId)); - map.put("score", PrimitiveTypeProvider.fromObject(Math.min(1, data.label.get().score))); - tag = Optional.of(new CompleteTag(data.label.get().labelId, data.label.get().description, data.label.get().description)); - } - break; - case OCR: - map.put(SimpleFulltextFeatureDescriptor.FIELDNAMES[0], id); - map.put(SimpleFulltextFeatureDescriptor.FIELDNAMES[1], PrimitiveTypeProvider.fromObject(data.ocr.get().description)); - // Score is ignored because it's never used in search and 0 anyways - //map.put("score", PrimitiveTypeProvider.fromObject(data.ocr.get().score)); - break; - default: - throw new UnsupportedOperationException(); - } - return map; - } -} diff --git a/cineast-runtime/src/main/java/org/vitrivr/cineast/standalone/importer/vbs2019/MLTFeatureImporter.java b/cineast-runtime/src/main/java/org/vitrivr/cineast/standalone/importer/vbs2019/MLTFeatureImporter.java deleted file mode 100644 index 7f62a4cef..000000000 --- a/cineast-runtime/src/main/java/org/vitrivr/cineast/standalone/importer/vbs2019/MLTFeatureImporter.java +++ /dev/null @@ -1,72 +0,0 @@ -package org.vitrivr.cineast.standalone.importer.vbs2019; - -import java.io.BufferedReader; -import java.io.FileReader; -import java.io.IOException; -import java.nio.file.Path; -import java.util.HashMap; -import java.util.Map; -import java.util.NoSuchElementException; -import java.util.Optional; -import org.apache.commons.lang3.tuple.ImmutablePair; -import org.apache.commons.lang3.tuple.Pair; -import org.apache.logging.log4j.LogManager; -import org.apache.logging.log4j.Logger; -import org.vitrivr.cineast.core.data.providers.primitive.PrimitiveTypeProvider; -import org.vitrivr.cineast.core.importer.Importer; - -/** - * Purpose-built for output generated by https://github.com/vitrivr/mobilenet-feature-extraction - */ -public class MLTFeatureImporter implements Importer> { - - private static final Logger LOGGER = LogManager.getLogger(); - private final BufferedReader reader; - - public MLTFeatureImporter(Path input) throws IOException { - reader = new BufferedReader(new FileReader(input.toFile())); - } - - private synchronized Optional> nextPair() { - try { - String line = reader.readLine(); - if (line == null) { - LOGGER.info("Reached EoF"); - return Optional.empty(); - } - String[] split = line.split(","); - String id = split[0]; - float[] feature = new float[512]; - for (int i = 1; i < split.length; i++) { - feature[i - 1] = Float.parseFloat(split[i]); - } - return Optional.of(ImmutablePair.of(id, feature)); - } catch (IOException e) { - LOGGER.error("IOException while reading"); - LOGGER.error(e); - return Optional.empty(); - } - } - - /** - * @return Pair mapping a segmentID to a List of Descriptions - */ - @Override - public Pair readNext() { - try { - Optional> node = nextPair(); - return node.orElse(null); - } catch (NoSuchElementException e) { - return null; - } - } - - @Override - public Map convert(Pair data) { - final HashMap map = new HashMap<>(2); - String id = data.getLeft(); - map.put("id", PrimitiveTypeProvider.fromObject(id)); - map.put("feature", PrimitiveTypeProvider.fromObject(data.getRight())); - return map; - } -} diff --git a/cineast-runtime/src/main/java/org/vitrivr/cineast/standalone/importer/vbs2019/ObjectMetadataImportHandler.java b/cineast-runtime/src/main/java/org/vitrivr/cineast/standalone/importer/vbs2019/ObjectMetadataImportHandler.java deleted file mode 100644 index e51f40023..000000000 --- a/cineast-runtime/src/main/java/org/vitrivr/cineast/standalone/importer/vbs2019/ObjectMetadataImportHandler.java +++ /dev/null @@ -1,36 +0,0 @@ -package org.vitrivr.cineast.standalone.importer.vbs2019; - -import java.io.IOException; -import java.nio.file.Files; -import java.nio.file.Path; -import org.apache.logging.log4j.LogManager; -import org.apache.logging.log4j.Logger; -import org.vitrivr.cineast.core.data.entities.MediaObjectMetadataDescriptor; -import org.vitrivr.cineast.core.util.LogHelper; -import org.vitrivr.cineast.standalone.importer.handlers.DataImportHandler; - -public class ObjectMetadataImportHandler extends DataImportHandler { - - private static final Logger LOGGER = LogManager.getLogger(); - - public ObjectMetadataImportHandler(int threads, int batchsize) { - super(threads, batchsize); - } - - @Override - public void doImport(Path root) { - try { - LOGGER.info("Starting data import for caption files in: {}", root.toString()); - Files.walk(root, 2).filter(p -> p.toString().toLowerCase().endsWith(".json")).forEach(p -> { - try { - this.futures.add(this.service.submit(new DataImportRunner(new ObjectMetadataImporter(p), MediaObjectMetadataDescriptor.ENTITY, "metadata"))); - } catch (IOException e) { - LOGGER.fatal("Failed to open path at {} ", p); - throw new RuntimeException(e); - } - }); - } catch (IOException e) { - LOGGER.error("Could not start data import process with path '{}' due to an IOException: {}. Aborting...", root.toString(), LogHelper.getStackTrace(e)); - } - } -} diff --git a/cineast-runtime/src/main/java/org/vitrivr/cineast/standalone/importer/vbs2019/ObjectMetadataImporter.java b/cineast-runtime/src/main/java/org/vitrivr/cineast/standalone/importer/vbs2019/ObjectMetadataImporter.java deleted file mode 100644 index 80f6c2f1e..000000000 --- a/cineast-runtime/src/main/java/org/vitrivr/cineast/standalone/importer/vbs2019/ObjectMetadataImporter.java +++ /dev/null @@ -1,130 +0,0 @@ -package org.vitrivr.cineast.standalone.importer.vbs2019; - -import com.fasterxml.jackson.core.JsonParser; -import com.fasterxml.jackson.core.JsonToken; -import com.fasterxml.jackson.databind.JsonNode; -import com.fasterxml.jackson.databind.ObjectMapper; -import com.fasterxml.jackson.databind.node.ObjectNode; -import java.io.IOException; -import java.nio.file.Path; -import java.util.HashMap; -import java.util.Iterator; -import java.util.Map; -import java.util.Map.Entry; -import java.util.NoSuchElementException; -import java.util.Optional; -import org.apache.logging.log4j.LogManager; -import org.apache.logging.log4j.Logger; -import org.vitrivr.cineast.core.data.entities.MediaObjectMetadataDescriptor; -import org.vitrivr.cineast.core.data.providers.primitive.DoubleTypeProvider; -import org.vitrivr.cineast.core.data.providers.primitive.LongTypeProvider; -import org.vitrivr.cineast.core.data.providers.primitive.PrimitiveTypeProvider; -import org.vitrivr.cineast.core.data.providers.primitive.StringTypeProvider; -import org.vitrivr.cineast.core.importer.Importer; - -public class ObjectMetadataImporter implements Importer> { - - private static final Logger LOGGER = LogManager.getLogger(); - private final ObjectMapper mapper; - private final JsonParser parser; - private String _id; - private Iterator> _meta; - private Iterator _metaArray; - private String _key; - - public ObjectMetadataImporter(Path input) throws IOException { - mapper = new ObjectMapper(); - parser = mapper.getFactory().createParser(input.toFile()); - if (parser.nextToken() != JsonToken.START_ARRAY) { - throw new IOException("Invalid format"); - } - if (parser.nextToken() != JsonToken.START_OBJECT) { - throw new IOException("Invalid format"); - } - nextObjectMetadata(); - } - - private Optional>> nextObjectMetadata() throws IOException { - if (parser.nextToken() != JsonToken.START_OBJECT) { - LOGGER.info("File done"); - return Optional.empty(); - } - ObjectNode node = mapper.readTree(parser); - if (node == null) { - LOGGER.info("File is done"); - return Optional.empty(); - } - _meta = node.fields(); - if (_meta == null) { - throw new IOException("Empty file"); - } - _id = "v_" + node.get("v3cId").textValue(); - return Optional.of(_meta); - } - - private synchronized Optional> nextPair() throws IOException { - while (_meta == null || !_meta.hasNext()) { - //isempty() only after java 11 - if (!nextObjectMetadata().isPresent()) { - return Optional.empty(); - } - } - if (_metaArray != null && _metaArray.hasNext()) { - //return active meta array element - } - Entry next = _meta.next(); - JsonNode jsonVal = next.getValue(); - String key = next.getKey(); - PrimitiveTypeProvider primitiveVal = null; - if (next.getValue().isArray()) { - _metaArray = next.getValue().iterator(); - _key = next.getKey(); - if (_metaArray.hasNext()) { - jsonVal = _metaArray.next(); - } else { - return nextPair(); - } - } - if (jsonVal.isFloatingPointNumber()) { - primitiveVal = new DoubleTypeProvider(jsonVal.asDouble()); - } - if (jsonVal.isNumber()) { - primitiveVal = new LongTypeProvider(jsonVal.asLong()); - } - if (jsonVal.isTextual()) { - primitiveVal = new StringTypeProvider(jsonVal.asText()); - } - if (primitiveVal == null) { - LOGGER.warn("Unknown type {}", jsonVal.getNodeType()); - } - - final HashMap map = new HashMap<>(2); - map.put(MediaObjectMetadataDescriptor.FIELDNAMES[0], PrimitiveTypeProvider.fromObject(_id)); - map.put(MediaObjectMetadataDescriptor.FIELDNAMES[1], PrimitiveTypeProvider.fromObject("vimeo")); - map.put(MediaObjectMetadataDescriptor.FIELDNAMES[2], PrimitiveTypeProvider.fromObject(key)); - map.put(MediaObjectMetadataDescriptor.FIELDNAMES[3], primitiveVal); - return Optional.of(map); - } - - /** - * @return Pair mapping a segmentID to a List of Descriptions - */ - @Override - public Map readNext() { - try { - Optional> node = nextPair(); - //isEmpty() only since java 11 - if (!node.isPresent()) { - return null; - } - return node.get(); - } catch (NoSuchElementException | IOException e) { - return null; - } - } - - @Override - public Map convert(Map data) { - return data; - } -} diff --git a/cineast-runtime/src/main/java/org/vitrivr/cineast/standalone/importer/vbs2019/TagImportHandler.java b/cineast-runtime/src/main/java/org/vitrivr/cineast/standalone/importer/vbs2019/TagImportHandler.java deleted file mode 100644 index 0d1a930c4..000000000 --- a/cineast-runtime/src/main/java/org/vitrivr/cineast/standalone/importer/vbs2019/TagImportHandler.java +++ /dev/null @@ -1,32 +0,0 @@ -package org.vitrivr.cineast.standalone.importer.vbs2019; - -import java.io.IOException; -import java.nio.file.Path; -import org.apache.logging.log4j.LogManager; -import org.apache.logging.log4j.Logger; -import org.vitrivr.cineast.core.db.dao.reader.TagReader; -import org.vitrivr.cineast.core.features.SegmentTags; -import org.vitrivr.cineast.core.util.LogHelper; -import org.vitrivr.cineast.standalone.importer.handlers.DataImportHandler; - -public class TagImportHandler extends DataImportHandler { - - private static final Logger LOGGER = LogManager.getLogger(); - - public TagImportHandler(int threads, int batchsize) { - super(threads, batchsize); - } - - @Override - public void doImport(Path root) { - try { - LOGGER.info("Starting data import for tag files in: {}", root.toString()); - - this.futures.add(this.service.submit(new DataImportRunner(new TagImporter(root.resolve("tagDetails.tsv"), TagReader.TAG_ID_COLUMNNAME, TagReader.TAG_NAME_COLUMNNAME, null, TagReader.TAG_DESCRIPTION_COLUMNNAME), TagReader.TAG_ENTITY_NAME, "tags"))); - this.futures.add(this.service.submit(new DataImportRunner(new TagImporter(root.resolve("uniqueTagInstances.tsv"), "id", "tagid", "score"), SegmentTags.SEGMENT_TAGS_TABLE_NAME, "unique mappings from segments and tags"))); - LOGGER.info("Completed data import with Tag Import files in: {}", root.toString()); - } catch (IOException e) { - LOGGER.error("Could not start data import process with path '{}' due to an IOException: {}. Aborting...", root.toString(), LogHelper.getStackTrace(e)); - } - } -} diff --git a/cineast-runtime/src/main/java/org/vitrivr/cineast/standalone/importer/vbs2019/TagImporter.java b/cineast-runtime/src/main/java/org/vitrivr/cineast/standalone/importer/vbs2019/TagImporter.java deleted file mode 100644 index dd7bccbf7..000000000 --- a/cineast-runtime/src/main/java/org/vitrivr/cineast/standalone/importer/vbs2019/TagImporter.java +++ /dev/null @@ -1,100 +0,0 @@ -package org.vitrivr.cineast.standalone.importer.vbs2019; - -import java.io.IOException; -import java.nio.charset.Charset; -import java.nio.file.Path; -import java.util.Arrays; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.NoSuchElementException; -import java.util.Optional; -import org.apache.commons.io.FileUtils; -import org.apache.logging.log4j.LogManager; -import org.apache.logging.log4j.Logger; -import org.vitrivr.cineast.core.data.providers.primitive.PrimitiveTypeProvider; -import org.vitrivr.cineast.core.db.dao.reader.TagReader; -import org.vitrivr.cineast.core.importer.Importer; - -public class TagImporter implements Importer { - - private static final Logger LOGGER = LogManager.getLogger(); - private final String[] columnNames; - private final List lines; - private int index; - - public TagImporter(Path input, String... columnNames) throws IOException { - this.columnNames = columnNames; - lines = FileUtils.readLines(input.toFile(), Charset.defaultCharset()); - index = 0; - } - - private synchronized Optional nextPair() { - if (index < (lines.size() - 1)) { - String line = lines.get(index); - String[] split = line.split("\t"); - index++; - return Optional.of(split); - } - return Optional.empty(); - } - - /** - * @return Pair mapping a segmentID to a List of Descriptions - */ - @Override - public String[] readNext() { - try { - return nextPair().orElse(null); - } catch (NoSuchElementException e) { - return null; - } - } - - @Override - public Map convert(String[] data) { - final HashMap map = new HashMap<>(data.length); - /** - * Iterate over tsv array - */ - for (int i = 0; i < data.length; i++) { - /* - * Skip column if no col-name is provided - */ - if (columnNames[i] == null) { - continue; - } - if (columnNames[i].equals(TagReader.TAG_NAME_COLUMNNAME) || columnNames[i].equals(TagReader.TAG_DESCRIPTION_COLUMNNAME)) { - /** sanity-check if there's an @ */ - if (data[i].contains("@")) { - map.put(columnNames[i], PrimitiveTypeProvider.fromObject(data[i].substring(0, data[i].indexOf("@")))); - continue; - } - } - if (columnNames[i].equals("id")) { - if (!data[i].startsWith("v_") && !data[i].startsWith("Q")) { - map.put(columnNames[i], PrimitiveTypeProvider.fromObject("v_" + data[i])); - continue; - } - //id can also be Q... - } - map.put(columnNames[i], PrimitiveTypeProvider.fromObject(data[i])); - } - /** If there's no description yet, fill it */ - if (Arrays.asList(columnNames).contains(TagReader.TAG_DESCRIPTION_COLUMNNAME) && !map.containsKey(TagReader.TAG_DESCRIPTION_COLUMNNAME)) { - map.put(TagReader.TAG_DESCRIPTION_COLUMNNAME, map.getOrDefault(TagReader.TAG_NAME_COLUMNNAME, PrimitiveTypeProvider.fromObject("no description"))); - } - // since there is no score provided... - if (data.length < columnNames.length) { - for (int i = data.length; i < columnNames.length; i++) { - if (columnNames[i] == null) { - continue; - } - if (columnNames[i].equals("score")) { - map.put(columnNames[i], PrimitiveTypeProvider.fromObject(1)); - } - } - } - return map; - } -} diff --git a/cineast-runtime/src/main/java/org/vitrivr/cineast/standalone/importer/vbs2019/gvision/GoogleVisionCategory.java b/cineast-runtime/src/main/java/org/vitrivr/cineast/standalone/importer/vbs2019/gvision/GoogleVisionCategory.java deleted file mode 100644 index cf74e2f09..000000000 --- a/cineast-runtime/src/main/java/org/vitrivr/cineast/standalone/importer/vbs2019/gvision/GoogleVisionCategory.java +++ /dev/null @@ -1,12 +0,0 @@ -package org.vitrivr.cineast.standalone.importer.vbs2019.gvision; - -public enum GoogleVisionCategory { - - PARTIALLY_MATCHING_IMAGES("empty"), WEB("features_segmenttags"), PAGES_MATCHING_IMAGES("empty"), FULLY_MATCHING_IMAGES("empty"), LABELS("features_segmenttags"), OCR("features_ocr"); - - public final String tableName; - - GoogleVisionCategory(String tableName) { - this.tableName = tableName; - } -} diff --git a/cineast-runtime/src/main/java/org/vitrivr/cineast/standalone/importer/vbs2019/gvision/GoogleVisionLabelTuple.java b/cineast-runtime/src/main/java/org/vitrivr/cineast/standalone/importer/vbs2019/gvision/GoogleVisionLabelTuple.java deleted file mode 100644 index 2367371f1..000000000 --- a/cineast-runtime/src/main/java/org/vitrivr/cineast/standalone/importer/vbs2019/gvision/GoogleVisionLabelTuple.java +++ /dev/null @@ -1,20 +0,0 @@ -package org.vitrivr.cineast.standalone.importer.vbs2019.gvision; - -import com.fasterxml.jackson.databind.JsonNode; - -public class GoogleVisionLabelTuple { - - public final String labelId; - public final String description; - public final float score; - - public GoogleVisionLabelTuple(JsonNode node) { - this(node.get("id").asText(), node.get("decription").asText(), (float) node.get("score").asDouble()); - } - - public GoogleVisionLabelTuple(String labelId, String description, float score) { - this.labelId = labelId; - this.description = description; - this.score = score; - } -} diff --git a/cineast-runtime/src/main/java/org/vitrivr/cineast/standalone/importer/vbs2019/gvision/GoogleVisionOCRTuple.java b/cineast-runtime/src/main/java/org/vitrivr/cineast/standalone/importer/vbs2019/gvision/GoogleVisionOCRTuple.java deleted file mode 100644 index 22ecd1d15..000000000 --- a/cineast-runtime/src/main/java/org/vitrivr/cineast/standalone/importer/vbs2019/gvision/GoogleVisionOCRTuple.java +++ /dev/null @@ -1,22 +0,0 @@ -package org.vitrivr.cineast.standalone.importer.vbs2019.gvision; - -import com.fasterxml.jackson.databind.JsonNode; - -public class GoogleVisionOCRTuple { - - public final String ocrId; - public final String description; - public final float score; - - public GoogleVisionOCRTuple(String ocrId, String description, float score) { - this.ocrId = ocrId; - this.description = description; - this.score = score; - } - - public GoogleVisionOCRTuple(JsonNode node) { - this(node.get("id").asText(), node.get("decription").asText(), (float) node.get("score").asDouble()); - } -} - - diff --git a/cineast-runtime/src/main/java/org/vitrivr/cineast/standalone/importer/vbs2019/gvision/GoogleVisionTuple.java b/cineast-runtime/src/main/java/org/vitrivr/cineast/standalone/importer/vbs2019/gvision/GoogleVisionTuple.java deleted file mode 100644 index 61e9c4b49..000000000 --- a/cineast-runtime/src/main/java/org/vitrivr/cineast/standalone/importer/vbs2019/gvision/GoogleVisionTuple.java +++ /dev/null @@ -1,49 +0,0 @@ -package org.vitrivr.cineast.standalone.importer.vbs2019.gvision; - -import com.fasterxml.jackson.databind.JsonNode; -import com.google.common.base.Optional; -import org.apache.commons.lang3.builder.ToStringBuilder; - -public class GoogleVisionTuple { - - public final GoogleVisionCategory category; - public final Optional web; - public final Optional label; - public final Optional ocr; - public final String completeID; - - public GoogleVisionTuple(GoogleVisionCategory category, - Optional web, - Optional label, - Optional ocr, String completeID) { - this.category = category; - this.web = web; - this.label = label; - this.ocr = ocr; - this.completeID = completeID; - } - - public static GoogleVisionTuple of(GoogleVisionCategory category, JsonNode jsonNode, String completeID) { - switch (category) { - case PARTIALLY_MATCHING_IMAGES: - throw new UnsupportedOperationException(); - case WEB: - return new GoogleVisionTuple(category, Optional.of(new GoogleVisionWebTuple(jsonNode)), Optional.absent(), Optional.absent(), completeID); - case PAGES_MATCHING_IMAGES: - throw new UnsupportedOperationException(); - case FULLY_MATCHING_IMAGES: - throw new UnsupportedOperationException(); - case LABELS: - return new GoogleVisionTuple(category, Optional.absent(), Optional.of(new GoogleVisionLabelTuple(jsonNode)), Optional.absent(), completeID); - case OCR: - return new GoogleVisionTuple(category, Optional.absent(), Optional.absent(), Optional.of(new GoogleVisionOCRTuple(jsonNode)), completeID); - default: - throw new UnsupportedOperationException(); - } - } - - @Override - public String toString() { - return ToStringBuilder.reflectionToString(this); - } -} diff --git a/cineast-runtime/src/main/java/org/vitrivr/cineast/standalone/importer/vbs2019/gvision/GoogleVisionWebTuple.java b/cineast-runtime/src/main/java/org/vitrivr/cineast/standalone/importer/vbs2019/gvision/GoogleVisionWebTuple.java deleted file mode 100644 index 3b99eb012..000000000 --- a/cineast-runtime/src/main/java/org/vitrivr/cineast/standalone/importer/vbs2019/gvision/GoogleVisionWebTuple.java +++ /dev/null @@ -1,20 +0,0 @@ -package org.vitrivr.cineast.standalone.importer.vbs2019.gvision; - -import com.fasterxml.jackson.databind.JsonNode; - -public class GoogleVisionWebTuple { - - public final String labelId; - public final String description; - public final float score; - - public GoogleVisionWebTuple(String labelId, String description, float score) { - this.labelId = labelId; - this.description = description; - this.score = score; - } - - public GoogleVisionWebTuple(JsonNode node) { - this(node.get("id").asText(), node.get("decription").asText(), (float) node.get("score").asDouble()); - } -} diff --git a/cineast-runtime/src/main/java/org/vitrivr/cineast/standalone/importer/vbs2019/v3c1analysis/ColorlabelImportHandler.java b/cineast-runtime/src/main/java/org/vitrivr/cineast/standalone/importer/vbs2019/v3c1analysis/ColorlabelImportHandler.java deleted file mode 100644 index 48e8238f7..000000000 --- a/cineast-runtime/src/main/java/org/vitrivr/cineast/standalone/importer/vbs2019/v3c1analysis/ColorlabelImportHandler.java +++ /dev/null @@ -1,36 +0,0 @@ -package org.vitrivr.cineast.standalone.importer.vbs2019.v3c1analysis; - -import java.io.IOException; -import java.nio.file.Files; -import java.nio.file.Path; -import org.apache.logging.log4j.LogManager; -import org.apache.logging.log4j.Logger; -import org.vitrivr.cineast.core.data.entities.MediaSegmentMetadataDescriptor; -import org.vitrivr.cineast.core.util.LogHelper; -import org.vitrivr.cineast.standalone.importer.handlers.DataImportHandler; - -public class ColorlabelImportHandler extends DataImportHandler { - - private static final Logger LOGGER = LogManager.getLogger(); - - public ColorlabelImportHandler(int threads, int batchsize) { - super(threads, batchsize); - } - - @Override - public void doImport(Path root) { - try { - LOGGER.info("Starting data import for colorlabel files in: {} with {} threads", root.toString(), this.numberOfThreads); - Files.walk(root.resolve("colorlabels/"), 2).filter(p -> p.toString().toLowerCase().endsWith(".txt")).forEach(p -> { - try { - String color = p.getFileName().toString().split("\\.")[0]; - this.futures.add(this.service.submit(new DataImportRunner(new ColorlabelImporter(p, color), MediaSegmentMetadataDescriptor.ENTITY, "import colorlabels " + color))); - } catch (IOException e) { - throw new RuntimeException(e); - } - }); - } catch (IOException e) { - LOGGER.error("Could not start data import process with path '{}' due to an IOException: {}. Aborting...", root.toString(), LogHelper.getStackTrace(e)); - } - } -} diff --git a/cineast-runtime/src/main/java/org/vitrivr/cineast/standalone/importer/vbs2019/v3c1analysis/ColorlabelImporter.java b/cineast-runtime/src/main/java/org/vitrivr/cineast/standalone/importer/vbs2019/v3c1analysis/ColorlabelImporter.java deleted file mode 100644 index face0bd88..000000000 --- a/cineast-runtime/src/main/java/org/vitrivr/cineast/standalone/importer/vbs2019/v3c1analysis/ColorlabelImporter.java +++ /dev/null @@ -1,61 +0,0 @@ -package org.vitrivr.cineast.standalone.importer.vbs2019.v3c1analysis; - -import java.io.IOException; -import java.nio.file.Path; -import java.util.HashMap; -import java.util.Map; -import java.util.NoSuchElementException; -import java.util.Optional; -import org.apache.commons.io.FileUtils; -import org.apache.commons.io.LineIterator; -import org.vitrivr.cineast.core.data.entities.MediaSegmentMetadataDescriptor; -import org.vitrivr.cineast.core.data.providers.primitive.PrimitiveTypeProvider; -import org.vitrivr.cineast.core.importer.Importer; - -/** - * Imports the colorlabels as given by the https://github.com/klschoef/V3C1Analysis repo. File is expected to be in format: - *

- * every line contains the segmentid formatted xxxxx_yyyy, where before the _ is 0-padded to length 5 the movie id and behind the _ the non-0 padded segmentID - */ -public class ColorlabelImporter implements Importer> { - - private final String label; - private LineIterator lineIterator = null; - - - public ColorlabelImporter(Path input, String label) throws IOException { - this.label = label; - lineIterator = FileUtils.lineIterator(input.toFile()); - if (!lineIterator.hasNext()) { - throw new IOException("Empty file"); - } - } - - private synchronized Optional> nextPair() { - if (!lineIterator.hasNext()) { - return Optional.empty(); - } - String id = lineIterator.next(); - Map _return = new HashMap<>(); - _return.put(MediaSegmentMetadataDescriptor.FIELDNAMES[0], PrimitiveTypeProvider.fromObject("v_" + id)); - _return.put(MediaSegmentMetadataDescriptor.FIELDNAMES[1], PrimitiveTypeProvider.fromObject("v3c1")); - _return.put(MediaSegmentMetadataDescriptor.FIELDNAMES[2], PrimitiveTypeProvider.fromObject("colorlabels")); - _return.put(MediaSegmentMetadataDescriptor.FIELDNAMES[3], PrimitiveTypeProvider.fromObject(this.label)); - return Optional.of(_return); - } - - @Override - public Map readNext() { - try { - Optional> node = nextPair(); - return node.orElse(null); - } catch (NoSuchElementException e) { - return null; - } - } - - @Override - public Map convert(Map data) { - return data; - } -} diff --git a/cineast-runtime/src/main/java/org/vitrivr/cineast/standalone/importer/vbs2019/v3c1analysis/SequenceIdLookupService.java b/cineast-runtime/src/main/java/org/vitrivr/cineast/standalone/importer/vbs2019/v3c1analysis/SequenceIdLookupService.java deleted file mode 100644 index 663f161b9..000000000 --- a/cineast-runtime/src/main/java/org/vitrivr/cineast/standalone/importer/vbs2019/v3c1analysis/SequenceIdLookupService.java +++ /dev/null @@ -1,45 +0,0 @@ -package org.vitrivr.cineast.standalone.importer.vbs2019.v3c1analysis; - -import java.io.IOException; -import java.nio.charset.Charset; -import java.nio.file.Path; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import org.apache.commons.io.FileUtils; - -/** - * Reads the msb-allshots.txt file from the V3C1 Metadata Repo and provides an easy-to-use lookup which takes the framenumber and returns the 0-based sequence number. We assume that sequences are sequentially ordered by file - */ -public class SequenceIdLookupService { - - private Map> lookup = new HashMap<>(); - - public SequenceIdLookupService(Path input) throws IOException { - List lines = FileUtils.readLines(input.toFile(), Charset.defaultCharset()); - //skip header - lines.forEach(line -> { - if (line.startsWith("video")) { - return; - } - String[] split = line.split(";"); - String videoID = split[0].split("\\.")[0]; - lookup.putIfAbsent(videoID, new ArrayList<>()); - int start = Integer.parseInt(split[1]); - lookup.get(videoID).add(start); - }); - //order all lists - lookup.values().forEach(list -> list.sort(Integer::compare)); - } - - public int getSequenceNumber(String movieID, int frame) { - List list = lookup.get(movieID); - for (int i = 0; i < list.size(); i++) { - if (list.get(i) > frame) { - return i - 1; - } - } - return list.size() - 1; - } -} diff --git a/cineast-runtime/src/main/java/org/vitrivr/cineast/standalone/listener/RetrievalResultCSVExporter.java b/cineast-runtime/src/main/java/org/vitrivr/cineast/standalone/listener/RetrievalResultCSVExporter.java deleted file mode 100644 index ff8bd121c..000000000 --- a/cineast-runtime/src/main/java/org/vitrivr/cineast/standalone/listener/RetrievalResultCSVExporter.java +++ /dev/null @@ -1,90 +0,0 @@ -package org.vitrivr.cineast.standalone.listener; - -import java.io.File; -import java.io.FileNotFoundException; -import java.io.PrintWriter; -import java.util.ArrayList; -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.Set; -import org.apache.logging.log4j.LogManager; -import org.apache.logging.log4j.Logger; -import org.vitrivr.cineast.core.config.DatabaseConfig; -import org.vitrivr.cineast.core.config.ReadableQueryConfig; -import org.vitrivr.cineast.core.data.entities.MediaObjectDescriptor; -import org.vitrivr.cineast.core.data.entities.MediaSegmentDescriptor; -import org.vitrivr.cineast.core.data.score.ScoreElement; -import org.vitrivr.cineast.core.db.dao.reader.MediaObjectReader; -import org.vitrivr.cineast.core.db.dao.reader.MediaSegmentReader; -import org.vitrivr.cineast.core.util.LogHelper; -import org.vitrivr.cineast.standalone.runtime.RetrievalTask; - -public class RetrievalResultCSVExporter implements RetrievalResultListener { - - private static File baseFolder = new File("retrieval_results"); // TODO make configurable - private static final Logger LOGGER = LogManager.getLogger(); - - private final MediaSegmentReader mediaSegmentReader; - private final MediaObjectReader mediaObjectReader; - - public RetrievalResultCSVExporter(DatabaseConfig databaseConfig) { - mediaSegmentReader = new MediaSegmentReader(databaseConfig.getSelectorSupplier().get()); - mediaObjectReader = new MediaObjectReader(databaseConfig.getSelectorSupplier().get()); - } - - @Override - public void notify(List 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 ids = new ArrayList<>(resultList.size()); - for (ScoreElement e : resultList) { - ids.add(e.getId()); - } - - Map segments = mediaSegmentReader.lookUpSegments(ids); - Set objectIds = new HashSet<>(); - - for (MediaSegmentDescriptor sd : segments.values()) { - objectIds.add(sd.getObjectId()); - } - - Map 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)); - } - - } -} diff --git a/cineast-runtime/src/main/java/org/vitrivr/cineast/standalone/listener/RetrievalResultListener.java b/cineast-runtime/src/main/java/org/vitrivr/cineast/standalone/listener/RetrievalResultListener.java deleted file mode 100644 index 8a91c083b..000000000 --- a/cineast-runtime/src/main/java/org/vitrivr/cineast/standalone/listener/RetrievalResultListener.java +++ /dev/null @@ -1,21 +0,0 @@ -package org.vitrivr.cineast.standalone.listener; - -import java.util.List; -import org.vitrivr.cineast.core.data.score.ScoreElement; -import org.vitrivr.cineast.core.features.retriever.Retriever; -import org.vitrivr.cineast.standalone.runtime.RetrievalTask; - -/** - * Listener which can be attached to retrieval logic to get notified on raw results of a {@link Retriever} - */ -public interface RetrievalResultListener { - - /** - * gets called whenever a {@link Retriever} returns - * - * @param resultList the retrieved results - * @param task the {@link RetrievalTask} containing retriever and query - */ - public void notify(List resultList, RetrievalTask task); - -} diff --git a/cineast-runtime/src/main/java/org/vitrivr/cineast/standalone/runtime/ContinuousQueryDispatcher.java b/cineast-runtime/src/main/java/org/vitrivr/cineast/standalone/runtime/ContinuousQueryDispatcher.java index 8caae348f..2e99b8c6f 100644 --- a/cineast-runtime/src/main/java/org/vitrivr/cineast/standalone/runtime/ContinuousQueryDispatcher.java +++ b/cineast-runtime/src/main/java/org/vitrivr/cineast/standalone/runtime/ContinuousQueryDispatcher.java @@ -31,7 +31,6 @@ import org.vitrivr.cineast.core.util.math.MathHelper; import org.vitrivr.cineast.core.util.ScoreFusion; import org.vitrivr.cineast.standalone.config.Config; -import org.vitrivr.cineast.standalone.listener.RetrievalResultListener; public class ContinuousQueryDispatcher { @@ -44,8 +43,6 @@ public class ContinuousQueryDispatcher { private static final int MAX_RESULTS = Config.sharedConfig().getRetriever().getMaxResults(); private static final int KEEP_ALIVE_TIME = 60; - private static final List resultListeners = new ArrayList<>(); - private static final LimitedQueue taskQueue = new LimitedQueue<>(TASK_QUEUE_SIZE); private static ExecutorService executor = new ThreadPoolExecutor(THREAD_COUNT, THREAD_COUNT, KEEP_ALIVE_TIME, TimeUnit.SECONDS, taskQueue); @@ -78,18 +75,6 @@ public static void shutdown() { clearExecutor(); } - public static void addRetrievalResultListener(RetrievalResultListener listener) { - Objects.requireNonNull(listener, LISTENER_NULL_MESSAGE); - if (!resultListeners.contains(listener)) { - resultListeners.add(listener); - } - } - - public static void removeRetrievalResultListener(RetrievalResultListener listener) { - Objects.requireNonNull(listener, LISTENER_NULL_MESSAGE); - resultListeners.remove(listener); - } - private ContinuousQueryDispatcher(Function taskFactory, TObjectDoubleMap retrieverWeights, RetrieverInitializer initializer, MediaSegmentReader mediaSegmentReader) { @@ -198,10 +183,6 @@ private void addRetrievalResult(TObjectDoubleMap scoreByObjectId, return; } - for (RetrievalResultListener listener : resultListeners) { - listener.notify(scoreElements, task); - } - double retrieverWeight = this.retrieverWeights.get(task.getRetriever()); for (ScoreElement element : scoreElements) { TObjectDoubleMap scoreById; diff --git a/cineast-runtime/src/main/java/org/vitrivr/cineast/standalone/util/ContinuousRetrievalLogic.java b/cineast-runtime/src/main/java/org/vitrivr/cineast/standalone/util/ContinuousRetrievalLogic.java index f2cafc2e5..5ea0efac4 100644 --- a/cineast-runtime/src/main/java/org/vitrivr/cineast/standalone/util/ContinuousRetrievalLogic.java +++ b/cineast-runtime/src/main/java/org/vitrivr/cineast/standalone/util/ContinuousRetrievalLogic.java @@ -14,7 +14,6 @@ import org.vitrivr.cineast.core.features.retriever.Retriever; import org.vitrivr.cineast.core.features.retriever.RetrieverInitializer; import org.vitrivr.cineast.standalone.config.Config; -import org.vitrivr.cineast.standalone.listener.RetrievalResultListener; import org.vitrivr.cineast.standalone.runtime.ContinuousQueryDispatcher; public class ContinuousRetrievalLogic { @@ -92,14 +91,6 @@ public List retrieveByRetrieverName(AbstractQueryTermContai return retrieveByRetriever(qc, retriever.get(), config); } - public void addRetrievalResultListener(RetrievalResultListener listener) { - ContinuousQueryDispatcher.addRetrievalResultListener(listener); - } - - public void removeRetrievalResultListener(RetrievalResultListener listener) { - ContinuousQueryDispatcher.removeRetrievalResultListener(listener); - } - public void shutdown() { ContinuousQueryDispatcher.shutdown(); segmentReader.close(); diff --git a/cineast.json b/cineast.json index 168097d8f..9c751ba46 100644 --- a/cineast.json +++ b/cineast.json @@ -35,12 +35,6 @@ {"feature": "DominantEdgeGrid16", "weight": 1.4}, {"feature": "DominantEdgeGrid8", "weight": 1.4} ], - "motion": [ - {"feature": "SubDivMotionHistogram3", "weight": 0.5}, - {"feature": "SubDivMotionHistogram5", "weight": 0.5}, - {"feature": "SubDivMotionHistogramBackground3", "weight": 0.5}, - {"feature": "SubDivMotionHistogramBackground5", "weight": 0.5} - ], "localfeatures": [ {"feature": "HOGMirflickr25K512", "weight": 1.0} ], From 7ebaf373c3b8fa7a758a990b6a53f97fd13281c2 Mon Sep 17 00:00:00 2001 From: Silvan Heller Date: Sun, 13 Mar 2022 14:09:23 +0100 Subject: [PATCH 3/9] finalizing functionality for db query IDs --- .../cineast/api/grpc/CineastQueryService.java | 4 +- .../vitrivr/cineast/api/util/QueryUtil.java | 2 +- .../queries/AbstractQueryMessageHandler.java | 43 ++++++--------- .../queries/SegmentQueryMessageHandler.java | 4 +- .../vitrivr/cineast/core/db/DBSelector.java | 26 +++++++-- .../db/cottontaildb/CottontailSelector.java | 53 +++++++++++-------- .../db/dao/reader/AbstractMetadataReader.java | 27 ++++++++-- .../core/db/dao/reader/MediaObjectReader.java | 9 +++- .../db/dao/reader/MediaSegmentReader.java | 16 ++++-- .../cineast/core/util/DBQueryIDGenerator.java | 43 +++++++++++++++ .../cineast/core/util/QueryIDGenerator.java | 14 ----- 11 files changed, 161 insertions(+), 80 deletions(-) create mode 100644 cineast-core/src/main/java/org/vitrivr/cineast/core/util/DBQueryIDGenerator.java delete mode 100644 cineast-core/src/main/java/org/vitrivr/cineast/core/util/QueryIDGenerator.java diff --git a/cineast-api/src/main/java/org/vitrivr/cineast/api/grpc/CineastQueryService.java b/cineast-api/src/main/java/org/vitrivr/cineast/api/grpc/CineastQueryService.java index f27a6a3ee..936d5612f 100644 --- a/cineast-api/src/main/java/org/vitrivr/cineast/api/grpc/CineastQueryService.java +++ b/cineast-api/src/main/java/org/vitrivr/cineast/api/grpc/CineastQueryService.java @@ -236,7 +236,7 @@ public void getSimilar(CineastGrpc.TemporalQuery query, StreamObserver segments = mediaSegmentReader.lookUpSegments(segmentIds); + Map segments = mediaSegmentReader.lookUpSegments(segmentIds, uuid); responseObserver.onNext( QueryContainerUtil.queryResult( @@ -261,7 +261,7 @@ public void getSimilar(CineastGrpc.TemporalQuery query, StreamObserver objects = mediaObjectReader.lookUpObjects(objectIds); + Map objects = mediaObjectReader.lookUpObjects(objectIds, uuid); responseObserver.onNext( QueryContainerUtil.queryResult( diff --git a/cineast-api/src/main/java/org/vitrivr/cineast/api/util/QueryUtil.java b/cineast-api/src/main/java/org/vitrivr/cineast/api/util/QueryUtil.java index e75543595..21996ef29 100644 --- a/cineast-api/src/main/java/org/vitrivr/cineast/api/util/QueryUtil.java +++ b/cineast-api/src/main/java/org/vitrivr/cineast/api/util/QueryUtil.java @@ -124,7 +124,7 @@ public static List findSegmentsSimilarTemporal(ContinuousRetriev ) ).distinct().collect(Collectors.toList()); - var segmentDescriptors = segmentReader.lookUpSegments(segmentIds); + var segmentDescriptors = segmentReader.lookUpSegments(segmentIds, config.getQueryId().toString()); var stagedQueryResults = stagedResults.stream().map( resultsMap -> resultsMap.values().stream().flatMap(Collection::stream).collect(Collectors.toList()) ).collect(Collectors.toList()); diff --git a/cineast-api/src/main/java/org/vitrivr/cineast/api/websocket/handlers/queries/AbstractQueryMessageHandler.java b/cineast-api/src/main/java/org/vitrivr/cineast/api/websocket/handlers/queries/AbstractQueryMessageHandler.java index 147899f23..8bd2dcc76 100644 --- a/cineast-api/src/main/java/org/vitrivr/cineast/api/websocket/handlers/queries/AbstractQueryMessageHandler.java +++ b/cineast-api/src/main/java/org/vitrivr/cineast/api/websocket/handlers/queries/AbstractQueryMessageHandler.java @@ -43,7 +43,7 @@ import org.vitrivr.cineast.core.db.dao.reader.MediaSegmentMetadataReader; import org.vitrivr.cineast.core.db.dao.reader.MediaSegmentReader; import org.vitrivr.cineast.core.util.LogHelper; -import org.vitrivr.cineast.core.util.QueryIDGenerator; +import org.vitrivr.cineast.core.util.DBQueryIDGenerator; import org.vitrivr.cineast.core.util.TimeHelper; import org.vitrivr.cineast.standalone.config.Config; import org.vitrivr.cineast.standalone.config.ConstrainedQueryConfig; @@ -135,36 +135,27 @@ public final void handle(Session session, T message) { * @param segmentIds List of segment IDs that should be looked up. * @return List of found {@link MediaSegmentDescriptor} */ - protected List loadSegments(List segmentIds) { - return loadSegments(segmentIds, QueryIDGenerator.generateQueryID()); - } - protected List loadSegments(List segmentIds, String queryID) { - queryID = queryID + "-loadseg"; LOGGER.trace("Loading segment information for {} segmentIDs, qid {}", segmentIds.size(), queryID); return TimeHelper.timeCall(() -> { - final Map map = this.mediaSegmentReader.lookUpSegments(segmentIds); + final Map map = this.mediaSegmentReader.lookUpSegments(segmentIds, queryID); final ArrayList sdList = new ArrayList<>(map.size()); segmentIds.stream().filter(map::containsKey).forEach(s -> sdList.add(map.get(s))); return sdList; }, "loading segment information, qid " + queryID, Level.TRACE); } + /** * Performs a lookup for the {@link MediaObjectDescriptor} identified by the provided object IDs and returns a list of the {@link MediaSegmentDescriptor}s that were found. * * @param objectIds List of object IDs that should be looked up. * @return List of found {@link MediaObjectDescriptor} */ - protected List loadObjects(List objectIds) { - return loadObjects(objectIds, QueryIDGenerator.generateQueryID()); - } - protected List loadObjects(List objectIds, String queryID) { - queryID = queryID + "-loadobj"; LOGGER.trace("Loading object information for {} segmentIDs, qid {}", objectIds.size(), queryID); return TimeHelper.timeCall(() -> { - final Map map = this.mediaObjectReader.lookUpObjects(objectIds); + final Map map = this.mediaObjectReader.lookUpObjects(objectIds, queryID); final ArrayList vdList = new ArrayList<>(map.size()); objectIds.stream().filter(map::containsKey).forEach(s -> vdList.add(map.get(s))); return vdList; @@ -189,7 +180,7 @@ protected synchronized List loadAndWriteObjectMetadata(Session session, return Lists.partition(objectIds, 100_000).stream().map(list -> loadAndWriteObjectMetadata(session, queryId, list, objectIdsForWhichMetadataIsFetched, metadataAccessSpec)).flatMap(Collection::stream).collect(Collectors.toList()); } Thread thread = new Thread(() -> { - final List objectMetadata = this.objectMetadataReader.findBySpec(objectIds, metadataAccessSpec); + final List objectMetadata = this.objectMetadataReader.findBySpec(objectIds, metadataAccessSpec, queryId); if (objectMetadata.isEmpty()) { return; } @@ -225,7 +216,7 @@ synchronized List loadAndWriteSegmentMetadata(Session session, String qu return Lists.partition(segmentIds, 100_000).stream().map(list -> loadAndWriteSegmentMetadata(session, queryId, list, segmentIdsForWhichMetadataIsFetched, metadataAccessSpec)).flatMap(Collection::stream).collect(Collectors.toList()); } Thread fetching = new Thread(() -> { - final List segmentMetadata = this.segmentMetadataReader.findBySpec(segmentIds, metadataAccessSpec); + final List segmentMetadata = this.segmentMetadataReader.findBySpec(segmentIds, metadataAccessSpec, queryId); if (segmentMetadata.isEmpty()) { return; } @@ -257,21 +248,21 @@ synchronized List loadAndWriteSegmentMetadata(Session session, String qu * * @return objectIds retrieved for the segmentIds */ - protected List submitSegmentAndObjectInformation(Session session, String queryId, List segmentIds) { + protected List submitSegmentAndObjectInformation(Session session, String queryID, List segmentIds) { /* Load segment & object information. */ - LOGGER.trace("Loading segment and object information for submission, {} segments, qid {}", segmentIds.size(), queryId); - final List segments = this.loadSegments(segmentIds, queryId); - return submitPrefetchedSegmentAndObjectInformation(session, queryId, segments); + LOGGER.trace("Loading segment and object information for submission, {} segments, qid {}", segmentIds.size(), queryID); + final List segments = this.loadSegments(segmentIds, queryID); + return submitPrefetchedSegmentAndObjectInformation(session, queryID, segments); } - protected List submitPrefetchedSegmentAndObjectInformation(Session session, String queryId, List segments) { + protected List submitPrefetchedSegmentAndObjectInformation(Session session, String queryID, List segments) { final List objectIds = segments.stream().map(MediaSegmentDescriptor::getObjectId).collect(Collectors.toList()); - return submitPrefetchedSegmentandObjectInformationfromIDs(session, queryId, segments, objectIds); + return submitPrefetchedSegmentandObjectInformationfromIDs(session, queryID, segments, objectIds); } - List submitPrefetchedSegmentandObjectInformationfromIDs(Session session, String queryId, List segments, List objectIds) { + List submitPrefetchedSegmentandObjectInformationfromIDs(Session session, String queryID, List segments, List objectIds) { LOGGER.trace("Loading object information"); - final List objects = this.loadObjects(objectIds, queryId.substring(0, 3)); + final List objects = this.loadObjects(objectIds, queryID); if (segments.isEmpty() || objects.isEmpty()) { LOGGER.traceEntry("Segment / Objectlist is Empty, ignoring this iteration"); @@ -280,8 +271,8 @@ List submitPrefetchedSegmentandObjectInformationfromIDs(Session session, LOGGER.trace("Writing results to the websocket"); /* Write segments, objects and similarity search data to stream. */ - this.write(session, new MediaObjectQueryResult(queryId, objects)); - this.write(session, new MediaSegmentQueryResult(queryId, segments)); + this.write(session, new MediaObjectQueryResult(queryID, objects)); + this.write(session, new MediaSegmentQueryResult(queryID, segments)); return objectIds; } @@ -291,7 +282,7 @@ List submitPrefetchedSegmentandObjectInformationfromIDs(Session session, void submitSegmentAndObjectInformationFromIds(Session session, String queryId, List segmentIds, List objectIds) { /* Load segment & object information. */ LOGGER.trace("Loading segment and object information for submission, {} segments {} objects", segmentIds.size(), objectIds.size()); - final List segments = this.loadSegments(segmentIds, queryId.substring(0, 3)); + final List segments = this.loadSegments(segmentIds, queryId); submitPrefetchedSegmentandObjectInformationfromIDs(session, queryId, segments, objectIds); } diff --git a/cineast-api/src/main/java/org/vitrivr/cineast/api/websocket/handlers/queries/SegmentQueryMessageHandler.java b/cineast-api/src/main/java/org/vitrivr/cineast/api/websocket/handlers/queries/SegmentQueryMessageHandler.java index fb4a6f052..721e2d68a 100644 --- a/cineast-api/src/main/java/org/vitrivr/cineast/api/websocket/handlers/queries/SegmentQueryMessageHandler.java +++ b/cineast-api/src/main/java/org/vitrivr/cineast/api/websocket/handlers/queries/SegmentQueryMessageHandler.java @@ -35,14 +35,14 @@ public void execute(Session session, QueryConfig qconf, SegmentQuery message, Se /* Retrieve segments; if empty, abort query. */ final List segmentId = new ArrayList<>(0); segmentId.add(message.getSegmentId()); - final List segment = this.loadSegments(segmentId); + final List segment = this.loadSegments(segmentId, uuid); if (segment.isEmpty()) { return; } /* Retrieve media objects; if empty, abort query. */ final List objectId = segment.stream().map(MediaSegmentDescriptor::getObjectId).collect(Collectors.toList()); - final List object = this.loadObjects(objectId); + final List object = this.loadObjects(objectId, uuid); if (object.isEmpty()) { return; } diff --git a/cineast-core/src/main/java/org/vitrivr/cineast/core/db/DBSelector.java b/cineast-core/src/main/java/org/vitrivr/cineast/core/db/DBSelector.java index d78f40751..df5c00881 100644 --- a/cineast-core/src/main/java/org/vitrivr/cineast/core/db/DBSelector.java +++ b/cineast-core/src/main/java/org/vitrivr/cineast/core/db/DBSelector.java @@ -112,6 +112,13 @@ default List> getRows(String fieldName, Primi */ List> getRows(String fieldName, Iterable values); + /** + * By default, the queryID is ignored + */ + default List> getRows(String fieldName, Iterable values, String dbQueryID) { + return getRows(fieldName, values); + } + /** * Conversion to PrimitiveTypeProviders is expensive so feel free to use & implement extension for generic objects */ @@ -119,6 +126,13 @@ default List> getRows(String fieldName, List< return getRows(fieldName, values.stream().map(StringTypeProvider::new).collect(Collectors.toList())); } + /** + * Conversion to PrimitiveTypeProviders is expensive so feel free to use & implement extension for generic objects + */ + default List> getRows(String fieldName, List values, String dbQueryID) { + return getRows(fieldName, values.stream().map(StringTypeProvider::new).collect(Collectors.toList())); + } + /** * Performs a fulltext search with multiple query terms. That is, the storage engine is tasked to lookup for entries in the provided fields that match the provided query terms. * @@ -203,14 +217,19 @@ default Map countDistinctValues(String column) { /** * by default just calls the implementation with a null-list for ids */ - default List> getMetadataBySpec(List spec) { - return this.getMetadataByIdAndSpec(null, spec, null); + default List> getMetadataBySpec(List spec, String dbQueryID) { + return this.getMetadataByIdAndSpec(null, spec, null, dbQueryID); + } + + default List> getMetadataByIdAndSpec(List ids, List spec, String idColName) { + return getMetadataByIdAndSpec(ids, spec, idColName, null); } /** * Horribly slow default implementation which iterates over the whole table */ - default List> getMetadataByIdAndSpec(List ids, List spec, String idColName) { + default List> getMetadataByIdAndSpec(List ids, List spec, String idColName, String dbQueryID) { + LOGGER.trace("fetching metadata with spec, dbQueryID {}", dbQueryID); return getAll().stream().filter(tuple -> { // check if there are any elements of the specification which do not work if (spec.stream().noneMatch(el -> { @@ -284,6 +303,7 @@ default List> getAll(List columns, in */ List> getAll(); + boolean existsEntity(String name); /** diff --git a/cineast-core/src/main/java/org/vitrivr/cineast/core/db/cottontaildb/CottontailSelector.java b/cineast-core/src/main/java/org/vitrivr/cineast/core/db/cottontaildb/CottontailSelector.java index 43424a253..2e532ee6a 100644 --- a/cineast-core/src/main/java/org/vitrivr/cineast/core/db/cottontaildb/CottontailSelector.java +++ b/cineast-core/src/main/java/org/vitrivr/cineast/core/db/cottontaildb/CottontailSelector.java @@ -4,6 +4,7 @@ import static org.vitrivr.cineast.core.util.CineastConstants.DOMAIN_COL_NAME; import static org.vitrivr.cineast.core.util.CineastConstants.GENERIC_ID_COLUMN_QUALIFIER; import static org.vitrivr.cineast.core.util.CineastConstants.KEY_COL_NAME; +import static org.vitrivr.cineast.core.util.DBQueryIDGenerator.generateQueryID; import io.grpc.Status.Code; import io.grpc.StatusRuntimeException; @@ -28,7 +29,6 @@ import org.vitrivr.cineast.core.db.DBSelector; import org.vitrivr.cineast.core.db.RelationalOperator; import org.vitrivr.cineast.core.db.dao.MetadataAccessSpecification; -import org.vitrivr.cineast.core.util.QueryIDGenerator; import org.vitrivr.cottontail.client.iterators.Tuple; import org.vitrivr.cottontail.client.iterators.TupleIterator; import org.vitrivr.cottontail.client.language.basics.Direction; @@ -97,7 +97,7 @@ public List> getNearestNeighbourRows(int k, f @Override public List getFeatureVectors(String fieldName, PrimitiveTypeProvider value, String vectorName, ReadableQueryConfig queryConfig) { - final Query query = new Query(this.fqn).select(vectorName, null).where(new Literal(fieldName, "==", value.toObject())).queryId(queryConfig.getQueryId().toString()); + final Query query = new Query(this.fqn).select(vectorName, null).where(new Literal(fieldName, "==", value.toObject())).queryId(generateQueryID("get-fv", queryConfig)); try { final TupleIterator results = this.cottontail.client.query(query); final List _return = new LinkedList<>(); @@ -114,7 +114,7 @@ public List getFeatureVectors(String fieldName, PrimitiveTypeProvider v @Override public List getFeatureVectorsGeneric(String fieldName, PrimitiveTypeProvider value, String vectorName, ReadableQueryConfig qc) { - final Query query = new Query(this.fqn).select(vectorName, null).where(new Literal(fieldName, "==", value.toObject())).queryId(qc.getQueryId().toString()); + final Query query = new Query(this.fqn).select(vectorName, null).where(new Literal(fieldName, "==", value.toObject())).queryId(generateQueryID("get-fv-gen", qc)); try { return toSingleCol(this.cottontail.client.query(query), vectorName); } catch (StatusRuntimeException e) { @@ -135,6 +135,18 @@ public List> getRows(String fieldName, List> getRows(String fieldName, Iterable values, String dbQueryID) { + final Object[] mapped = StreamSupport.stream(values.spliterator(), false).map(PrimitiveTypeProvider::toObject).toArray(); + return getRowsHelper(fieldName, "IN", mapped, dbQueryID); + } + + @Override + public List> getRows(String fieldName, List values, String dbQueryID) { + final Object[] mapped = values.toArray(); + return getRowsHelper(fieldName, "IN", mapped, dbQueryID); + } + @Override public List> getRows(String fieldName, RelationalOperator operator, Iterable values) { final Object[] mapped = StreamSupport.stream(values.spliterator(), false).map(PrimitiveTypeProvider::toObject).toArray(); @@ -142,9 +154,8 @@ public List> getRows(String fieldName, Relati return getRowsHelper(fieldName, op, mapped, "get-rows-" + op + "-iterable"); } - private List> getRowsHelper(String fieldName, String op, Object[] mapped, String qIdInfix) { - String queryId = QueryIDGenerator.generateQueryID(qIdInfix); - final Query query = new Query(this.fqn).select("*", null).where(new Literal(fieldName, op, mapped)).queryId(queryId); + private List> getRowsHelper(String fieldName, String op, Object[] mapped, String dbQueryID) { + final Query query = new Query(this.fqn).select("*", null).where(new Literal(fieldName, op, mapped)).queryId(dbQueryID); try { return processResults(this.cottontail.client.query(query)); } catch (StatusRuntimeException e) { @@ -159,14 +170,15 @@ public List> getFulltextRows(int rows, String final String predicate = Arrays.stream(terms).map(String::trim).collect(Collectors.joining(" OR ")); final Query query = new Query(this.fqn) .select("*", null) - .fulltext(fieldname, predicate, DB_DISTANCE_VALUE_QUALIFIER); + .fulltext(fieldname, predicate, DB_DISTANCE_VALUE_QUALIFIER) + .queryId(generateQueryID("ft-rows", queryConfig)); + /* Process predicates. */ if (queryConfig != null && !queryConfig.getRelevantSegmentIds().isEmpty()) { final Set relevant = queryConfig.getRelevantSegmentIds(); final Literal segmentIds = new Literal(GENERIC_ID_COLUMN_QUALIFIER, "IN", relevant.toArray()); query.where(new And(segmentIds, new Literal(DB_DISTANCE_VALUE_QUALIFIER, ">", 0.0))); - query.queryId(queryConfig.getQueryId().toString()); } else { query.where(new Literal(DB_DISTANCE_VALUE_QUALIFIER, ">", 0.0)); } @@ -182,10 +194,7 @@ public List> getFulltextRows(int rows, String @Override public List> getRowsAND(List>> conditions, String identifier, List projection, ReadableQueryConfig qc) { /* Prepare plain query. */ - final Query query = new Query(this.fqn); - if (qc != null) { - query.queryId(qc.getQueryId().toString()); - } + final Query query = new Query(this.fqn).queryId(generateQueryID("get-rows-and", qc)); if (projection.isEmpty()) { query.select("*", null); } else { @@ -223,16 +232,16 @@ public List> getRowsAND(List> getMetadataBySpec(List spec) { - final Query query = new Query(this.fqn).select("*", null); + public List> getMetadataBySpec(List spec, String dbQueryID) { + final Query query = new Query(this.fqn).select("*", null).queryId(dbQueryID); final Optional predicates = generateQueryFromMetadataSpec(spec); predicates.ifPresent(query::where); return processResults(this.cottontail.client.query(query)); } @Override - public List> getMetadataByIdAndSpec(List ids, List spec, String idColName) { - final Query query = new Query(this.fqn).select("*", null); + public List> getMetadataByIdAndSpec(List ids, List spec, String idColName, String dbQueryID) { + final Query query = new Query(this.fqn).select("*", null).queryId(dbQueryID == null ? "md-id-spec" : dbQueryID); final Optional predicates = generateQueryFromMetadataSpec(spec); final Literal segmentIds = new Literal(idColName, "IN", ids.toArray()); if (predicates.isPresent()) { @@ -274,7 +283,7 @@ public Optional generateQueryFromMetadataSpec(List getAll(String column) { - final Query query = new Query(this.fqn).select(column, null).queryId(QueryIDGenerator.generateQueryID("all-" + column)); + final Query query = new Query(this.fqn).select(column, null).queryId(generateQueryID("all-" + column)); try { return toSingleCol(this.cottontail.client.query(query), column); } catch (StatusRuntimeException e) { @@ -286,7 +295,7 @@ public List getAll(String column) { @Override public List> getAll(List columns, int limit) { final Query query = new Query(this.fqn); - query.queryId(QueryIDGenerator.generateQueryID("all-cols-limit-" + limit)); + query.queryId(generateQueryID("all-cols-limit-" + limit)); for (String c : columns) { query.select(c, null); } @@ -304,7 +313,7 @@ public List> getAll(List columns, int @Override public List getUniqueValues(String column) { final Query query = new Query(this.fqn).distinct(column, null). - queryId(QueryIDGenerator.generateQueryID("unique-" + column)); + queryId(generateQueryID("unique-" + column)); try { return toSingleCol(this.cottontail.client.query(query), column); } catch (StatusRuntimeException e) { @@ -315,7 +324,7 @@ public List getUniqueValues(String column) { public Map countDistinctValues(String column) { final Query query = new Query(this.fqn).select(column, null) - .queryId(QueryIDGenerator.generateQueryID("count-distinct-" + column)); + .queryId(generateQueryID("count-distinct-" + column)); final Map count = new HashMap<>(); try { final TupleIterator results = this.cottontail.client.query(query); @@ -333,7 +342,7 @@ public Map countDistinctValues(String column) { @Override public List> getAll() { final Query query = new Query(this.fqn).select("*", null) - .queryId("get-all"); + .queryId(generateQueryID("get-all-" + this.fqn)); try { return processResults(this.cottontail.client.query(query)); } catch (StatusRuntimeException e) { @@ -397,7 +406,7 @@ private Query knn(int k, float[] vector, String column, ReadableQueryConfig conf .distance(column, vector, distance, DB_DISTANCE_VALUE_QUALIFIER) .order(DB_DISTANCE_VALUE_QUALIFIER, Direction.ASC) .limit(k) - .queryId(config.getQueryId().toString()); + .queryId(generateQueryID("knn", config)); for (String s : select) { query.select(s, null); diff --git a/cineast-core/src/main/java/org/vitrivr/cineast/core/db/dao/reader/AbstractMetadataReader.java b/cineast-core/src/main/java/org/vitrivr/cineast/core/db/dao/reader/AbstractMetadataReader.java index b80256567..0416d0f72 100644 --- a/cineast-core/src/main/java/org/vitrivr/cineast/core/db/dao/reader/AbstractMetadataReader.java +++ b/cineast-core/src/main/java/org/vitrivr/cineast/core/db/dao/reader/AbstractMetadataReader.java @@ -16,6 +16,7 @@ import org.vitrivr.cineast.core.db.DBSelector; import org.vitrivr.cineast.core.db.dao.MetadataAccessSpecification; import org.vitrivr.cineast.core.db.dao.MetadataType; +import org.vitrivr.cineast.core.util.DBQueryIDGenerator; /** * Abstraction layer for segment and object metadata retrieval. @@ -56,6 +57,10 @@ public List lookupMultimediaMetadata(List ids) { } public List findBySpec(List ids, List spec) { + return findBySpec(ids, spec, null); + } + + public List findBySpec(List ids, List spec, String queryID) { if (ids == null || spec == null) { LOGGER.warn("provided id-list {} or spec {} is null, returning empty list", ids, spec); return new ArrayList<>(); @@ -67,12 +72,17 @@ public List findBySpec(List ids, List sp StopWatch watch = StopWatch.createStarted(); ids = sanitizeIds(ids); spec = sanitizeSpec(spec); - List> results = selector.getMetadataByIdAndSpec(ids, spec, idColName); + String dbQueryID = DBQueryIDGenerator.generateQueryID("find-md-spec-" + tableName, queryID); + List> results = selector.getMetadataByIdAndSpec(ids, spec, idColName, dbQueryID); LOGGER.debug("Performed metadata lookup for {} ids in {} ms. {} results.", ids.size(), watch.getTime(TimeUnit.MILLISECONDS), results.size()); return mapToResultList(results); } public List findBySpec(List spec) { + return findBySpec(spec, null); + } + + public List findBySpec(List spec, String queryID) { if (spec == null) { LOGGER.warn("Provided spec is null, returning empty list"); return new ArrayList<>(); @@ -83,7 +93,8 @@ public List findBySpec(List spec) { } StopWatch watch = StopWatch.createStarted(); spec = sanitizeSpec(spec); - List> results = selector.getMetadataBySpec(spec); + String dbQueryID = DBQueryIDGenerator.generateQueryID("find-my-spec-" + tableName, queryID); + List> results = selector.getMetadataBySpec(spec, dbQueryID); LOGGER.debug("Performed metadata lookup in {} ms. {} results.", watch.getTime(TimeUnit.MILLISECONDS), results.size()); return mapToResultList(results); } @@ -105,11 +116,17 @@ public List findBySpec(List ids, MetadataAccessSpecification spec) { } public List findBySpec(MetadataAccessSpecification... spec) { - return this.findBySpec(Lists.newArrayList(spec)); + return this.findBySpec(Lists.newArrayList(spec), null); } - public List findBySpec(MetadataAccessSpecification spec) { - return this.findBySpec(Lists.newArrayList(spec)); + /** + * Returns metadata according to spec + * + * @param spec access specification + * @param queryID can be null + */ + public List findBySpec(MetadataAccessSpecification spec, String queryID) { + return this.findBySpec(Lists.newArrayList(spec), queryID); } public List sanitizeSpec(List spec) { diff --git a/cineast-core/src/main/java/org/vitrivr/cineast/core/db/dao/reader/MediaObjectReader.java b/cineast-core/src/main/java/org/vitrivr/cineast/core/db/dao/reader/MediaObjectReader.java index 4f0288110..02d3d2481 100644 --- a/cineast-core/src/main/java/org/vitrivr/cineast/core/db/dao/reader/MediaObjectReader.java +++ b/cineast-core/src/main/java/org/vitrivr/cineast/core/db/dao/reader/MediaObjectReader.java @@ -13,6 +13,7 @@ import org.vitrivr.cineast.core.data.providers.primitive.ProviderDataType; import org.vitrivr.cineast.core.data.providers.primitive.StringTypeProvider; import org.vitrivr.cineast.core.db.DBSelector; +import org.vitrivr.cineast.core.util.DBQueryIDGenerator; public class MediaObjectReader extends AbstractEntityReader { @@ -99,20 +100,24 @@ public MediaObjectDescriptor lookUpObjectByPath(String path) { return mapToDescriptor(result.get(0)); } - public Map lookUpObjects(Iterable videoIds) { + public Map lookUpObjects(Iterable videoIds, String queryID) { if (videoIds == null) { return new HashMap<>(); } + String dbQueryID = DBQueryIDGenerator.generateQueryID("load-obj", queryID); HashMap _return = new HashMap<>(); - List> results = selector.getRows(MediaObjectDescriptor.FIELDNAMES[0], Lists.newArrayList(videoIds)); + List> results = selector.getRows(MediaObjectDescriptor.FIELDNAMES[0], Lists.newArrayList(videoIds), dbQueryID); results.forEach(el -> { MediaObjectDescriptor d = mapToDescriptor(el); _return.put(d.getObjectId(), d); }); return _return; + } + public Map lookUpObjects(Iterable videoIds) { + return lookUpObjects(videoIds, null); } public List getAllObjects() { diff --git a/cineast-core/src/main/java/org/vitrivr/cineast/core/db/dao/reader/MediaSegmentReader.java b/cineast-core/src/main/java/org/vitrivr/cineast/core/db/dao/reader/MediaSegmentReader.java index e324a33a2..2c80994da 100644 --- a/cineast-core/src/main/java/org/vitrivr/cineast/core/db/dao/reader/MediaSegmentReader.java +++ b/cineast-core/src/main/java/org/vitrivr/cineast/core/db/dao/reader/MediaSegmentReader.java @@ -18,6 +18,7 @@ import org.vitrivr.cineast.core.data.providers.primitive.PrimitiveTypeProvider; import org.vitrivr.cineast.core.data.providers.primitive.StringTypeProvider; import org.vitrivr.cineast.core.db.DBSelector; +import org.vitrivr.cineast.core.util.DBQueryIDGenerator; public class MediaSegmentReader extends AbstractEntityReader { @@ -65,7 +66,11 @@ public Optional lookUpSegment(String segmentId) { } public Map lookUpSegments(Iterable segmentIds) { - Stream descriptors = this.lookUpSegmentsByField(FIELDNAMES[0], segmentIds); + return lookUpSegments(segmentIds, null); + } + + public Map lookUpSegments(Iterable segmentIds, String queryID) { + Stream descriptors = this.lookUpSegmentsByField(FIELDNAMES[0], segmentIds, queryID); //this implicitly deduplicates the stream Map _return = new HashMap<>(); descriptors.forEach(msd -> _return.put(msd.getSegmentId(), msd)); @@ -102,11 +107,16 @@ private Stream lookUpSegmentsByField( private Stream lookUpSegmentsByField( String fieldName, Iterable fieldValues) { + return lookUpSegmentsByField(fieldName, fieldValues, null); + } + + private Stream lookUpSegmentsByField( + String fieldName, Iterable fieldValues, String queryID) { + String dbQueryID = DBQueryIDGenerator.generateQueryID("seg-lookup", queryID); Set uniqueFieldValues = new HashSet<>(); fieldValues.forEach(el -> uniqueFieldValues.add(new StringTypeProvider(el))); - List> segmentsProperties = - this.selector.getRows(fieldName, Lists.newArrayList(uniqueFieldValues)); + List> segmentsProperties = this.selector.getRows(fieldName, Lists.newArrayList(uniqueFieldValues), dbQueryID); return segmentsProperties .stream() .map(MediaSegmentReader::propertiesToDescriptor) diff --git a/cineast-core/src/main/java/org/vitrivr/cineast/core/util/DBQueryIDGenerator.java b/cineast-core/src/main/java/org/vitrivr/cineast/core/util/DBQueryIDGenerator.java new file mode 100644 index 000000000..c795ae3ec --- /dev/null +++ b/cineast-core/src/main/java/org/vitrivr/cineast/core/util/DBQueryIDGenerator.java @@ -0,0 +1,43 @@ +package org.vitrivr.cineast.core.util; + +import org.apache.commons.lang3.RandomStringUtils; +import org.vitrivr.cineast.core.config.QueryConfig; +import org.vitrivr.cineast.core.config.ReadableQueryConfig; + +/** + * Util class to generate query IDs which are used to connect with the DB + */ +public class DBQueryIDGenerator { + + public static String generateQueryID() { + return generateQueryID(""); + } + + /** + * Generates a queryID with an infix which provides context + */ + public static String generateQueryID(String infix) { + return generate(infix, "noqid-" + RandomStringUtils.randomAlphanumeric(3)); + } + + /** + * Generates a query id with an infix based on an existing query id (e.g. one provided through a {@link QueryConfig} + * + * @param infix infix to use in the queryID + * @param existingID can be null, in which case {@link #generateQueryID(String)} will be called with the infix + */ + public static String generateQueryID(String infix, String existingID) { + return existingID == null ? generateQueryID(infix) : generate(infix, existingID.substring(0, 3)); + } + + /** + * uses {@link ReadableQueryConfig#getQueryId()} as a basis for postfix + */ + public static String generateQueryID(String infix, ReadableQueryConfig qc) { + return qc == null ? generate(infix, "qc-null") : generate(infix, qc.getQueryId().toString().substring(0, 3)); + } + + private static String generate(String infix, String postfix) { + return "q-cin-" + infix + "-" + postfix; + } +} diff --git a/cineast-core/src/main/java/org/vitrivr/cineast/core/util/QueryIDGenerator.java b/cineast-core/src/main/java/org/vitrivr/cineast/core/util/QueryIDGenerator.java deleted file mode 100644 index 060b9644e..000000000 --- a/cineast-core/src/main/java/org/vitrivr/cineast/core/util/QueryIDGenerator.java +++ /dev/null @@ -1,14 +0,0 @@ -package org.vitrivr.cineast.core.util; - -import org.apache.commons.lang3.RandomStringUtils; - -public class QueryIDGenerator { - - public static String generateQueryID() { - return generateQueryID(""); - } - - public static String generateQueryID(String infix) { - return "q-" + infix + RandomStringUtils.randomNumeric(3); - } -} From 3c897b1e7cdfe45eab0d621ced06f95269ced8f2 Mon Sep 17 00:00:00 2001 From: Silvan Heller Date: Sun, 13 Mar 2022 14:26:39 +0100 Subject: [PATCH 4/9] fixing logging, boolean retriever not being instantiable --- .../cineast/core/db/cottontaildb/CottontailSelector.java | 4 ++++ .../cineast/core/features/CollectionBooleanRetriever.java | 4 ++-- .../cineast/core/features/abstracts/BooleanRetriever.java | 6 ++++-- 3 files changed, 10 insertions(+), 4 deletions(-) diff --git a/cineast-core/src/main/java/org/vitrivr/cineast/core/db/cottontaildb/CottontailSelector.java b/cineast-core/src/main/java/org/vitrivr/cineast/core/db/cottontaildb/CottontailSelector.java index 2e532ee6a..a46d941e5 100644 --- a/cineast-core/src/main/java/org/vitrivr/cineast/core/db/cottontaildb/CottontailSelector.java +++ b/cineast-core/src/main/java/org/vitrivr/cineast/core/db/cottontaildb/CottontailSelector.java @@ -22,6 +22,8 @@ import java.util.stream.StreamSupport; import org.apache.commons.lang3.time.StopWatch; import org.apache.commons.lang3.tuple.Triple; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; import org.vitrivr.cineast.core.config.ReadableQueryConfig; import org.vitrivr.cineast.core.config.ReadableQueryConfig.Distance; import org.vitrivr.cineast.core.data.distance.DistanceElement; @@ -42,6 +44,8 @@ public final class CottontailSelector implements DBSelector { + private static final Logger LOGGER = LogManager.getLogger(); + /** * Internal reference to the {@link CottontailWrapper} used by this {@link CottontailSelector}. */ diff --git a/cineast-core/src/main/java/org/vitrivr/cineast/core/features/CollectionBooleanRetriever.java b/cineast-core/src/main/java/org/vitrivr/cineast/core/features/CollectionBooleanRetriever.java index f504f3ee5..acef5e1fe 100644 --- a/cineast-core/src/main/java/org/vitrivr/cineast/core/features/CollectionBooleanRetriever.java +++ b/cineast-core/src/main/java/org/vitrivr/cineast/core/features/CollectionBooleanRetriever.java @@ -15,11 +15,11 @@ public class CollectionBooleanRetriever extends BooleanRetriever { RelationalOperator.IN, RelationalOperator.LIKE)); - protected CollectionBooleanRetriever(String entity, Collection attributes) { + public CollectionBooleanRetriever(String entity, Collection attributes) { super(entity, attributes); } - protected CollectionBooleanRetriever(LinkedHashMap properties) { + public CollectionBooleanRetriever(LinkedHashMap properties) { super(properties); } diff --git a/cineast-core/src/main/java/org/vitrivr/cineast/core/features/abstracts/BooleanRetriever.java b/cineast-core/src/main/java/org/vitrivr/cineast/core/features/abstracts/BooleanRetriever.java index 2d4dd8aff..eb0088c15 100644 --- a/cineast-core/src/main/java/org/vitrivr/cineast/core/features/abstracts/BooleanRetriever.java +++ b/cineast-core/src/main/java/org/vitrivr/cineast/core/features/abstracts/BooleanRetriever.java @@ -38,6 +38,7 @@ public abstract class BooleanRetriever implements MultipleInstantiatableRetrieve protected final String entity; protected final HashSet attributes = new HashSet<>(); protected final HashMap columnTypes = new HashMap<>(); + private String idCol = GENERIC_ID_COLUMN_QUALIFIER; protected BooleanRetriever(String entity, Collection attributes) { this.entity = entity; @@ -57,6 +58,7 @@ protected BooleanRetriever(Map properties) { this.attributes.addAll(attrs); } + this.idCol = properties.getOrDefault("idCol", GENERIC_ID_COLUMN_QUALIFIER); } @Override @@ -103,10 +105,10 @@ protected List getMatching(List expressions, Re be.getValues() )).collect(Collectors.toList()), GENERIC_ID_COLUMN_QUALIFIER, // for compound ops, we want to join via id. Cottontail (the official storage layer) does not use this identifier - Collections.singletonList(GENERIC_ID_COLUMN_QUALIFIER), // we're only interested in the ids + Collections.singletonList(idCol), // we're only interested in the ids qc); // we're returning a boolean score element since the score is always 1 if a query matches here - return rows.stream().map(row -> new BooleanSegmentScoreElement(row.get(GENERIC_ID_COLUMN_QUALIFIER).getString())).collect(Collectors.toList()); + return rows.stream().map(row -> new BooleanSegmentScoreElement(row.get(idCol).getString())).collect(Collectors.toList()); } @Override From e02f3d2b0349507000fb55d097183cbc2c3cb42f Mon Sep 17 00:00:00 2001 From: Silvan Heller Date: Sun, 13 Mar 2022 14:31:30 +0100 Subject: [PATCH 5/9] avoiding crashes when a retriever class can not be found --- .../java/org/vitrivr/cineast/core/util/ReflectionHelper.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/cineast-core/src/main/java/org/vitrivr/cineast/core/util/ReflectionHelper.java b/cineast-core/src/main/java/org/vitrivr/cineast/core/util/ReflectionHelper.java index 4d1e54adb..110e3e2a7 100644 --- a/cineast-core/src/main/java/org/vitrivr/cineast/core/util/ReflectionHelper.java +++ b/cineast-core/src/main/java/org/vitrivr/cineast/core/util/ReflectionHelper.java @@ -306,6 +306,8 @@ public static Class getClassFromName(String className, Class expectedS targetClass = (Class) c; } catch (UnsupportedOperationException e) { LOGGER.warn("'name' was not a string during class instantiation in instantiateFromJson"); + } catch(ClassNotFoundException e){ + LOGGER.warn("Class {} was not found", className); } return targetClass; } From b21b4e7b223451019d762cbdd61d89ba94c6d804 Mon Sep 17 00:00:00 2001 From: Silvan Heller Date: Sun, 13 Mar 2022 15:03:14 +0100 Subject: [PATCH 6/9] moving util packages --- .../java/org/vitrivr/cineast/core/features/OCRSearch.java | 4 ++-- .../cineast/core/util/{ocr => }/HungarianAlgorithm.java | 2 +- .../cineast/core/util/{ocr => }/ThreadLocalObjectCache.java | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) rename cineast-core/src/main/java/org/vitrivr/cineast/core/util/{ocr => }/HungarianAlgorithm.java (99%) rename cineast-core/src/main/java/org/vitrivr/cineast/core/util/{ocr => }/ThreadLocalObjectCache.java (94%) diff --git a/cineast-core/src/main/java/org/vitrivr/cineast/core/features/OCRSearch.java b/cineast-core/src/main/java/org/vitrivr/cineast/core/features/OCRSearch.java index a24da8051..d4340a8e8 100644 --- a/cineast-core/src/main/java/org/vitrivr/cineast/core/features/OCRSearch.java +++ b/cineast-core/src/main/java/org/vitrivr/cineast/core/features/OCRSearch.java @@ -20,13 +20,13 @@ import org.vitrivr.cineast.core.data.entities.SimpleFulltextFeatureDescriptor; import org.vitrivr.cineast.core.data.segments.SegmentContainer; import org.vitrivr.cineast.core.features.abstracts.AbstractTextRetriever; -import org.vitrivr.cineast.core.util.ocr.HungarianAlgorithm; +import org.vitrivr.cineast.core.util.HungarianAlgorithm; import org.vitrivr.cineast.core.util.ocr.MultiTracker; import org.vitrivr.cineast.core.util.ocr.NeedlemanWunschMerge; import org.vitrivr.cineast.core.util.text.TextDetector_EAST; import org.vitrivr.cineast.core.util.text.TextRecognizer_CTC; import org.vitrivr.cineast.core.util.text.TextStream; -import org.vitrivr.cineast.core.util.ocr.ThreadLocalObjectCache; +import org.vitrivr.cineast.core.util.ThreadLocalObjectCache; /** * OCR is handled by adding fuzziness / levenshtein-distance support to the query if there are no quotes present (as quotes indicate precision) This makes sense here since we expect small errors from OCR sources diff --git a/cineast-core/src/main/java/org/vitrivr/cineast/core/util/ocr/HungarianAlgorithm.java b/cineast-core/src/main/java/org/vitrivr/cineast/core/util/HungarianAlgorithm.java similarity index 99% rename from cineast-core/src/main/java/org/vitrivr/cineast/core/util/ocr/HungarianAlgorithm.java rename to cineast-core/src/main/java/org/vitrivr/cineast/core/util/HungarianAlgorithm.java index a2a336847..5817d038b 100644 --- a/cineast-core/src/main/java/org/vitrivr/cineast/core/util/ocr/HungarianAlgorithm.java +++ b/cineast-core/src/main/java/org/vitrivr/cineast/core/util/HungarianAlgorithm.java @@ -1,4 +1,4 @@ -package org.vitrivr.cineast.core.util.ocr; +package org.vitrivr.cineast.core.util; import java.util.Arrays; diff --git a/cineast-core/src/main/java/org/vitrivr/cineast/core/util/ocr/ThreadLocalObjectCache.java b/cineast-core/src/main/java/org/vitrivr/cineast/core/util/ThreadLocalObjectCache.java similarity index 94% rename from cineast-core/src/main/java/org/vitrivr/cineast/core/util/ocr/ThreadLocalObjectCache.java rename to cineast-core/src/main/java/org/vitrivr/cineast/core/util/ThreadLocalObjectCache.java index ddf64ef94..6a9a640b0 100644 --- a/cineast-core/src/main/java/org/vitrivr/cineast/core/util/ocr/ThreadLocalObjectCache.java +++ b/cineast-core/src/main/java/org/vitrivr/cineast/core/util/ThreadLocalObjectCache.java @@ -1,4 +1,4 @@ -package org.vitrivr.cineast.core.util.ocr; +package org.vitrivr.cineast.core.util; import com.google.common.cache.CacheBuilder; import com.google.common.cache.CacheLoader; From 163c23681d6965f9001e63f06a0d830e62d331ed Mon Sep 17 00:00:00 2001 From: Silvan Heller Date: Sun, 13 Mar 2022 15:07:49 +0100 Subject: [PATCH 7/9] replacing fastutil --- .../handlers/queries/TemporalQueryMessageHandler.java | 4 ++-- cineast-core/build.gradle | 2 -- .../core/temporal/AbstractTemporalScoringAlgorithm.java | 4 ++-- 3 files changed, 4 insertions(+), 6 deletions(-) diff --git a/cineast-api/src/main/java/org/vitrivr/cineast/api/websocket/handlers/queries/TemporalQueryMessageHandler.java b/cineast-api/src/main/java/org/vitrivr/cineast/api/websocket/handlers/queries/TemporalQueryMessageHandler.java index e511a9f66..bb18dad2c 100644 --- a/cineast-api/src/main/java/org/vitrivr/cineast/api/websocket/handlers/queries/TemporalQueryMessageHandler.java +++ b/cineast-api/src/main/java/org/vitrivr/cineast/api/websocket/handlers/queries/TemporalQueryMessageHandler.java @@ -1,5 +1,6 @@ package org.vitrivr.cineast.api.websocket.handlers.queries; +import gnu.trove.map.hash.TIntObjectHashMap; import java.util.ArrayList; import java.util.HashMap; import java.util.HashSet; @@ -10,7 +11,6 @@ import java.util.stream.Collectors; import java.util.stream.IntStream; -import it.unimi.dsi.fastutil.ints.Int2ObjectLinkedOpenHashMap; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import org.eclipse.jetty.websocket.api.Session; @@ -54,7 +54,7 @@ public void execute(Session session, QueryConfig qconf, TemporalQuery message, S List cleanupThreads = new ArrayList<>(); /* We need a set of segments and objects to be used for temporal scoring as well as a storage of all container results where are the index of the outer list is where container i was scored */ - Map> containerResults = new Int2ObjectLinkedOpenHashMap<>(); + Map> containerResults = new TIntObjectHashMap<>(); Set segments = new HashSet<>(); Set sentSegmentIds = new HashSet<>(); diff --git a/cineast-core/build.gradle b/cineast-core/build.gradle index c7db2387f..5f5d8c0ad 100644 --- a/cineast-core/build.gradle +++ b/cineast-core/build.gradle @@ -91,8 +91,6 @@ dependencies { api group: "net.sf.trove4j", name: "trove4j", version: version_trove4j api group: "com.google.guava", name: "guava", version: version_guava api group: "com.googlecode.javaewah", name: "JavaEWAH", version: version_javaewah - implementation group: 'it.unimi.dsi', name: 'fastutil', version: '8.5.8' - /** Mockito for unit testing */ implementation 'org.mockito:mockito-inline:3.11.0' diff --git a/cineast-core/src/main/java/org/vitrivr/cineast/core/temporal/AbstractTemporalScoringAlgorithm.java b/cineast-core/src/main/java/org/vitrivr/cineast/core/temporal/AbstractTemporalScoringAlgorithm.java index 66aaa89cc..07ffb1dd9 100644 --- a/cineast-core/src/main/java/org/vitrivr/cineast/core/temporal/AbstractTemporalScoringAlgorithm.java +++ b/cineast-core/src/main/java/org/vitrivr/cineast/core/temporal/AbstractTemporalScoringAlgorithm.java @@ -1,12 +1,12 @@ package org.vitrivr.cineast.core.temporal; +import gnu.trove.map.hash.TIntObjectHashMap; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.TreeSet; import java.util.stream.Collectors; -import it.unimi.dsi.fastutil.ints.Int2ObjectLinkedOpenHashMap; import org.vitrivr.cineast.core.data.StringDoublePair; import org.vitrivr.cineast.core.data.TemporalObject; import org.vitrivr.cineast.core.data.entities.MediaSegmentDescriptor; @@ -56,7 +56,7 @@ protected AbstractTemporalScoringAlgorithm(Map s /* Else assign the scored segment to the ScoredSegment and if there is already a scored Segment present att this score to the one present. */ - scoredSegmentStorage.putIfAbsent(segmentDescriptor.getSegmentId(), new Int2ObjectLinkedOpenHashMap<>()); + scoredSegmentStorage.putIfAbsent(segmentDescriptor.getSegmentId(), new TIntObjectHashMap()); if (scoredSegmentStorage.get(segmentDescriptor.getSegmentId()).containsKey(currentContainerId)) { scoredSegmentStorage.get(segmentDescriptor.getSegmentId()).get(currentContainerId).addScore(stringDoublePair); } else { From 3c2d6ab2f02edf6d2fce52f94c8be9a5af8335ea Mon Sep 17 00:00:00 2001 From: Silvan Heller Date: Mon, 14 Mar 2022 09:22:35 +0100 Subject: [PATCH 8/9] fixing trove issues --- .../queries/TemporalQueryMessageHandler.java | 4 +--- .../temporal/AbstractTemporalScoringAlgorithm.java | 13 +++++++------ .../SequentialTemporalScoringAlgorithm.java | 13 ++++++++----- 3 files changed, 16 insertions(+), 14 deletions(-) diff --git a/cineast-api/src/main/java/org/vitrivr/cineast/api/websocket/handlers/queries/TemporalQueryMessageHandler.java b/cineast-api/src/main/java/org/vitrivr/cineast/api/websocket/handlers/queries/TemporalQueryMessageHandler.java index bb18dad2c..48880c901 100644 --- a/cineast-api/src/main/java/org/vitrivr/cineast/api/websocket/handlers/queries/TemporalQueryMessageHandler.java +++ b/cineast-api/src/main/java/org/vitrivr/cineast/api/websocket/handlers/queries/TemporalQueryMessageHandler.java @@ -1,6 +1,5 @@ package org.vitrivr.cineast.api.websocket.handlers.queries; -import gnu.trove.map.hash.TIntObjectHashMap; import java.util.ArrayList; import java.util.HashMap; import java.util.HashSet; @@ -10,7 +9,6 @@ import java.util.concurrent.CompletableFuture; import java.util.stream.Collectors; import java.util.stream.IntStream; - import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import org.eclipse.jetty.websocket.api.Session; @@ -54,7 +52,7 @@ public void execute(Session session, QueryConfig qconf, TemporalQuery message, S List cleanupThreads = new ArrayList<>(); /* We need a set of segments and objects to be used for temporal scoring as well as a storage of all container results where are the index of the outer list is where container i was scored */ - Map> containerResults = new TIntObjectHashMap<>(); + Map> containerResults = new HashMap<>(); Set segments = new HashSet<>(); Set sentSegmentIds = new HashSet<>(); diff --git a/cineast-core/src/main/java/org/vitrivr/cineast/core/temporal/AbstractTemporalScoringAlgorithm.java b/cineast-core/src/main/java/org/vitrivr/cineast/core/temporal/AbstractTemporalScoringAlgorithm.java index 07ffb1dd9..9e048b954 100644 --- a/cineast-core/src/main/java/org/vitrivr/cineast/core/temporal/AbstractTemporalScoringAlgorithm.java +++ b/cineast-core/src/main/java/org/vitrivr/cineast/core/temporal/AbstractTemporalScoringAlgorithm.java @@ -4,9 +4,9 @@ import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.Map.Entry; import java.util.TreeSet; import java.util.stream.Collectors; - import org.vitrivr.cineast.core.data.StringDoublePair; import org.vitrivr.cineast.core.data.TemporalObject; import org.vitrivr.cineast.core.data.entities.MediaSegmentDescriptor; @@ -23,7 +23,7 @@ public abstract class AbstractTemporalScoringAlgorithm { /* Map an object id to a TreeSet of the corresponding ScoredSegments. We utilize a Tree set instead of a Hashset because we are interested in the natural order of the ScoredSegments. We later want to retrieve all segments larger to a current segment and that is only possible in a data structure that provides ordering. */ protected final Map> scoredSegmentSets; /* Map segment Ids to a Map that maps container Ids of the corresponding temporal result container to ScoredSegments. This is due to the fact that a segment may be present in multiple result containers. */ - protected final Map> scoredSegmentStorage; + protected final Map> scoredSegmentStorage; protected final float maxLength; protected final int maxContainerId; @@ -56,7 +56,7 @@ protected AbstractTemporalScoringAlgorithm(Map s /* Else assign the scored segment to the ScoredSegment and if there is already a scored Segment present att this score to the one present. */ - scoredSegmentStorage.putIfAbsent(segmentDescriptor.getSegmentId(), new TIntObjectHashMap()); + scoredSegmentStorage.putIfAbsent(segmentDescriptor.getSegmentId(), new TIntObjectHashMap()); if (scoredSegmentStorage.get(segmentDescriptor.getSegmentId()).containsKey(currentContainerId)) { scoredSegmentStorage.get(segmentDescriptor.getSegmentId()).get(currentContainerId).addScore(stringDoublePair); } else { @@ -67,9 +67,9 @@ protected AbstractTemporalScoringAlgorithm(Map s } /* Assign the scored segments to the tree sets corresponding to their objectId. */ - for (Map.Entry> entry : scoredSegmentStorage.entrySet()) { + for (Entry> entry : scoredSegmentStorage.entrySet()) { String objectId = segmentMap.get(entry.getKey()).getObjectId(); - for (ScoredSegment scoredSegment : entry.getValue().values()) { + entry.getValue().forEachValue(scoredSegment -> { if (this.scoredSegmentSets.containsKey(objectId)) { this.scoredSegmentSets.get(objectId).add(scoredSegment); } else { @@ -77,7 +77,8 @@ protected AbstractTemporalScoringAlgorithm(Map s tmpSet.add(scoredSegment); this.scoredSegmentSets.put(objectId, tmpSet); } - } + return true; + }); } } diff --git a/cineast-core/src/main/java/org/vitrivr/cineast/core/temporal/sequential/SequentialTemporalScoringAlgorithm.java b/cineast-core/src/main/java/org/vitrivr/cineast/core/temporal/sequential/SequentialTemporalScoringAlgorithm.java index 77602b8b7..7b4768db6 100644 --- a/cineast-core/src/main/java/org/vitrivr/cineast/core/temporal/sequential/SequentialTemporalScoringAlgorithm.java +++ b/cineast-core/src/main/java/org/vitrivr/cineast/core/temporal/sequential/SequentialTemporalScoringAlgorithm.java @@ -1,5 +1,7 @@ package org.vitrivr.cineast.core.temporal.sequential; +import gnu.trove.map.hash.TIntObjectHashMap; +import gnu.trove.procedure.TObjectProcedure; import java.util.ArrayList; import java.util.Comparator; import java.util.HashMap; @@ -41,14 +43,15 @@ public SequentialTemporalScoringAlgorithm(Map se @Override public List score() { /* Calculate the best path for every segment in the result set given to the class. */ - for (Map segments : scoredSegmentStorage.values()) { - for (ScoredSegment scoredSegment : segments.values()) { + for (TIntObjectHashMap segments : scoredSegmentStorage.values()) { + segments.forEachValue(scoredSegment -> { MediaSegmentDescriptor mediaSegmentDescriptor = segmentMap.get(scoredSegment.getSegmentId()); - SequentialPath sequentialPath = this.getBestPathForSegment(mediaSegmentDescriptor, scoredSegment); + SequentialPath sequentialPath = getBestPathForSegment(mediaSegmentDescriptor, scoredSegment); objectPaths.putIfAbsent(mediaSegmentDescriptor.getObjectId(), new ArrayList<>()); - this.objectPaths.get(mediaSegmentDescriptor.getObjectId()).add(sequentialPath); - } + objectPaths.get(mediaSegmentDescriptor.getObjectId()).add(sequentialPath); + return true; + }); } List results = new ArrayList<>(); From efdbe72f581f045c3948ae3c33277f836b06e122 Mon Sep 17 00:00:00 2001 From: Silvan Heller Date: Mon, 14 Mar 2022 13:34:07 +0100 Subject: [PATCH 9/9] bumping version --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index 7e39ef00f..f8dcf5618 100644 --- a/build.gradle +++ b/build.gradle @@ -11,7 +11,7 @@ allprojects { group = 'org.vitrivr' /* Our current version, on dev branch this should always be release+1-SNAPSHOT */ - version = '3.9.0' + version = '3.10.0' apply plugin: 'java-library' apply plugin: 'maven-publish'