Merge branch 'develop' into multi-artists
This commit is contained in:
@@ -118,17 +118,17 @@ Track::getAllWithMBIDAndMissingFeatures(Wt::Dbo::Session& session)
|
|||||||
return std::vector<pointer>(res.begin(), res.end());
|
return std::vector<pointer>(res.begin(), res.end());
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<Track::pointer>
|
std::vector<IdType>
|
||||||
Track::getAllWithFeatures(Wt::Dbo::Session& session, boost::optional<std::size_t> limit)
|
Track::getAllIdsWithFeatures(Wt::Dbo::Session& session, boost::optional<std::size_t> limit)
|
||||||
{
|
{
|
||||||
int size {limit ? static_cast<int>(*limit) : -1};
|
int size {limit ? static_cast<int>(*limit) : -1};
|
||||||
|
|
||||||
Wt::Dbo::collection<pointer> res = session.query<pointer>
|
Wt::Dbo::collection<IdType> res = session.query<IdType>
|
||||||
("SELECT t FROM track t")
|
("SELECT t.id FROM track t")
|
||||||
.where("EXISTS (SELECT * from track_features t_f WHERE t_f.track_id = t.id)")
|
.where("EXISTS (SELECT * from track_features t_f WHERE t_f.track_id = t.id)")
|
||||||
.limit(size);
|
.limit(size);
|
||||||
|
|
||||||
return std::vector<pointer>(res.begin(), res.end());
|
return std::vector<IdType>(res.begin(), res.end());
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<Cluster::pointer>
|
std::vector<Cluster::pointer>
|
||||||
|
|||||||
@@ -64,13 +64,13 @@ class Track : public Wt::Dbo::Dbo<Track>
|
|||||||
bool& moreExpected);
|
bool& moreExpected);
|
||||||
|
|
||||||
static Wt::Dbo::collection< pointer > getAll(Wt::Dbo::Session& session);
|
static Wt::Dbo::collection< pointer > getAll(Wt::Dbo::Session& session);
|
||||||
static std::vector<IdType> getAllIds(Wt::Dbo::Session& session); // nested transaction
|
static std::vector<IdType> getAllIds(Wt::Dbo::Session& session); // nested transaction
|
||||||
static std::vector<boost::filesystem::path> getAllPaths(Wt::Dbo::Session& session); // nested transaction
|
static std::vector<boost::filesystem::path> getAllPaths(Wt::Dbo::Session& session); // nested transaction
|
||||||
static std::vector<pointer> getMBIDDuplicates(Wt::Dbo::Session& session);
|
static std::vector<pointer> getMBIDDuplicates(Wt::Dbo::Session& session);
|
||||||
static std::vector<pointer> getChecksumDuplicates(Wt::Dbo::Session& session);
|
static std::vector<pointer> getChecksumDuplicates(Wt::Dbo::Session& session);
|
||||||
static std::vector<pointer> getLastAdded(Wt::Dbo::Session& session, Wt::WDateTime after, int size = 1);
|
static std::vector<pointer> getLastAdded(Wt::Dbo::Session& session, Wt::WDateTime after, int size = 1);
|
||||||
static std::vector<pointer> getAllWithMBIDAndMissingFeatures(Wt::Dbo::Session& session); // nested transaction
|
static std::vector<pointer> getAllWithMBIDAndMissingFeatures(Wt::Dbo::Session& session); // nested transaction
|
||||||
static std::vector<pointer> getAllWithFeatures(Wt::Dbo::Session& session, boost::optional<std::size_t> limit = {}); // nested transaction
|
static std::vector<IdType> getAllIdsWithFeatures(Wt::Dbo::Session& session, boost::optional<std::size_t> limit = {}); // nested transaction
|
||||||
|
|
||||||
// Create utility
|
// Create utility
|
||||||
static pointer create(Wt::Dbo::Session& session, const boost::filesystem::path& p);
|
static pointer create(Wt::Dbo::Session& session, const boost::filesystem::path& p);
|
||||||
|
|||||||
@@ -81,6 +81,12 @@ getJsonData(const std::string& mbid)
|
|||||||
std::string
|
std::string
|
||||||
extractLowLevelFeatures(const std::string& mbid)
|
extractLowLevelFeatures(const std::string& mbid)
|
||||||
{
|
{
|
||||||
|
if (boost::filesystem::exists("/storage/emeric/lms-dev/features/" + mbid))
|
||||||
|
{
|
||||||
|
std::ifstream ifs{std::string{"/storage/emeric/lms-dev/features/" + mbid}.c_str()};
|
||||||
|
return std::string {std::istreambuf_iterator<char>{ifs}, std::istreambuf_iterator<char>{}};
|
||||||
|
}
|
||||||
|
|
||||||
return getJsonData(mbid);
|
return getJsonData(mbid);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -106,10 +106,10 @@ void
|
|||||||
FeaturesScannerAddon::updateSearcher()
|
FeaturesScannerAddon::updateSearcher()
|
||||||
{
|
{
|
||||||
Wt::Dbo::Transaction transaction {_db.getSession()};
|
Wt::Dbo::Transaction transaction {_db.getSession()};
|
||||||
auto tracks {Database::Track::getAllWithFeatures(_db.getSession())};
|
std::vector<Database::IdType> trackIds {Database::Track::getAllIdsWithFeatures(_db.getSession())};
|
||||||
transaction.commit();
|
transaction.commit();
|
||||||
|
|
||||||
if (tracks.empty())
|
if (trackIds.empty())
|
||||||
{
|
{
|
||||||
LMS_LOG(DBUPDATER, INFO) << "No track suitable for features similarity clustering";
|
LMS_LOG(DBUPDATER, INFO) << "No track suitable for features similarity clustering";
|
||||||
std::atomic_store(&_searcher, std::shared_ptr<FeaturesSearcher>{});
|
std::atomic_store(&_searcher, std::shared_ptr<FeaturesSearcher>{});
|
||||||
|
|||||||
@@ -68,7 +68,7 @@ getFeatureInfoMapNbDimensions(const FeatureInfoMap& featureInfoMap)
|
|||||||
|
|
||||||
static
|
static
|
||||||
boost::optional<SOM::InputVector>
|
boost::optional<SOM::InputVector>
|
||||||
getInputVectorFromTrack(const Database::Track::pointer& track, const FeatureInfoMap& featuresInfo, std::size_t nbDimensions)
|
getInputVectorFromTrack(Wt::Dbo::Session& session, Database::IdType trackId, const FeatureInfoMap& featuresInfo, std::size_t nbDimensions)
|
||||||
{
|
{
|
||||||
boost::optional<SOM::InputVector> res {SOM::InputVector {nbDimensions}};
|
boost::optional<SOM::InputVector> res {SOM::InputVector {nbDimensions}};
|
||||||
|
|
||||||
@@ -76,6 +76,12 @@ getInputVectorFromTrack(const Database::Track::pointer& track, const FeatureInfo
|
|||||||
for (auto itFeatureInfo : featuresInfo)
|
for (auto itFeatureInfo : featuresInfo)
|
||||||
features[itFeatureInfo.first] = {};
|
features[itFeatureInfo.first] = {};
|
||||||
|
|
||||||
|
Wt::Dbo::Transaction transaction {session};
|
||||||
|
|
||||||
|
Database::Track::pointer track {Database::Track::getById(session, trackId)};
|
||||||
|
if (!track)
|
||||||
|
return res;
|
||||||
|
|
||||||
if (!track->getTrackFeatures()->getFeatures(features))
|
if (!track->getTrackFeatures()->getFeatures(features))
|
||||||
return res;
|
return res;
|
||||||
|
|
||||||
@@ -115,7 +121,7 @@ getInputVectorWeights(const FeatureInfoMap& featuresInfo, std::size_t nbDimensio
|
|||||||
|
|
||||||
FeaturesSearcher::FeaturesSearcher(Wt::Dbo::Session& session, bool& stopRequested)
|
FeaturesSearcher::FeaturesSearcher(Wt::Dbo::Session& session, bool& stopRequested)
|
||||||
{
|
{
|
||||||
Wt::Dbo::Transaction transaction{session};
|
Wt::Dbo::Transaction transaction {session};
|
||||||
|
|
||||||
FeatureInfoMap featuresInfo {getFeatureInfoMap(session)};
|
FeatureInfoMap featuresInfo {getFeatureInfoMap(session)};
|
||||||
std::size_t nbDimensions {getFeatureInfoMapNbDimensions(featuresInfo)};
|
std::size_t nbDimensions {getFeatureInfoMapNbDimensions(featuresInfo)};
|
||||||
@@ -123,31 +129,33 @@ FeaturesSearcher::FeaturesSearcher(Wt::Dbo::Session& session, bool& stopRequeste
|
|||||||
LMS_LOG(SIMILARITY, DEBUG) << "Features dimension = " << nbDimensions;
|
LMS_LOG(SIMILARITY, DEBUG) << "Features dimension = " << nbDimensions;
|
||||||
|
|
||||||
LMS_LOG(SIMILARITY, DEBUG) << "Getting Tracks with features...";
|
LMS_LOG(SIMILARITY, DEBUG) << "Getting Tracks with features...";
|
||||||
auto tracks {Database::Track::getAllWithFeatures(session)};
|
std::vector<Database::IdType> trackIds {Database::Track::getAllIdsWithFeatures(session)};
|
||||||
LMS_LOG(SIMILARITY, DEBUG) << "Getting Tracks with features DONE";
|
LMS_LOG(SIMILARITY, DEBUG) << "Getting Tracks with features DONE";
|
||||||
|
|
||||||
std::vector<SOM::InputVector> samples;
|
transaction.commit();
|
||||||
std::vector<Database::IdType> tracksIds;
|
|
||||||
|
|
||||||
samples.reserve(tracks.size());
|
std::vector<SOM::InputVector> samples;
|
||||||
tracksIds.reserve(tracks.size());
|
std::vector<Database::IdType> samplesTrackIds;
|
||||||
|
|
||||||
|
samples.reserve(trackIds.size());
|
||||||
|
samplesTrackIds.reserve(trackIds.size());
|
||||||
|
|
||||||
LMS_LOG(SIMILARITY, DEBUG) << "Extracting features...";
|
LMS_LOG(SIMILARITY, DEBUG) << "Extracting features...";
|
||||||
for (const Database::Track::pointer& track : tracks)
|
for (Database::IdType trackId : trackIds)
|
||||||
{
|
{
|
||||||
if (stopRequested)
|
if (stopRequested)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
boost::optional<SOM::InputVector> inputVector {getInputVectorFromTrack(track, featuresInfo, nbDimensions)};
|
boost::optional<SOM::InputVector> inputVector {getInputVectorFromTrack(session, trackId, featuresInfo, nbDimensions)};
|
||||||
|
if (!inputVector)
|
||||||
|
continue;
|
||||||
|
|
||||||
samples.emplace_back(std::move(*inputVector));
|
samples.emplace_back(std::move(*inputVector));
|
||||||
tracksIds.emplace_back(track.id());
|
samplesTrackIds.emplace_back(trackId);
|
||||||
}
|
}
|
||||||
LMS_LOG(SIMILARITY, DEBUG) << "Extracting features DONE";
|
LMS_LOG(SIMILARITY, DEBUG) << "Extracting features DONE";
|
||||||
|
|
||||||
transaction.commit();
|
if (samples.empty())
|
||||||
|
|
||||||
if (tracksIds.empty())
|
|
||||||
{
|
{
|
||||||
LMS_LOG(SIMILARITY, INFO) << "Nothing to classify!";
|
LMS_LOG(SIMILARITY, INFO) << "Nothing to classify!";
|
||||||
return;
|
return;
|
||||||
@@ -191,12 +199,13 @@ FeaturesSearcher::FeaturesSearcher(Wt::Dbo::Session& session, bool& stopRequeste
|
|||||||
|
|
||||||
const SOM::Position position {network.getClosestRefVectorPosition(samples[i])};
|
const SOM::Position position {network.getClosestRefVectorPosition(samples[i])};
|
||||||
|
|
||||||
trackPositions[tracksIds[i]].insert(position);
|
trackPositions[samplesTrackIds[i]].insert(position);
|
||||||
}
|
}
|
||||||
|
|
||||||
LMS_LOG(SIMILARITY, DEBUG) << "Classifying tracks DONE";
|
LMS_LOG(SIMILARITY, DEBUG) << "Classifying tracks DONE";
|
||||||
|
|
||||||
init(session, std::move(network), std::move(trackPositions));
|
init(session, std::move(network), std::move(trackPositions));
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
FeaturesSearcher::FeaturesSearcher(Wt::Dbo::Session& session, FeaturesCache cache)
|
FeaturesSearcher::FeaturesSearcher(Wt::Dbo::Session& session, FeaturesCache cache)
|
||||||
@@ -269,12 +278,12 @@ FeaturesSearcher::dump(Wt::Dbo::Session& session, std::ostream& os) const
|
|||||||
if (!track)
|
if (!track)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
os << "\t - " << track->getName() << " - ";
|
os << "\t";
|
||||||
if (track->getArtist())
|
if (track->getArtist())
|
||||||
os << track->getArtist()->getName() << " - ";
|
os << track->getArtist()->getName() << " - ";
|
||||||
if (track->getRelease())
|
if (track->getRelease())
|
||||||
os << track->getRelease()->getName();
|
os << track->getRelease()->getName() << " - ";
|
||||||
os << std::endl;
|
os << track->getName() << std::endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -100,16 +100,20 @@ int main(int argc, char *argv[])
|
|||||||
std::cout << "Getting all features..." << std::endl;
|
std::cout << "Getting all features..." << std::endl;
|
||||||
Wt::Dbo::Transaction transaction(db.getSession());
|
Wt::Dbo::Transaction transaction(db.getSession());
|
||||||
|
|
||||||
auto tracks = Database::Track::getAllWithFeatures(db.getSession(), nbTracks);
|
std::vector<Database::IdType> trackIds {Database::Track::getAllIdsWithFeatures(db.getSession(), nbTracks)};
|
||||||
|
|
||||||
nbTracks = tracks.size();
|
nbTracks = trackIds.size();
|
||||||
std::cout << "Getting features DONE (" << nbTracks << " tracks)" << std::endl;
|
std::cout << "Getting features DONE (" << nbTracks << " tracks)" << std::endl;
|
||||||
|
|
||||||
std::cout << "Reading features..." << std::endl;
|
std::cout << "Reading features..." << std::endl;
|
||||||
std::vector<SOM::InputVector> tracksFeatures;
|
std::vector<SOM::InputVector> tracksFeatures;
|
||||||
|
|
||||||
for (const auto& track : tracks)
|
for (Database::IdType trackId : trackIds)
|
||||||
{
|
{
|
||||||
|
Database::Track::pointer track {Database::Track::getById(db.getSession(), trackId)};
|
||||||
|
if (!track)
|
||||||
|
continue;
|
||||||
|
|
||||||
SOM::InputVector features {nbDims};
|
SOM::InputVector features {nbDims};
|
||||||
if (!getTrackFeatures(db.getSession(), track, featuresSettings, features))
|
if (!getTrackFeatures(db.getSession(), track, featuresSettings, features))
|
||||||
continue;
|
continue;
|
||||||
@@ -163,8 +167,12 @@ int main(int argc, char *argv[])
|
|||||||
std::cout << "Classifying tracks..." << std::endl;
|
std::cout << "Classifying tracks..." << std::endl;
|
||||||
|
|
||||||
SOM::Matrix< std::vector<Database::Track::pointer> > tracksMap(width, height);
|
SOM::Matrix< std::vector<Database::Track::pointer> > tracksMap(width, height);
|
||||||
for (auto track : tracks)
|
for (Database::IdType trackId : trackIds)
|
||||||
{
|
{
|
||||||
|
Database::Track::pointer track {Database::Track::getById(db.getSession(), trackId)};
|
||||||
|
if (!track)
|
||||||
|
continue;
|
||||||
|
|
||||||
SOM::InputVector features {nbDims};
|
SOM::InputVector features {nbDims};
|
||||||
if (!getTrackFeatures(db.getSession(), track, featuresSettings, features))
|
if (!getTrackFeatures(db.getSession(), track, featuresSettings, features))
|
||||||
continue;
|
continue;
|
||||||
@@ -194,8 +202,12 @@ int main(int argc, char *argv[])
|
|||||||
}
|
}
|
||||||
|
|
||||||
// For each track, get the nearest tracks
|
// For each track, get the nearest tracks
|
||||||
for (const auto& track : tracks)
|
for (Database::IdType trackId : trackIds)
|
||||||
{
|
{
|
||||||
|
Database::Track::pointer track {Database::Track::getById(db.getSession(), trackId)};
|
||||||
|
if (!track)
|
||||||
|
continue;
|
||||||
|
|
||||||
SOM::InputVector features {nbDims};
|
SOM::InputVector features {nbDims};
|
||||||
if (!getTrackFeatures(db.getSession(), track, featuresSettings, features))
|
if (!getTrackFeatures(db.getSession(), track, featuresSettings, features))
|
||||||
continue;
|
continue;
|
||||||
|
|||||||
Reference in New Issue
Block a user