Skip to content

Feat/add prediction artifact and upload method #292

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

Open
wants to merge 29 commits into
base: main
Choose a base branch
from

Conversation

j279li
Copy link
Contributor

@j279li j279li commented Jun 3, 2025

Summary of Changes

This PR introduces a new Prediction artifact, and an associated upload method

New Features

  • Prediction Artifact (Predictions)

    • Added a new Predictions model to represent prediction artifacts as Zarr archives.
    • Includes validators to ensure Zarr structure consistency.
    • Provides convenient properties (columns, dtypes, n_rows, etc.) for quick data exploration.
    • Methods for setting/getting prediction values, creating Zarr archives from dicts, and uploading to the Polaris Hub.
  • Upload API (upload_prediction)

    • Added a new upload_prediction method in PolarisHubClient for uploading prediction artifacts.
    • Handles metadata, manifest, and archive uploads with progress tracking.

@j279li j279li self-assigned this Jun 3, 2025
@j279li j279li added the feature Annotates any PR that adds new features; Used in the release process label Jun 3, 2025
Copy link
Contributor

@jstlaurent jstlaurent left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Left some comments about the model structure. We can chat about it some more if you'd like. 😄

Copy link
Collaborator

@cwognum cwognum left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice work, @j279li !

@j279li j279li force-pushed the feat/predictions-submission branch from fe10e34 to db77f00 Compare June 5, 2025 15:23
@j279li
Copy link
Contributor Author

j279li commented Jun 5, 2025

@jstlaurent I've encountered circular import issues with BenchmarkV2Specification, since the benchmark package already imports from the evaluate package. To work around this, I moved the Predictions class into its own package for now. Would that be alright, or do you have other ideas?

@j279li j279li marked this pull request as ready for review June 11, 2025 13:38
Copy link
Contributor

@danielpeng1 danielpeng1 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice job!

@cwognum
Copy link
Collaborator

cwognum commented Jun 17, 2025

@j279li Ping me once this is ready for another review! Happy to take a look!

@j279li
Copy link
Contributor Author

j279li commented Jun 17, 2025

@j279li Ping me once this is ready for another review! Happy to take a look!

Hey @cwognum, It's basically good for another review! Predictions upload should be fully functional now.

Copy link
Contributor

@Andrewq11 Andrewq11 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks again, @j279li 💪 I've left a few comments we should probably take a look at. It's coming along nicely!

Comment on lines 98 to 133
if len(data) > 0:
# Extract a sample value to determine the type
if isinstance(data, (list, tuple)):
sample_value = data[0]
elif hasattr(data, "__getitem__"):
try:
sample_value = data[0]
except (IndexError, TypeError):
sample_value = None
else:
sample_value = None

if sample_value is not None:
sample_type_name = type(sample_value).__name__
if sample_type_name == "Mol" and "rdkit" in str(type(sample_value).__module__):
codec_kwargs["object_codec"] = RDKitMolCodec()
codec_kwargs["dtype"] = object
elif sample_type_name == "AtomArray" and "biotite" in str(
type(sample_value).__module__
):
codec_kwargs["object_codec"] = AtomArrayCodec()
codec_kwargs["dtype"] = object
elif annotation.dtype == np.dtype(object):
# For other object types, use object dtype
codec_kwargs["dtype"] = object

# Create the array in the Zarr archive
if "object_codec" in codec_kwargs:
# For object codecs, we need to create a numpy object array first
# Use np.empty to avoid numpy trying to convert AtomArrays to numpy arrays
data_array = np.empty(len(data), dtype=object)
for i, item in enumerate(data):
data_array[i] = item
root.array(col, data=data_array, **codec_kwargs)
else:
root.array(col, data=data, **codec_kwargs)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'll need some more context on this block here. Let's chat about this a little further once @cwognum has had a chance to look at it.

Copy link
Collaborator

@cwognum cwognum left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi @j279li, sorry for not spotting any of this on my first review. I've been out of the loop on recent changes to Polaris, so I may also be missing some context here.

We're making good progress, but I think we should take another look at how we've done things for competitions. Specifically, I would like us to revisit the user-facing API as well as the validation of the Predictions class.

Happy to find some chat to about this tomorrow!

Comment on lines 94 to 95
if hasattr(self.benchmark.dataset, "annotations") and col in self.benchmark.dataset.annotations:
annotation = self.benchmark.dataset.annotations[col]
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Change requested: Rather than using the dataset annotations as the source of truth, we should use the dataset's Zarr archive to determine the dtype. Each prediction column should match the corresponding dataset column.

def zarr_root_path(self) -> str:
return self._zarr_root_path

def _create_zarr_from_predictions(self):
Copy link
Collaborator

@cwognum cwognum Jun 18, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Change requested: I think this method can be simplified a lot. It can copy the configuration (dtype, codec, etc.) of each array from the benchmark's dataset's Zarr Root and infer the array size from the test split.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
feature Annotates any PR that adds new features; Used in the release process
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants