spacr.qt.widgets.model_share¶
Add a local model to the zoo, and optionally share it on Hugging Face.
WHY THERE IS NO BUILT-IN TOKEN. Uploading to one account from every user’s machine would mean shipping a write token inside spaCR. A write token is not an upload permit: it can also rewrite and DELETE every model in that account, and anyone who installs spaCR can read it out of the package. So the upload uses the token belonging to whoever is running it:
huggingface-cli login, or the HF_TOKEN / HUGGING_FACE_HUB_TOKEN environment variable.
It publishes to SHARE_REPO when that token may write there – the
owner can grant that per person in the repository’s settings – and otherwise
to the uploader’s own namespace, which always works and is never destructive
to somebody else. Either way the model card carries the same table, so a
shared model is readable in the same terms as a bundled one.
Functions¶
|
The model card, carrying the same table every spaCR model card uses. |
|
Send a contribution folder through the central upload Space. |
|
Publish through the central endpoint. Returns its reply. |
|
|
|
A community target name as it appears in a repository id. |
|
A README for a new community dataset, in the layout this module writes. |
|
The dataset repository community training data for |
|
The short text shown beside Upload, asking for careful annotations. |
|
Send a contribution folder as a pull request. Returns its URL. |
|
Make sure the community dataset exists; create it with a README if not. |
|
The uploader's own Hugging Face token, or |
|
The community target a user-named image-and-mask dataset goes to. |
|
Pack a training-data folder into ONE uncompressed tar. Returns its path. |
|
Match an images folder to a masks folder by file name. |
|
Whether a |
|
A label mask file as a 2-D array. |
|
Which of spaCR's proposed plaques the contributor kept, edited or removed. |
|
Upload a checkpoint and its card. Returns the model page URL. |
|
A repository-safe folder name. |
|
Where this token may publish: the shared repo, or its own namespace. |
|
Lay a contribution out on disk exactly as the dataset README describes. |
|
Well boxes as YOLO label lines, |
Module Contents¶
- spacr.qt.widgets.model_share.card(fields: Dict[str, Any], filename: str, sha256: str, repo_id: str, folder: str) → str[source]¶
The model card, carrying the same table every spaCR model card uses.
- Parameters:
fields – the share form’s values:
display_name,kind,trained_on,notesand the metrics (f1,aji,dice,train_loss,val_lossand the rest); a missing value is shown as unstated.filename – file name of the checkpoint; also the heading when no
display_nameis given.sha256 – hex SHA-256 digest of the checkpoint, printed on the card.
repo_id – Hugging Face repository the model is published to; accepted but not written into the card.
folder – folder inside the repository that holds the checkpoint.
- spacr.qt.widgets.model_share.central_contribute(folder: Any, target: str) → str[source]¶
Send a contribution folder through the central upload Space.
For a contributor with no Hugging Face login: the folder goes to the Space (see
tools/model_upload_space/) as one uncompressed tar, and the Space checks it and opens the pull request with its own token. The Space accepts onlyfigures,plaquesandcommunity_<name>targets, aboutMAX_CONTRIBUTION_BYTES, the file typeswrite_contribution()writes, and every image paired with its mask or labels and its meta file.- Parameters:
folder – a folder
write_contribution()made.target – as for
community_repo(); sent as the name the Space resolves,figures,plaquesorcommunity_<name>.
- Returns:
the pull request’s URL.
- Raises:
RuntimeError – when no endpoint is configured, the folder is over the limit, or the Space refuses it (with the Space’s reason).
- spacr.qt.widgets.model_share.central_upload(path: str, fields: Dict[str, Any]) → str[source]¶
Publish through the central endpoint. Returns its reply.
Speaks the Gradio HTTP API directly with urllib rather than through gradio_client, because that package is not a spaCR dependency: when it was missing this raised, the caller fell back to the uploader’s own token, and the model went somewhere nobody was looking for it. A publish path that depends on an optional import is a publish path that silently does something else.
- Parameters:
path – local checkpoint file to upload.
fields – the share form’s values;
display_name,kind,trained_onandcontactare sent as their own arguments, the whole mapping as JSON, and a non-emptytrain_data_diris packed withpack_training_data()and uploaded too.
- spacr.qt.widgets.model_share.community_layout(target: str) → str[source]¶
"boxes"for figure pages with well boxes,"masks"for everything else.- Parameters:
target – as for
community_repo().
- spacr.qt.widgets.model_share.community_name(name: str) → str[source]¶
A community target name as it appears in a repository id.
- Parameters:
name – what the user or the caller calls the collection, e.g.
"Toxoplasma PV"; lower-cased, and every run of characters other thana-zand0-9becomes one underscore.
- spacr.qt.widgets.model_share.community_readme(target: str, *, purpose: str = '') → str[source]¶
A README for a new community dataset, in the layout this module writes.
- Parameters:
target – as for
community_repo().purpose – what the data will train, one sentence; a general sentence when empty.
- spacr.qt.widgets.model_share.community_repo(target: str) → str[source]¶
The dataset repository community training data for
targetgoes to.One dataset repository per collection, not folders of one repository: every spaCR training set on Hugging Face is its own dataset repository beside the model it trains, and each upload arrives on it as a pull request.
"figures"and"plaques"are Plaque Assay’s two; any other name iseinarolafsson/community_<name>.- Parameters:
target –
"figures","plaques", a name, or a fullowner/repoid (used as it is).
- spacr.qt.widgets.model_share.conscience_for(target: str) → str[source]¶
The short text shown beside Upload, asking for careful annotations.
Callers translate it with
tr().- Parameters:
target – as for
community_repo().
- spacr.qt.widgets.model_share.contribute(folder: Any, target: str, token: str | None = None) → str[source]¶
Send a contribution folder as a pull request. Returns its URL.
A pull request rather than a commit, whoever sends it: every contribution is reviewed before it becomes training data, and any logged-in Hugging Face user may open one on a public dataset, so the uploader’s own token is enough and no write token ships with spaCR. A dataset that does not exist yet is created first by
ensure_community_repo(), which only its owner can do.The contributor’s own login is preferred. With no login, or when the login cannot create a dataset that does not exist yet, the folder goes through the central upload Space instead (
central_contribute()), which opens the same pull request with its own token.- Parameters:
folder – a folder
write_contribution()made.target – as for
community_repo(); picks the repository.token – the uploader’s Hugging Face token;
find_token()’s when None.
- spacr.qt.widgets.model_share.ensure_community_repo(target: str, token: str, *, purpose: str = '') → str[source]¶
Make sure the community dataset exists; create it with a README if not.
Only the owner of the
einarolafssonnamespace can create one; for anyone else a missing repository is an error that says who to ask.- Parameters:
target – as for
community_repo().token – a Hugging Face token.
purpose – passed to
community_readme()for a new repository.
- Returns:
the dataset’s URL.
- spacr.qt.widgets.model_share.find_token() → str | None[source]¶
The uploader’s own Hugging Face token, or
None.
- spacr.qt.widgets.model_share.masks_dataset_target(name: str) → str[source]¶
The community target a user-named image-and-mask dataset goes to.
Always
community_<name>, so a dataset the user calls “figures” or “plaques” never lands in Plaque Assay’s two collections by accident.- Parameters:
name – what the user calls it, e.g.
"Toxoplasma vacuoles GFP".- Returns:
a target
community_repo()maps toeinarolafsson/community_<name>.- Raises:
ValueError – when
namehas no letters or digits.
- spacr.qt.widgets.model_share.pack_training_data(folder: str, out_dir: str | None = None) → str[source]¶
Pack a training-data folder into ONE uncompressed tar. Returns its path.
Uncompressed on purpose: microscopy TIFFs are already poorly compressible and gzipping tens of gigabytes costs far more time than it saves bytes. Raises if the result would be larger than the endpoint accepts, BEFORE the upload is attempted, so a user does not wait out a transfer that was never going to be accepted.
- Parameters:
folder – training-data folder to pack; it must exist, and its files must total no more than
MAX_TRAIN_BYTES.
- spacr.qt.widgets.model_share.pair_images_and_masks(images_dir: Any, masks_dir: Any) → Dict[str, Any][source]¶
Match an images folder to a masks folder by file name.
An image and a mask belong together when their names match without the extension, so
a.pngpairs witha.tif. Nothing is read but the folder listings.- Parameters:
images_dir – the folder of images.
masks_dir – the folder of label masks.
- Returns:
pairs((image, mask)paths, in name order),imagesandmasks(the counts),no_mask(images with no mask of the same name),no_image(masks with no image),duplicates(names that match more than one file on one side), andproblem(why the folders cannot be read, else empty). The folders match whenproblem,no_mask,no_imageandduplicatesare all empty and there is at least one pair.
- spacr.qt.widgets.model_share.pairs_match(report: Dict[str, Any]) → bool[source]¶
Whether a
pair_images_and_masks()report may be uploaded.- Parameters:
report – the report.
- Returns:
True when every image has exactly one mask of the same name, every mask one image, and there is at least one pair.
- spacr.qt.widgets.model_share.read_label_mask(path: Any) → Any[source]¶
A label mask file as a 2-D array.
- Parameters:
path – a
.tif/.tiff,.npyor ordinary image file.- Returns:
the labels; a colour image keeps its first channel.
- spacr.qt.widgets.model_share.seed_changes(seed: Any, final: Any) → Dict[str, Any][source]¶
Which of spaCR’s proposed plaques the contributor kept, edited or removed.
- Parameters:
seed – the label mask spaCR proposed, or None when it proposed nothing.
final – the label mask being contributed, same shape.
- Returns:
{"kept", "edited", "removed"}as lists of seed label ids, and"added": how many final labels overlap no seeded plaque.
- spacr.qt.widgets.model_share.share(path: str, fields: Dict[str, Any], token: str) → str[source]¶
Upload a checkpoint and its card. Returns the model page URL.
- Parameters:
path – local checkpoint file to upload.
fields – the share form’s values;
display_namenames the staging folder and the whole mapping fills the model card.token – Hugging Face access token used for every call.
- spacr.qt.widgets.model_share.slugify(text: str) → str[source]¶
A repository-safe folder name.
- Parameters:
text – display name or file name to convert; it is lower-cased and every run of characters other than
a-zand0-9becomes one hyphen. An empty result becomes"model".
- spacr.qt.widgets.model_share.target_repo(token: str) → Tuple[str, bool][source]¶
Where this token may publish: the shared repo, or its own namespace.
- Parameters:
token – Hugging Face access token; it decides whether the shared repository is reachable and, if not, whose namespace is used.
- Returns:
(repo_id, is_shared).
- spacr.qt.widgets.model_share.write_contribution(target: str, items: Any, dest: Any, *, consent: Dict[str, Any], contribution_id: str = '', notes: str = '') → pathlib.Path[source]¶
Lay a contribution out on disk exactly as the dataset README describes.
Refuses the whole contribution when any image has no annotation: an image without boxes or masks teaches a model that it holds nothing, which is almost never true of an image somebody chose to send. In the masks layout it also refuses, before writing anything, any image whose mask is not the image’s own size, naming each one with both sizes: a mask of another size does not lie on its image.
- Parameters:
target –
"figures"(boxes layout),"plaques"or any other community name (masks layout); seecommunity_repo().items – one mapping per image. Boxes layout:
name,image(theH x W x 3page the boxes were drawn on),boxes(pixel(x0, y0, x1, y1)), and optionallysource,paper(DOI, citation, PMCID) andprovenance(which proposed boxes were kept, moved or deleted). Masks layout:name,source(the original file, copied unchanged),labels(the label mask) and optionallyseed(spaCR’s proposed mask) andextra(anything else to record in the image’s meta file).dest – the folder the contribution folder is made in.
consent – what the contributor agreed to; recorded verbatim in
contribution.json.contribution_id – the folder name; a date and a random suffix when empty.
notes – the contributor’s own words about the images, recorded in
contribution.jsonwhen given.
- Returns:
the contribution folder.
- spacr.qt.widgets.model_share.yolo_lines(boxes: Any, width: int, height: int) → list[source]¶
Well boxes as YOLO label lines,
0 cx cy w hnormalised to 0-1.- Parameters:
boxes –
(x0, y0, x1, y1)pixel boxes; corners in either order, clipped to the image.width – image width in pixels.
height – image height in pixels.
- Returns:
one line per box with a positive area, class 0 (“plaque well”).