Skip to content

Commit

Permalink
initial commit
Browse files Browse the repository at this point in the history
  • Loading branch information
intern-william@nodeflux-67 committed Jun 26, 2022
1 parent b7c12fe commit 0e1151f
Show file tree
Hide file tree
Showing 11 changed files with 261 additions and 75 deletions.
4 changes: 3 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1,2 +1,4 @@
env/*
*__pycache__*
*__pycache__*
*.ipynb_checkpoints*
*.pickle*
10 changes: 10 additions & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
FROM python:3.9.13-slim

ENV DEBIAN_FRONTEND=noninteractive

RUN apt-get update -qq && \
apt-get install -y git vim libgtk2.0-dev zip unzip && \
rm -rf /var/cache/apk/*

COPY requirements.txt /
RUN pip --no-cache-dir install -r /requirements.txt
11 changes: 0 additions & 11 deletions app.py

This file was deleted.

10 changes: 10 additions & 0 deletions app_dash.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import dash
import config

app = dash.Dash(__name__, use_pages=True)
app.layout = dash.html.Div([
dash.page_container
])

if __name__ == '__main__':
app.run_server(host=config.host, port=config.port['dash'])
49 changes: 49 additions & 0 deletions app_flask.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
import fiftyone as fo
from flask import Flask, render_template, request, redirect, url_for
import config, utils

app = Flask(__name__)
dataset = fo.Dataset()
session = None

@app.route('/fiftyone/<name>', methods=['GET'])
def preview_fiftyone(name):
return redirect(f'{config.url}:{config.port["fiftyone"]}/datasets/{name}')

@app.route('/embedding/<name>', methods=['GET'])
def preview_embedding(name):
return redirect(f'{config.url}:{config.port["dash"]}/embedding/{name}')

@app.route('/compute', methods=['POST'])
def compute():
data = request.get_json()
name = data['name']

dataset = fo.load_dataset(name)
df = utils.create_dataframe(dataset)
save_path = f'{name}.pickle'
df.to_pickle(save_path)

print(f'Saved computation to {save_path}')
return '', 204

@app.route('/fiftyone/update', methods=['POST'])
def fiftyone_load():
data = request.get_json()
name = data['name']
ids = data['ids']

global dataset, session
dataset = fo.load_dataset(name)
stage = fo.Select('')
stage.sample_ids.clear()
for id in ids: stage.sample_ids.append(id)
view = dataset.add_stage(stage)
session.view = view

print(f'Updated view of dataset {name} to {len(ids)} samples.')
return '', 204

if __name__ == '__main__':
session = fo.launch_app(dataset, address=config.address, port=config.port['fiftyone'], remote=True)
app.run(host=config.host, port=config.port['flask'])
9 changes: 9 additions & 0 deletions config.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
port = {
'flask' : 6000,
'fiftyone' : 6002,
'dash' : 6001,
}

host = address = ip = '0.0.0.0'

url = 'http://192.168.103.67'
11 changes: 0 additions & 11 deletions pages/display.py

This file was deleted.

131 changes: 91 additions & 40 deletions pages/embedding.py
Original file line number Diff line number Diff line change
@@ -1,48 +1,99 @@
import fiftyone as fo
import fiftyone.brain as fob
import dash
import pandas as pd
import math

def compute_embeddings(dataset):
return fob.compute_visualization(
dataset,
num_dims=2,
brain_key="image_embeddings",
verbose=True,
seed=51,
patches_field="ground_truth"
).points

def create_dataframe(dataset):
embeddings = compute_embeddings(dataset)

df = pd.DataFrame(columns=['index', 'uniqueness', 'label','sqrt_area','embeddings_x', 'embeddings_y'])

index = 0
for sample in dataset:
for detection in sample.ground_truth.detections:
print(detection)
df.loc[index] = [index, sample.uniqueness, detection.label, math.sqrt(detection.area), embeddings[index,0], embeddings[index, 1]]
index += 1

return df
import plotly.express as px
import plotly.graph_objects as go
import requests
import os
import config

def create_figure(df, min_uniqueness, max_uniqueness, min_sqrt_area, max_sqrt_area):
mask = (df['uniqueness'] >= min_uniqueness) & (df['uniqueness'] <= max_uniqueness) & (df['sqrt_area'] >= min_sqrt_area) & (df['sqrt_area'] <= max_sqrt_area)
fig = px.scatter(df[mask], x='embeddings_x', y='embeddings_y', color='label', size='sqrt_area', custom_data=['id'], hover_data=['uniqueness'])
figure = go.FigureWidget(fig)
figure.update_layout(
autosize=True,
width=1080,
height=566,
)
return figure

df = None

def main(name):
if name not in fo.list_datasets():
message = f'Dataset {name} is not in list.'
else:
dataset = fo.load_dataset(name)
df = create_dataframe(dataset)
df.to_pickle(name)
message = 'Saved embedding to {name}.'

print(message)
return message

import dash

file_path = f'{name}.pickle'
if not os.path.exists(file_path): requests.post(url=f'{config.url}:{config.port["flask"]}/compute', json={'name':name})

global df
df = pd.read_pickle(file_path)
uniqueness_range = (0, 1)
sqrt_area_range = (0, df['sqrt_area'].max())

figure = create_figure(df, uniqueness_range[0], uniqueness_range[1], sqrt_area_range[0], sqrt_area_range[1])

return dash.html.Div(children=[
dash.html.H3('Embedding Visualization'),
dash.dcc.Graph(
id='graph',
figure=figure
),
dash.html.P(f'{name}', id='name'),
dash.html.P(id='num_sample'),
dash.html.P('Filter by uniqueness:'),
dash.dcc.RangeSlider(
id='uniqueness-slider',
min=0, max=1, step=0.001,
marks={0: '0', 1: '1'},
value=[0, 1]
),
dash.html.P('Filter by sqrt area:'),
dash.dcc.RangeSlider(
id='sqrt-area-slider',
min=0, max=df['sqrt_area'].max(), step=df['sqrt_area'].max()/1000,
marks={0: '0', df['sqrt_area'].max(): f'{df["sqrt_area"].max()}'},
value=[0, df['sqrt_area'].max()]
),
])

@dash.callback(
dash.Output(component_id='graph', component_property='figure'),
dash.Input(component_id='uniqueness-slider', component_property='value'),
dash.Input(component_id='sqrt-area-slider', component_property='value'),
)
def update_figure(uniqueness_slider_range, sqrt_area_slider_range):
global_uniqueness_range = uniqueness_slider_range
global_sqrt_area_range = sqrt_area_slider_range
figure = create_figure(df, global_uniqueness_range[0], global_uniqueness_range[1], global_sqrt_area_range[0], global_sqrt_area_range[1])
print(f'Updated uniquesness range to {global_uniqueness_range}')
print(f'Updated sqrt area range to {global_sqrt_area_range}')
return figure

@dash.callback(
dash.Output(component_id='num_sample', component_property='children'),
dash.Input(component_id='name', component_property='children'),
dash.Input(component_id='graph', component_property='selectedData')
)
def update(name, input_value):
print(name, input_value)
if input_value is not None:
ids = set()
points = input_value['points']
for point in points:
id = point['customdata'][0]
ids.add(id)
ids = list(ids)
requests.post(
url = f'{config.url}:{config.port["flask"]}/fiftyone/update',
json = {
'name' : name,
'ids' : ids
}
)
return f'Callback: {input_value}'

dash.register_page(__name__, path_template="/embedding/<name>")

def layout(name=None):
print(f'Computing embedding for {name}')
print(f'Dash embedding {name}')
if name is not None:
return main(name)
9 changes: 9 additions & 0 deletions requirements.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
Flask==2.1.2
dash==2.5.1
plotly==5.9.0
fiftyone==0.16.5
torch==1.11.0
torchvision==0.12.0
umap-learn==0.5.3
ipywidgetsipywidgets==7.7.1
pandas==1.4.3
41 changes: 41 additions & 0 deletions sender.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
import requests
import config

def get(url):
return requests.get(url)

def post(url, data):
requests.post(url=url, json=data)

def preview_fiftyone(name):
get(
url = f'{config.url}:{config.port["flask"]}/fiftyone/{name}'
)

def preview_embedding(name):
get(
url = f'{config.url}:{config.port["flask"]}/embedding/{name}'
)

def compute(name):
post(
url = f'{config.url}:{config.port["flask"]}/compute',
data = {
'name' : name
}
)

def fiftyone_load(name, ids):
post(
url = f'{config.url}:{config.port["flask"]}/fiftyone/load',
data = {
'name' : name,
'ids' : ids
}
)

if __name__ == '__main__':
compute('quickstart')
preview_embedding('quickstart')
preview_fiftyone('quickstart')
# fiftyone_load('quickstart', [''])
51 changes: 39 additions & 12 deletions utils.py
Original file line number Diff line number Diff line change
@@ -1,18 +1,45 @@
import fiftyone as fo
import fiftyone.brain as fob
import pandas as pd
import math

def create_quickstart():
import fiftyone.zoo as foz
return foz.load_zoo_dataset("quickstart")
def compute_embeddings(dataset):
return fob.compute_visualization(
dataset,
num_dims=2,
brain_key="image_embeddings",
verbose=True,
seed=51,
patches_field="ground_truth"
).points

def create(name):
return fo.Dataset(name)
def create_dataframe(dataset):
embeddings = compute_embeddings(dataset)

df = pd.DataFrame(columns=['id', 'uniqueness', 'label', 'area', 'sqrt_area','embeddings_x', 'embeddings_y'])

index = 0

def load(name):
return fo.load_dataset(name)
for sample in dataset:

def delete(name):
dataset = load(name)
dataset.delete()
id = sample.id

def ls():
print(fo.list_datasets())
try: uniqueness = sample.uniqueness
except: uniqueness = 0

for detection in sample.ground_truth.detections:

try: label = detection.label
except: label = ''

try: area = detection.area
except: area = 1

embeddings_x = embeddings[index, 0]
embeddings_y = embeddings[index, 1]

df.loc[index] = [id, uniqueness, label, area, math.sqrt(area), embeddings_x, embeddings_y]

index += 1

return df

0 comments on commit 0e1151f

Please sign in to comment.