Skip to content

Commit

Permalink
support fetch image api
Browse files Browse the repository at this point in the history
  • Loading branch information
Nanguage committed Feb 21, 2024
1 parent 283809c commit db6065a
Show file tree
Hide file tree
Showing 6 changed files with 73 additions and 17 deletions.
6 changes: 3 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,8 @@ Online instance: [ufish-web](https://ufish-team.github.io/#/)
Usage example:

```Python
import numpy as np
ufish = await api.createWindow("https://ufish-team.github.io/")
img = np.random.rand(100, 100) # generate a random image
ufish = await api.createWindow("http://localhost:5173/")
img = await ufish.fetchImage("https://huggingface.co/datasets/NaNg/TestData/resolve/main/FISH_spots/MERFISH_1.tif")
out = await ufish.predict(img) # predict the spots
print(out.enhanced.shape)
print(out.spots.shape)
Expand All @@ -29,6 +28,7 @@ CLick to run it using: [web-python-console](https://nanguage.github.io/web-pytho
| `setInputImage` | `img: np.ndarray; name: string` | Set the input image. |
| `getOutput` | | Get the output of the model. It's an object contain `enhanced: np.ndarray` and `spots: np.ndarray` fields |
| `runPredict` | | Run the prediction. |
| `fetchImage` | `url: string` | Fetch an image from the given url, return a numpy array |

## Development

Expand Down
10 changes: 4 additions & 6 deletions public/plugins/ufish.imjoy.html
Original file line number Diff line number Diff line change
Expand Up @@ -123,8 +123,7 @@
self.enhanced_image = None # enhanced image
self.spots = None # spots

@staticmethod
def load_image_from_bytes(file_name, img_bytes):
async def load_image_from_bytes(self, file_name, img_bytes):
_file = io.BytesIO(img_bytes)
_file.name = file_name
if file_name.endswith(".tif") or file_name.endswith(".tiff"):
Expand All @@ -139,15 +138,14 @@
image = imageio.imread(_file)
return image

@staticmethod
def save_image_to_bytes(image):
async def save_image_to_bytes(self, image):
_file = io.BytesIO()
with tifffile.TiffWriter(_file) as tif:
tif.save(image)
return _file.getvalue()

async def view_img_from_bytes(self, file_name, bytes_):
image = self.load_image_from_bytes(file_name, bytes_)
image = await self.load_image_from_bytes(file_name, bytes_)
self.image = image
await self.viewer.view_image(image, name=file_name)
return image.shape
Expand All @@ -165,7 +163,7 @@
self.spots = coords
await self.viewer.add_points(
np.flip(coords, axis=1), name="spots")
enh_bytes = self.save_image_to_bytes(enh_img)
enh_bytes = await self.save_image_to_bytes(enh_img)
fake_csv_file = io.StringIO()
coords_csv = df.to_csv(fake_csv_file, index=False)
csv_bytes = fake_csv_file.getvalue().encode()
Expand Down
7 changes: 3 additions & 4 deletions public/scripts/demo.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import numpy as np
ufish = await api.createWindow("https://ufish-team.github.io/")
img = np.random.rand(100, 100) # generate a random image
ufish = await api.createWindow("http://localhost:5173/")
img = await ufish.fetchImage("https://huggingface.co/datasets/NaNg/TestData/resolve/main/FISH_spots/MERFISH_1.tif")
out = await ufish.predict(img) # predict the spots
print(out.enhanced.shape)
print(out.spots.shape)
print(out.spots.shape)
12 changes: 11 additions & 1 deletion src/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -67,14 +67,24 @@ async function createApi() {
return await getOutput()
}

async function fetchImage(url: string) {
await waitRunable()
const runStore = useRunStore()
runStore.setImageUrl(url)
const arr = await runStore.getFetchedImage()
const res = removeNpArrProxy(arr)
return res
}

return {
"run": async () => {},
"run": async () => {await waitRunable()},
"setup": setup,
"waitReady": waitRunable,
"runPredict": run,
"setInputImage": setInputImage,
"getOutput": getOutput,
"predict": predict,
"fetchImage": fetchImage,
}
}

Expand Down
22 changes: 22 additions & 0 deletions src/stores/run.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,11 @@ export async function waitOutputGetable() {
await waitState(() => store.outputGetable, true);
}

export async function waitFetchGetable() {
const store = useRunStore();
await waitState(() => store.fetchGetable, true);
}

type ApiInput = {
data: object,
name: string,
Expand All @@ -38,6 +43,9 @@ export const useRunStore = defineStore("run", {
inputImage: null as ApiInput | null,
output: null as ApiOutput | null,
outputGetable: false,
imageUrl: null as string | null,
fetchedImage: null as object | null,
fetchGetable: false,
}),
actions: {
async waitRunable() {
Expand Down Expand Up @@ -66,5 +74,19 @@ export const useRunStore = defineStore("run", {
await waitOutputGetable();
return this.output;
},
setImageUrl(url: string | null) {
this.imageUrl = url;
if (url !== null) {
this.fetchGetable = false;
}
},
setFetchedImage(image: object | null) {
this.fetchedImage = image;
this.fetchGetable = true;
},
async getFetchedImage() {
await waitFetchGetable();
return this.fetchedImage;
}
}
})
33 changes: 30 additions & 3 deletions src/views/PredictView.vue
Original file line number Diff line number Diff line change
Expand Up @@ -211,10 +211,10 @@ export default {
fileInput.click()
}
async function loadExample() {
async function loadFromUrl(url: string) {
loadingData.value = true
if (plugin.value !== null) {
const res = await fetch(test_data_url)
const res = await fetch(url)
if (!res.ok) {
loadingData.value = false
runInfoText.value = `Failed to load example image, status: ${res.status}`
Expand All @@ -230,15 +230,42 @@ export default {
hasError.value = false
output.value = null
} else {
setTimeout(loadExample, 1000)
setTimeout(() => loadFromUrl(url), 1000)
}
}
const loadExample = () => loadFromUrl(test_data_url)
async function download() {
downloadBlob(output.value.enhanced, "enhanced.tif", "image/tiff")
downloadBlob(output.value.coords, "coords.csv", "text/csv;charset=utf-8;")
}
async function fetchImageFromUrl(url: string) {
const res = await fetch(url)
if (!res.ok) {
throw new Error(`Failed to fetch image from ${url}, status: ${res.status}`)
}
const data = await res.arrayBuffer()
const fileName = url.split('/').pop()
const arr = await plugin.value.load_image_from_bytes(fileName, data)
return arr
}
watch(() => runStore.imageUrl, async (newVal) => {
if (newVal !== null) {
try {
const arr = await fetchImageFromUrl(newVal)
runStore.setFetchedImage(arr)
runStore.setImageUrl(null)
} catch (error) {
console.log(error)
runStore.setFetchedImage(null)
runStore.setImageUrl(null)
}
}
})
return {
plugin,
run,
Expand Down

0 comments on commit db6065a

Please sign in to comment.