Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add utils for supporting rerun panel plugin #4876

Merged
merged 4 commits into from
Oct 4, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion app/packages/state/src/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ import {
RecordSource,
Store,
} from "relay-runtime";
import { State } from "./recoil";
import { ModalSample, State } from "./recoil";

export const deferrer =
(initialized: MutableRefObject<boolean>) =>
Expand Down Expand Up @@ -105,6 +105,7 @@ export const getStandardizedUrls = (
urls:
| readonly { readonly field: string; readonly url: string }[]
| { [field: string]: string }
| ModalSample["urls"]
) => {
if (!Array.isArray(urls)) {
return urls;
Expand Down
79 changes: 72 additions & 7 deletions app/packages/utilities/src/schema.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ const SCHEMA: schema.Schema = {
"fiftyone.core.odm.embedded_document.DynamicEmbeddedDocument",
ftype: "fiftyone.core.fields.EmbeddedDocumentField",
info: {},
name: "top",
name: "embedded",
path: "embedded",
subfield: null,
fields: {
Expand All @@ -30,7 +30,7 @@ const SCHEMA: schema.Schema = {
ftype: "fiftyone.core.fields.EmbeddedDocumentField",
info: {},
name: "field",
path: "field",
path: "embedded.field",
subfield: null,
},
},
Expand All @@ -42,7 +42,7 @@ const SCHEMA: schema.Schema = {
"fiftyone.core.odm.embedded_document.DynamicEmbeddedDocument",
ftype: "fiftyone.core.fields.EmbeddedDocumentField",
info: {},
name: "top",
name: "embeddedWithDbFields",
path: "embeddedWithDbFields",
subfield: null,
fields: {
Expand All @@ -54,15 +54,15 @@ const SCHEMA: schema.Schema = {
ftype: "fiftyone.core.fields.EmbeddedDocumentField",
info: {},
name: "sample_id",
path: "sample_id",
path: "embeddedWithDbFields.sample_id",
subfield: null,
},
},
},
};

describe("schema", () => {
describe("getCls ", () => {
describe("getCls", () => {
it("should get top level cls", () => {
expect(schema.getCls("top", SCHEMA)).toBe("TopLabel");
});
Expand All @@ -79,7 +79,7 @@ describe("schema", () => {
});
});

describe("getFieldInfo ", () => {
describe("getFieldInfo", () => {
it("should get top level field info", () => {
expect(schema.getFieldInfo("top", SCHEMA)).toEqual({
...SCHEMA.top,
Expand All @@ -89,7 +89,7 @@ describe("schema", () => {

it("should get embedded field info", () => {
expect(schema.getFieldInfo("embedded.field", SCHEMA)).toEqual({
...SCHEMA.embedded.fields.field,
...SCHEMA.embedded.fields!.field,
pathWithDbField: "",
});
});
Expand All @@ -109,4 +109,69 @@ describe("schema", () => {
expect(field?.pathWithDbField).toBe("embeddedWithDbFields._sample_id");
});
});

describe("getFieldsWithEmbeddedDocType", () => {
it("should get all fields with embeddedDocType at top level", () => {
expect(
schema.getFieldsWithEmbeddedDocType(
SCHEMA,
"fiftyone.core.labels.TopLabel"
)
).toEqual([SCHEMA.top]);
});

it("should get all fields with embeddedDocType in nested fields", () => {
expect(
schema.getFieldsWithEmbeddedDocType(
SCHEMA,
"fiftyone.core.labels.EmbeddedLabel"
)
).toEqual([
SCHEMA.embedded.fields!.field,
SCHEMA.embeddedWithDbFields.fields!.sample_id,
]);
});

it("should return empty array if embeddedDocType does not exist", () => {
expect(
schema.getFieldsWithEmbeddedDocType(SCHEMA, "nonexistentDocType")
).toEqual([]);
});

it("should return empty array for empty schema", () => {
expect(schema.getFieldsWithEmbeddedDocType({}, "anyDocType")).toEqual([]);
});
});

describe("doesSchemaContainEmbeddedDocType", () => {
it("should return true if embeddedDocType exists at top level", () => {
expect(
schema.doesSchemaContainEmbeddedDocType(
SCHEMA,
"fiftyone.core.labels.TopLabel"
)
).toBe(true);
});

it("should return true if embeddedDocType exists in nested fields", () => {
expect(
schema.doesSchemaContainEmbeddedDocType(
SCHEMA,
"fiftyone.core.labels.EmbeddedLabel"
)
).toBe(true);
});

it("should return false if embeddedDocType does not exist", () => {
expect(
schema.doesSchemaContainEmbeddedDocType(SCHEMA, "nonexistentDocType")
).toBe(false);
});

it("should return false for empty schema", () => {
expect(schema.doesSchemaContainEmbeddedDocType({}, "anyDocType")).toBe(
false
);
});
});
});
40 changes: 40 additions & 0 deletions app/packages/utilities/src/schema.ts
Original file line number Diff line number Diff line change
Expand Up @@ -51,3 +51,43 @@ export function getCls(fieldPath: string, schema: Schema): string | undefined {

return field.embeddedDocType.split(".").slice(-1)[0];
}

export function getFieldsWithEmbeddedDocType(
schema: Schema,
embeddedDocType: string
): Field[] {
const result: Field[] = [];

function recurse(schema: Schema) {
for (const field of Object.values(schema ?? {})) {
if (field.embeddedDocType === embeddedDocType) {
result.push(field);
}
if (field.fields) {
recurse(field.fields);
}
}
}

recurse(schema);
return result;
}

export function doesSchemaContainEmbeddedDocType(
schema: Schema,
embeddedDocType: string
): boolean {
function recurse(schema: Schema): boolean {
return Object.values(schema ?? {}).some((field) => {
if (field.embeddedDocType === embeddedDocType) {
return true;
}
if (field.fields) {
return recurse(field.fields);
}
return false;
});
}

return recurse(schema);
}
sashankaryal marked this conversation as resolved.
Show resolved Hide resolved
2 changes: 2 additions & 0 deletions fiftyone/server/metadata.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
import fiftyone.core.labels as fol
from fiftyone.core.collections import SampleCollection
from fiftyone.utils.utils3d import OrthographicProjectionMetadata
from fiftyone.utils.rerun import RrdFile

import fiftyone.core.media as fom

Expand All @@ -33,6 +34,7 @@
fol.Heatmap: "map_path",
fol.Segmentation: "mask_path",
OrthographicProjectionMetadata: "filepath",
RrdFile: "filepath",
}
_FFPROBE_BINARY_PATH = shutil.which("ffprobe")

Expand Down
25 changes: 25 additions & 0 deletions fiftyone/utils/rerun.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
"""
Utilities for working with `Rerun <https://rerun.io/>`_.
| Copyright 2017-2024, Voxel51, Inc.
| `voxel51.com <https://voxel51.com/>`_
|
"""

import fiftyone.core.fields as fof
import fiftyone.core.labels as fol
from fiftyone.core.odm import DynamicEmbeddedDocument


class RrdFile(DynamicEmbeddedDocument, fol._HasMedia):
"""Class for storing a rerun data (rrd) file and its associated metadata.
Args:
filepath (None): the path to the rrd file
version (None): the version of the rrd file
"""

_MEDIA_FIELD = "filepath"

filepath = fof.StringField()
version = fof.StringField()
sashankaryal marked this conversation as resolved.
Show resolved Hide resolved
Loading