Skip to content

Instantly share code, notes, and snippets.

@kylemcdonald
Created November 20, 2017 23:34
Show Gist options
  • Select an option

  • Save kylemcdonald/36fc527b18a41c06024863fd6c6f2773 to your computer and use it in GitHub Desktop.

Select an option

Save kylemcdonald/36fc527b18a41c06024863fd6c6f2773 to your computer and use it in GitHub Desktop.
Export visualizations for comparing UMAP to t-SNE.
#include "ofMain.h"
template <class T>
vector<T> loadEmbedding(string filename) {
vector<T> embedding;
ofBuffer embeddingBuffer = ofBufferFromFile(filename);
for(auto& line : embeddingBuffer.getLines()) {
if(line.size()) {
T x;
stringstream(line) >> x;
embedding.emplace_back(x);
}
}
return embedding;
}
void flip(vector<ofVec2f>& v, bool flip_x=false, bool flip_y=false) {
for(ofVec2f& x : v) {
if(flip_x) {
x.x = 1 - x.x;
}
if(flip_y) {
x.y = 1 - x.y;
}
}
}
float orientation_difference(vector<ofVec2f>& a, vector<ofVec2f>& b, ofVec2f pivot=ofVec2f(0.5, 0.5)) {
float sum = 0;
int n = a.size();
for(int i = 0; i < n; i++) {
float diff = (a[i] - pivot).angle(b[i] - pivot);
sum += diff;
}
return sum / n;
}
void rotate(vector<ofVec2f>& v, float angle, ofVec2f pivot=ofVec2f(0.5, 0.5)) {
for(ofVec2f& x : v) {
x.rotate(angle, pivot);
}
}
class ofApp : public ofBaseApp {
public:
vector<float> colors;
vector<ofVec2f> umap, tsne;
vector<ofImage> images;
ofTrueTypeFont font;
void setup() {
ofSetFrameRate(60);
ofBackground(0);
ofSetColor(0);
glPointSize(2);
ofEnableSmoothing();
ofEnableAlphaBlending();
font.load("Andale Mono.ttf", 32);
// tsne = loadEmbedding<ofVec2f>("tsne_embedding_subset.tsv");
// umap = loadEmbedding<ofVec2f>("umap_embedding_subset.tsv");
// for(int i = 0; i < umap.size(); i++) {
// images.emplace_back("zeros/" + ofToString(i) + ".png");
// }
colors = loadEmbedding<float>("y.tsv");
tsne = loadEmbedding<ofVec2f>("tsne_embedding.tsv");
umap = loadEmbedding<ofVec2f>("umap_embedding.tsv");
// flip(tsne, false, true);
// float angle = orientation_difference(tsne, umap);
// rotate(tsne, angle);
}
void update() {
}
void draw() {
float pad = 0.1;
float t = ofMap(sin(ofGetFrameNum() * TWO_PI / 128), -1, +1, 0, 1);
// float t = ofMap(sin(ofGetElapsedTimef()), -1, +1, 0, 1);
ofMesh mesh;
vector<ofVec2f> points;
mesh.setMode(OF_PRIMITIVE_POINTS);
int n = tsne.size();
for(int i = 0; i < n; i++) {
ofVec2f x = tsne[i].getInterpolated(umap[i], t);
mesh.addVertex(ofVec3f(x));
if(i < colors.size()) {
mesh.addColor(ofFloatColor::fromHsb(colors[i], 1, 1, .50));
}
points.push_back(x);
// x -= 0.5;
// x *= (1-pad) * ofGetWidth();
// x += ofGetWidth()/2;
// images[i].draw(x);
}
string text = t < 0.5 ? "t-SNE" : "UMAP";
ofSetColor(255);
font.drawString(text, 20, 60);
ofTranslate(ofGetWidth()/2, ofGetHeight()/2);
ofScale(ofGetWidth()*(1-pad), ofGetHeight()*(1-pad));
ofTranslate(-0.5, -0.5);
mesh.draw();
if(ofGetFrameNum() < 128) {
ofSaveScreen("screenshot-" + ofToString(ofGetFrameNum(), 4, '0') + ".png");
}
}
};
int main() {
ofSetupOpenGL(1024, 1024, OF_WINDOW);
ofRunApp(new ofApp());
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment