lightly-studio 0.4.0__py3-none-any.whl → 0.4.1__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of lightly-studio might be problematic. Click here for more details.

Files changed (74) hide show
  1. lightly_studio/__init__.py +1 -2
  2. lightly_studio/api/db_tables.py +3 -0
  3. lightly_studio/api/routes/api/dataset.py +5 -3
  4. lightly_studio/api/routes/api/embeddings2d.py +4 -16
  5. lightly_studio/core/dataset_query/dataset_query.py +98 -2
  6. lightly_studio/core/dataset_query/sample_field.py +11 -2
  7. lightly_studio/dist_lightly_studio_view_app/_app/immutable/assets/0.B-Bn8V7R.css +1 -0
  8. lightly_studio/dist_lightly_studio_view_app/_app/immutable/assets/Samples.CTl60pQb.css +1 -0
  9. lightly_studio/dist_lightly_studio_view_app/_app/immutable/assets/_layout.CxuTMeYy.css +1 -0
  10. lightly_studio/dist_lightly_studio_view_app/_app/immutable/assets/transform.Bte-FZ4V.css +1 -0
  11. lightly_studio/dist_lightly_studio_view_app/_app/immutable/chunks/{ChlxSwqI.js → 7XnHnNk_.js} +1 -1
  12. lightly_studio/dist_lightly_studio_view_app/_app/immutable/chunks/{DthpwYR_.js → BDE1kT04.js} +2 -2
  13. lightly_studio/dist_lightly_studio_view_app/_app/immutable/chunks/{D8ZGoCPm.js → BHoO7UL_.js} +2 -2
  14. lightly_studio/dist_lightly_studio_view_app/_app/immutable/chunks/{BiGQqqJP.js → BTpMiPuk.js} +1 -1
  15. lightly_studio/dist_lightly_studio_view_app/_app/immutable/chunks/BbG6fgnL.js +1 -0
  16. lightly_studio/dist_lightly_studio_view_app/_app/immutable/chunks/Bip0vTKl.js +1 -0
  17. lightly_studio/dist_lightly_studio_view_app/_app/immutable/chunks/{BrNKoXwc.js → BzYRexN9.js} +1 -1
  18. lightly_studio/dist_lightly_studio_view_app/_app/immutable/chunks/{CP9M7pei.js → C5oezL0m.js} +1 -1
  19. lightly_studio/dist_lightly_studio_view_app/_app/immutable/chunks/CEPpkZIV.js +1 -0
  20. lightly_studio/dist_lightly_studio_view_app/_app/immutable/chunks/ChO13USc.js +96 -0
  21. lightly_studio/dist_lightly_studio_view_app/_app/immutable/chunks/{ClzkJBWk.js → CmNXvs5e.js} +1 -1
  22. lightly_studio/dist_lightly_studio_view_app/_app/immutable/chunks/{DUtlYNuP.js → D9WxTSWa.js} +1 -1
  23. lightly_studio/dist_lightly_studio_view_app/_app/immutable/chunks/DELrRF6e.js +4 -0
  24. lightly_studio/dist_lightly_studio_view_app/_app/immutable/chunks/{BtXGzlpP.js → DFib3GIP.js} +1 -1
  25. lightly_studio/dist_lightly_studio_view_app/_app/immutable/chunks/{DMJzr1NB.js → DeAqvaPB.js} +1 -1
  26. lightly_studio/dist_lightly_studio_view_app/_app/immutable/chunks/DgCXCApo.js +438 -0
  27. lightly_studio/dist_lightly_studio_view_app/_app/immutable/chunks/DqhovIS0.js +1 -0
  28. lightly_studio/dist_lightly_studio_view_app/_app/immutable/entry/{app.Y-sSoz5q.js → app.CED-eiXl.js} +2 -2
  29. lightly_studio/dist_lightly_studio_view_app/_app/immutable/entry/start.D6UcpqyO.js +1 -0
  30. lightly_studio/dist_lightly_studio_view_app/_app/immutable/nodes/{0.0Fm6E-5B.js → 0.waSqEGqm.js} +2 -2
  31. lightly_studio/dist_lightly_studio_view_app/_app/immutable/nodes/{1.DB-0vkHb.js → 1.Bb_sKkYl.js} +1 -1
  32. lightly_studio/dist_lightly_studio_view_app/_app/immutable/nodes/{10.vaUePh5k.js → 10.D9Uicmfq.js} +1 -1
  33. lightly_studio/dist_lightly_studio_view_app/_app/immutable/nodes/{11.7i7ljNVT.js → 11.DKnK0EcJ.js} +1 -1
  34. lightly_studio/dist_lightly_studio_view_app/_app/immutable/nodes/13.D7dGgxYC.js +1 -0
  35. lightly_studio/dist_lightly_studio_view_app/_app/immutable/nodes/{2.Drwwdm7A.js → 2.BzK1sjoM.js} +138 -100
  36. lightly_studio/dist_lightly_studio_view_app/_app/immutable/nodes/{3.D3X_-Wan.js → 3.B08UPFst.js} +1 -1
  37. lightly_studio/dist_lightly_studio_view_app/_app/immutable/nodes/{4.C9TqY3tA.js → 4.C19_Nx95.js} +1 -1
  38. lightly_studio/dist_lightly_studio_view_app/_app/immutable/nodes/5.B2cR7brs.js +39 -0
  39. lightly_studio/dist_lightly_studio_view_app/_app/immutable/nodes/{6.fqfYR7dB.js → 6.C9Y2LZxG.js} +1 -1
  40. lightly_studio/dist_lightly_studio_view_app/_app/immutable/nodes/{7.C7gMM-gk.js → 7.CEbWmgIF.js} +1 -1
  41. lightly_studio/dist_lightly_studio_view_app/_app/immutable/nodes/8.Con-GcPz.js +20 -0
  42. lightly_studio/dist_lightly_studio_view_app/_app/immutable/nodes/{9.DbHcSiMn.js → 9.DW7FBNNH.js} +1 -1
  43. lightly_studio/dist_lightly_studio_view_app/_app/version.json +1 -1
  44. lightly_studio/dist_lightly_studio_view_app/index.html +7 -8
  45. lightly_studio/models/annotation/annotation_base.py +9 -0
  46. lightly_studio/models/dataset.py +6 -0
  47. lightly_studio/models/sample.py +1 -1
  48. lightly_studio/models/two_dim_embedding.py +16 -0
  49. lightly_studio/resolvers/annotation_resolver/get_all.py +3 -1
  50. lightly_studio/resolvers/dataset_resolver.py +18 -1
  51. lightly_studio/resolvers/sample_embedding_resolver.py +44 -2
  52. lightly_studio/resolvers/sample_resolver.py +1 -3
  53. lightly_studio/resolvers/twodim_embedding_resolver.py +93 -3
  54. lightly_studio/selection/select.py +70 -1
  55. lightly_studio/selection/selection_config.py +1 -1
  56. {lightly_studio-0.4.0.dist-info → lightly_studio-0.4.1.dist-info}/METADATA +1 -1
  57. {lightly_studio-0.4.0.dist-info → lightly_studio-0.4.1.dist-info}/RECORD +58 -58
  58. lightly_studio/dataset/loader.py +0 -581
  59. lightly_studio/dist_lightly_studio_view_app/_app/immutable/assets/0.CN4hnTks.css +0 -1
  60. lightly_studio/dist_lightly_studio_view_app/_app/immutable/assets/Samples.C0_eo9eP.css +0 -1
  61. lightly_studio/dist_lightly_studio_view_app/_app/immutable/assets/_layout.kFFGI0zL.css +0 -1
  62. lightly_studio/dist_lightly_studio_view_app/_app/immutable/assets/transform.sLzR40om.css +0 -1
  63. lightly_studio/dist_lightly_studio_view_app/_app/immutable/chunks/BOmrKuMn.js +0 -1
  64. lightly_studio/dist_lightly_studio_view_app/_app/immutable/chunks/BPpOWbDa.js +0 -1
  65. lightly_studio/dist_lightly_studio_view_app/_app/immutable/chunks/BaFFwDFr.js +0 -1
  66. lightly_studio/dist_lightly_studio_view_app/_app/immutable/chunks/BsaJCCG_.js +0 -96
  67. lightly_studio/dist_lightly_studio_view_app/_app/immutable/chunks/CWuDkrMZ.js +0 -436
  68. lightly_studio/dist_lightly_studio_view_app/_app/immutable/chunks/DyIcJj6J.js +0 -1
  69. lightly_studio/dist_lightly_studio_view_app/_app/immutable/chunks/WEyXQRi6.js +0 -1
  70. lightly_studio/dist_lightly_studio_view_app/_app/immutable/entry/start.CvxVp0Cu.js +0 -1
  71. lightly_studio/dist_lightly_studio_view_app/_app/immutable/nodes/13.9qy3WtZv.js +0 -1
  72. lightly_studio/dist_lightly_studio_view_app/_app/immutable/nodes/5.iRw6HCWX.js +0 -39
  73. lightly_studio/dist_lightly_studio_view_app/_app/immutable/nodes/8.C4v1w-oS.js +0 -20
  74. {lightly_studio-0.4.0.dist-info → lightly_studio-0.4.1.dist-info}/WHEEL +0 -0
@@ -1 +1 @@
1
- import{u as a}from"../chunks/DMJzr1NB.js";import{L as d}from"../chunks/DVxjPOJB.js";const s=async({parent:t,params:{dataset_id:e}})=>{const{globalStorage:o}=await t(),{tagsSelected:n}=a({dataset_id:e,kind:["annotation"]});return{annotationsSelectedTagsIds:n,annotationsSelectedAnnotationLabelsIds:o.selectedAnnotationFilterIds}},r=Object.freeze(Object.defineProperty({__proto__:null,load:s},Symbol.toStringTag,{value:"Module"}));export{d as component,r as universal};
1
+ import{u as a}from"../chunks/DeAqvaPB.js";import{L as d}from"../chunks/DVxjPOJB.js";const s=async({parent:t,params:{dataset_id:e}})=>{const{globalStorage:o}=await t(),{tagsSelected:n}=a({dataset_id:e,kind:["annotation"]});return{annotationsSelectedTagsIds:n,annotationsSelectedAnnotationLabelsIds:o.selectedAnnotationFilterIds}},r=Object.freeze(Object.defineProperty({__proto__:null,load:s},Symbol.toStringTag,{value:"Module"}));export{d as component,r as universal};
@@ -1 +1 @@
1
- import{u as a}from"../chunks/ClzkJBWk.js";import{u as l}from"../chunks/DMJzr1NB.js";import{u as m}from"../chunks/BOmrKuMn.js";import{L as b}from"../chunks/DVxjPOJB.js";const r=async({params:{dataset_id:e}})=>{const{selectedAnnotationFilterIds:s,textEmbedding:o}=m(),{tagsSelected:t}=l({dataset_id:e,kind:["sample"]}),{dimensionsValues:n}=a();return{samplesSelectedTagsIds:t,samplesDimensions:n,samplesTextEmbedding:o,samplesSelectedAnnotationLabelsIds:s}},c=Object.freeze(Object.defineProperty({__proto__:null,load:r},Symbol.toStringTag,{value:"Module"}));export{b as component,c as universal};
1
+ import{u as a}from"../chunks/CmNXvs5e.js";import{u as l}from"../chunks/DeAqvaPB.js";import{u as m}from"../chunks/Bip0vTKl.js";import{L as b}from"../chunks/DVxjPOJB.js";const r=async({params:{dataset_id:e}})=>{const{selectedAnnotationFilterIds:s,textEmbedding:o}=m(),{tagsSelected:t}=l({dataset_id:e,kind:["sample"]}),{dimensionsValues:n}=a();return{samplesSelectedTagsIds:t,samplesDimensions:n,samplesTextEmbedding:o,samplesSelectedAnnotationLabelsIds:s}},c=Object.freeze(Object.defineProperty({__proto__:null,load:r},Symbol.toStringTag,{value:"Module"}));export{b as component,c as universal};
@@ -0,0 +1,39 @@
1
+ import"../chunks/CWj6FrbW.js";import{p as ge,f as I,n as ct,a as ve,am as Ge,g as e,b as o,s as u,c as x,r as p,t as be,m as Se,u as Ut,Z as r,al as L,ab as st,$ as rt}from"../chunks/C3xJX0nD.js";import{c as ie,a as i,f as Z,t as Ke,d as Me}from"../chunks/CAPx0Bfm.js";import{s as Be}from"../chunks/DoEId1MK.js";import{i as O,s as J,a as Ce}from"../chunks/DmGM9V9Q.js";import{p as xe}from"../chunks/D9WxTSWa.js";import{I as ut,o as Yt,p as Ot,q as Zt,r as Gt,t as Re,v as Kt,w as mt,_ as Vt,x as jt,y as Wt,z as qt,C as gt,B as vt,D as Jt,R as Qt,n as ea,E as ta,F as aa,G as na,H as oa,J as sa,K as ra,M as la,N as ia}from"../chunks/DgCXCApo.js";import{u as je}from"../chunks/Bip0vTKl.js";import{u as ft,k as da,t as pe,c as q,e as ht,b as ca,i as ua}from"../chunks/BDE1kT04.js";import"../chunks/CmNXvs5e.js";import"../chunks/CEPpkZIV.js";import"../chunks/69_IOA4Y.js";import{b as ma,a as ga,g as va}from"../chunks/BHoO7UL_.js";import"../chunks/gBp1tBnA.js";import{e as lt}from"../chunks/SiegjVo0.js";import{s as _t,r as pt,p as Ve,b as it}from"../chunks/xQhUoIl9.js";import{S as fa}from"../chunks/BTpMiPuk.js";import{r as Ee}from"../chunks/7XnHnNk_.js";import{s as dt}from"../chunks/CpbA3HU7.js";import{B as ha,a as _a,b as ke,c as Oe,H as pa,d as Ze,D as ba,e as xa,u as bt,f as Sa,g as wa,Z as ya,h as Aa,S as $a}from"../chunks/ChO13USc.js";import{a as Ia,b as Pa,d as ka,e as Ea}from"../chunks/DqhovIS0.js";function Ma(m,t){ge(t,!0);/**
2
+ * @license @lucide/svelte v0.482.0 - ISC
3
+ *
4
+ * ISC License
5
+ *
6
+ * Copyright (c) for portions of Lucide are held by Cole Bemis 2013-2022 as part of Feather (MIT). All other copyright (c) for Lucide are held by Lucide Contributors 2022.
7
+ *
8
+ * Permission to use, copy, modify, and/or distribute this software for any
9
+ * purpose with or without fee is hereby granted, provided that the above
10
+ * copyright notice and this permission notice appear in all copies.
11
+ *
12
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
13
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
14
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
15
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
16
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
17
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
18
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
19
+ *
20
+ */let g=pt(t,["$$slots","$$events","$$legacy"]);const d=[["path",{d:"M15 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V7Z"}],["path",{d:"M14 2v4a2 2 0 0 0 2 2h4"}],["circle",{cx:"10",cy:"12",r:"2"}],["path",{d:"m20 17-1.296-1.296a2.41 2.41 0 0 0-3.408 0L9 22"}]];ut(m,_t({name:"file-image"},()=>g,{get iconNode(){return d},children:(n,c)=>{var l=ie(),h=I(l);Be(h,()=>t.children??ct),i(n,l)},$$slots:{default:!0}})),ve()}function Ba(m,t){ge(t,!0);/**
21
+ * @license @lucide/svelte v0.482.0 - ISC
22
+ *
23
+ * ISC License
24
+ *
25
+ * Copyright (c) for portions of Lucide are held by Cole Bemis 2013-2022 as part of Feather (MIT). All other copyright (c) for Lucide are held by Lucide Contributors 2022.
26
+ *
27
+ * Permission to use, copy, modify, and/or distribute this software for any
28
+ * purpose with or without fee is hereby granted, provided that the above
29
+ * copyright notice and this permission notice appear in all copies.
30
+ *
31
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
32
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
33
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
34
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
35
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
36
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
37
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
38
+ *
39
+ */let g=pt(t,["$$slots","$$events","$$legacy"]);const d=[["path",{d:"M18 22H4a2 2 0 0 1-2-2V6"}],["path",{d:"m22 13-1.296-1.296a2.41 2.41 0 0 0-3.408 0L11 18"}],["circle",{cx:"12",cy:"8",r:"2"}],["rect",{width:"16",height:"16",x:"6",y:"2",rx:"2"}]];ut(m,_t({name:"images"},()=>g,{get iconNode(){return d},children:(n,c)=>{var l=ie(),h=I(l);Be(h,()=>t.children??ct),i(n,l)},$$slots:{default:!0}})),ve()}var Ca=Z('<!> <span class="hidden sm:inline">Home</span>',1),Ra=Z('<!> <span class="max-w-[150px] truncate"> </span>',1),La=Z('<!> <span class="hidden sm:inline">Samples</span>',1),Ta=Z('<!> <span class="max-w-[200px] truncate"><!></span>',1),Da=Z("<!> <!> <!> <!> <!> <!> <!>",1);function Na(m,t){ge(t,!0);const g=()=>J(c,"$filteredSampleCount",d),[d,n]=Ce(),{filteredSampleCount:c}=je();ha(m,{class:"mb-2","data-testid":"sample-details-breadcrumb",children:(l,h)=>{_a(l,{children:(ne,de)=>{var T=Da(),y=I(T);ke(y,{children:(k,D)=>{{let A=o(()=>Ee.toHome());Oe(k,{get href(){return e(A)},class:"flex items-center gap-2",children:(N,M)=>{var v=Ca(),b=I(v);pa(b,{class:"h-4 w-4"}),Ge(2),i(N,v)},$$slots:{default:!0}})}},$$slots:{default:!0}});var G=u(y,2);Ze(G,{});var _=u(G,2);ke(_,{children:(k,D)=>{{let A=o(()=>Ee.toSamples(t.dataset.dataset_id));Oe(k,{get href(){return e(A)},class:"flex items-center gap-2",children:(N,M)=>{var v=Ra(),b=I(v);ba(b,{class:"h-4 w-4"});var E=u(b,2),ee=x(E,!0);p(E),be(()=>dt(ee,t.dataset.name)),i(N,v)},$$slots:{default:!0}})}},$$slots:{default:!0}});var P=u(_,2);Ze(P,{});var Q=u(P,2);ke(Q,{children:(k,D)=>{{let A=o(()=>Ee.toSamples(t.dataset.dataset_id));Oe(k,{get href(){return e(A)},class:"flex items-center gap-2",children:(N,M)=>{var v=La(),b=I(v);Ba(b,{class:"h-4 w-4"}),Ge(2),i(N,v)},$$slots:{default:!0}})}},$$slots:{default:!0}});var ce=u(Q,2);Ze(ce,{});var K=u(ce,2);ke(K,{children:(k,D)=>{xa(k,{class:"flex items-center gap-2",children:(A,N)=>{var M=Ta(),v=I(M);Ma(v,{class:"h-4 w-4"});var b=u(v,2),E=x(b);{var ee=f=>{var H=Ke();be(()=>dt(H,`Sample ${t.sampleIndex+1} of ${g()??""}`)),i(f,H)},te=f=>{var H=Ke("Sample");i(f,H)};O(E,f=>{t.sampleIndex!==void 0?f(ee):f(te,!1)})}p(b),i(A,M)},$$slots:{default:!0}})},$$slots:{default:!0}}),i(ne,T)},$$slots:{default:!0}})},$$slots:{default:!0}}),ve(),n()}function Ha(m,t){ge(t,!0);const g=()=>J(e(G),"$annotationResp",c),d=()=>J(e(ce),"$sample",c),n=()=>J(T,"$showAnnotationTextLabelsStore",c),[c,l]=Ce(),h=Ve(t,"isResizable",3,!1),{addReversibleAction:ne,clearReversibleActionsByGroupId:de}=je(),{showAnnotationTextLabelsStore:T}=ft(),y=o(()=>Gt({datasetId:t.datasetId,annotationId:t.annotationId})),G=o(()=>e(y).annotation),_=o(()=>e(y).updateAnnotation);let P=o(()=>g().data);const Q=o(()=>bt({sampleId:t.sampleId,datasetId:t.datasetId})),ce=o(()=>e(Q).sample);let K=o(()=>g().data?Yt(g().data):void 0);const k=M=>{(async()=>{try{await e(_)({annotation_id:t.annotationId,dataset_id:t.datasetId,bounding_box:M}),Sa({annotation:e(P),addReversibleAction:ne,updateAnnotation:e(_)})}catch(b){console.error("Failed to update annotation:",b.message)}})()};ma(()=>{de(wa)});var D=ie(),A=I(D);{var N=M=>{var v=ie(),b=I(v);da(b,()=>e(K),E=>{Ot(E,{get groupId(){return e(P).annotation_id},get onSelect(){return t.toggleAnnotationSelection},get box(){return e(K)},get isSelected(){return t.isSelected},children:(ee,te)=>{{let f=o(()=>({x:0,y:0,width:d().data.width,height:d().data.height}));Zt(ee,{get annotation(){return e(P)},get showLabel(){return n()},get imageWidth(){return d().data.width},get constraintBox(){return e(f)},get isResizable(){return h()},onBoundingBoxChanged:k})}},$$slots:{default:!0}})}),i(M,v)};O(A,M=>{e(P)&&d().data&&e(K)&&M(N)})}i(m,D),ve(),l()}const Fa=({datasetId:m})=>{const t=Re(Ia());return t.subscribe(()=>{}),{createAnnotation:d=>new Promise((n,c)=>{Se(t).mutate({path:{dataset_id:m},body:d},{onSuccess:l=>{n(l)},onError:l=>{c(l)}})})}},za=()=>{const m=Re(Pa());return m.subscribe(()=>{}),{createLabel:g=>new Promise((d,n)=>{Se(m).mutate({body:g},{onSuccess:c=>{d(c)},onError:c=>{n(c)}})})}},Xa=({datasetId:m})=>{const t=Re(ka());return t.subscribe(()=>{}),{deleteAnnotation:d=>new Promise((n,c)=>{Se(t).mutate({path:{dataset_id:m,annotation_id:d}},{onSuccess:()=>{n()},onError:l=>{c(l)}})})}},Ua=({datasetId:m})=>{const t=Re(Ea());return t.subscribe(()=>{}),{removeTagFromSample:(d,n)=>new Promise((c,l)=>{Se(t).mutate({path:{dataset_id:m,sample_id:d,tag_id:n}},{onSuccess:()=>c(),onError:h=>l(h)})})}};var Ya=Me('<line x1="0" stroke-width="1" vector-effect="non-scaling-stroke" stroke-dasharray="5,5" opacity="0.6"></line><line y1="0" vector-effect="non-scaling-stroke" stroke-width="1" stroke-dasharray="5,5" opacity="0.6"></line>',1),Oa=Me('<rect class="select-none" fill="transparent" role="button" style="outline: 0;cursor: crosshair;" tabindex="0"></rect>'),Za=Me("<g><!><!><!></g><!>",1),Ga=Me("<image></image><!>",1),Ka=Z('<div class="h-full w-full overflow-hidden"><div class="sample relative h-full w-full"><div class="absolute right-4 top-2 z-30"><!></div> <!> <!></div></div>'),Va=Z('<div class="flex h-full w-full flex-col space-y-4"><div class="flex w-full items-center"><!></div> <!> <div class="flex min-h-0 flex-1 gap-4"><div class="flex-1"><!></div> <div class="relative w-[375px]"><!></div></div></div>');function ja(m,t){ge(t,!0);const g=()=>J(M,"$labels",h),d=()=>J(b,"$isEditingMode",h),n=()=>J(e(D),"$sample",h),c=()=>J(de,"$selectedSampleIds",h),l=()=>J(G,"$isHidden",h),[h,ne]=Ce(),{selectedSampleIds:de,toggleSampleSelection:T}=je(),y=t.dataset.dataset_id,{isHidden:G,handleKeyEvent:_}=Kt(),{settingsStore:P}=ft(),{deleteAnnotation:Q}=Xa({datasetId:y}),{removeTagFromSample:ce}=Ua({datasetId:y}),K=()=>{va(Ee.toSamples(y))},k=o(()=>bt({sampleId:t.sampleId,datasetId:y})),D=o(()=>e(k).sample),A=o(()=>e(k).refetch),{createAnnotation:N}=Fa({datasetId:y}),M=mt(),{createLabel:v}=za(),{isEditingMode:b}=xe.data.globalStorage;let E=L(!1);const ee=async({x:a,y:s,width:X,height:j,labelName:S})=>{if(!g().data)return;let U=g().data.find(C=>C.annotation_label_name===S);U||(U=await v({annotation_label_name:S}));try{const C=await N({sample_id:t.sampleId,annotation_type:"object_detection",x:Math.round(a),y:Math.round(s),width:Math.round(X),height:Math.round(j),annotation_label_id:U.annotation_label_id});return e(A)(),r(R,C.annotation_id,!0),pe.success("Annotation created successfully"),C}catch(C){pe.error("Failed to create annotation. Please try again."),console.error("Error creating annotation:",C);return}},te=a=>{switch(a.key){case Se(P).key_go_back:d()?e(B)&&r(B,!1):K();break;case" ":a.preventDefault(),a.stopPropagation(),console.log("space pressed in sample details"),d()?r(E,!0):T(t.sampleId);break}_(a)},f=a=>{a.key===" "&&r(E,!1),_(a)};let H=o(()=>Aa(t.sampleId)),R=L(void 0),fe=L(void 0);ga(()=>{var a;r(R,void 0),r(re,void 0),(a=e(fe))==null||a(),r(B,!1),r(oe,void 0)});const we=a=>{e(E)||(e(R)===a?r(R,void 0):r(R,a,!0))};let re=L(void 0),F=L(!1),$=L(null),z=L(null),V=L(null);const ue=()=>{r(F,!1),r($,null),r(V,null)};let B=L(!1);const ye=10,xt=()=>{if(!e(z))return;const a=Wt(e(z));let s=null;const X=qt().on("start",j=>{if(!e(B))return;r(F,!0);const S=e(z).getBoundingClientRect(),U=j.sourceEvent.clientX,C=j.sourceEvent.clientY,W=(U-S.left)/S.width*n().data.width,Y=(C-S.top)/S.height*n().data.height;s={x:W,y:Y},r($,{x:W,y:Y,width:0,height:0},!0),r(V,{x:W,y:Y},!0)}).on("drag",j=>{if(!e($)||!e(F)||!s)return;const S=e(z).getBoundingClientRect(),U=j.sourceEvent.clientX,C=j.sourceEvent.clientY;let W=(U-S.left)/S.width*n().data.width,Y=(C-S.top)/S.height*n().data.height;const Ne=n().data.width,He=n().data.height;W=Math.max(0,Math.min(W,Ne)),Y=Math.max(0,Math.min(Y,He));const me=Math.min(s.x,W),he=Math.min(s.y,Y),Fe=Math.abs(W-s.x),Je=Math.abs(Y-s.y);r($,{x:me,y:he,width:Fe,height:Je},!0),r(V,{x:W,y:Y},!0)}).on("end",()=>{!e($)||!e(F)||(e($).width>ye&&e($).height>ye&&e(oe)&&ee({x:e($).x,y:e($).y,width:e($).width,height:e($).height,labelName:e(oe).label}),ue(),s=null)});return a.call(X),a.on("mousemove",wt),()=>{X.on("start",null).on("drag",null).on("end",null)}},St=a=>{if(!e(z)||e(F))return;const s=e(z).getBoundingClientRect(),X=a.clientX,j=a.clientY,S=(X-s.left)/s.width*n().data.width,U=(j-s.top)/s.height*n().data.height;r(V,{x:S,y:U},!0),a.stopPropagation(),a.preventDefault()},wt=Vt.throttle(St,50);Ut(()=>{xt(),e(D).subscribe(a=>{if(a.isSuccess&&a.data){let s=jt(a.data);r(Le,s,!0)}else r(Le,[],!0)})});let oe=L(void 0),Le=L(st([])),Ae=L(st(new Set));const yt=a=>{const s=new Set(e(Ae));s.has(a)?s.delete(a):s.add(a),r(Ae,s,!0)},At=o(()=>e(Le).filter(a=>!e(Ae).has(a.annotation_id))),Te=o(()=>e(oe)?ta(e(oe).label,1).color:"blue"),$t=async a=>{if(!n().data)return;(async()=>{try{await Q(a),pe.success("Annotation deleted successfully"),e(A)(),e(R)===a&&r(R,void 0)}catch(X){pe.error("Failed to delete annotation. Please try again."),console.error("Error deleting annotation:",X)}})()},It=async a=>{try{await ce(t.sampleId,a),pe.success("Tag removed successfully"),e(A)()}catch(s){pe.error("Failed to remove tag. Please try again."),console.error("Error removing tag from sample:",s)}},Pt=o(()=>e(E)?"grab":e(De)?"crosshair":"auto"),kt=o(()=>d()&&!e(E)),De=o(()=>e(B)&&!e(E)&&e(oe)!==void 0);let We=L(null);var qe=ie();lt("keydown",rt,te),lt("keyup",rt,f);var Et=I(qe);{var Mt=a=>{var s=Va(),X=x(s),j=x(X);Na(j,{get dataset(){return t.dataset},get sampleIndex(){return t.sampleIndex}}),p(X);var S=u(X,2);fa(S,{class:"mb-4 bg-border-hard"});var U=u(S,2),C=x(U),W=x(C);gt(W,{className:"h-full",children:(me,he)=>{vt(me,{className:"h-full",children:(Fe,Je)=>{var ze=Ka(),Xe=x(ze),Ue=x(Xe),Ct=x(Ue);{let le=o(()=>c().has(t.sampleId));Jt(Ct,{onSelect:()=>T(t.sampleId),get isSelected(){return e(le)}})}p(Ue);var Qe=u(Ue,2);{var Rt=le=>{var _e=ie(),$e=I(_e);Be($e,()=>t.children),i(le,_e)};O(Qe,le=>{t.children&&le(Rt)})}var Lt=u(Qe,2);ya(Lt,{get width(){return n().data.width},get height(){return n().data.height},get cursor(){return e(Pt)},get boundingBox(){return e(re)},registerResetFn:_e=>r(fe,_e,!0),zoomableContent:_e=>{var $e=Ga(),et=I($e),Tt=u(et);{var Dt=Ye=>{var tt=Za(),Ie=I(tt);let at;var nt=x(Ie);ht(nt,17,()=>e(At),w=>w.annotation_id,(w,ae)=>{{let se=o(()=>e(R)===e(ae).annotation_id);Ha(w,{get annotationId(){return e(ae).annotation_id},get sampleId(){return t.sampleId},get datasetId(){return y},get isResizable(){return e(kt)},get isSelected(){return e(se)},toggleAnnotationSelection:we})}});var ot=u(nt);{var Nt=w=>{Qt(w,{get bbox(){return e($)},get colorStroke(){return e(Te)},colorFill:"rgba(0, 123, 255, 0.1)",style:"outline: 0;",opacity:.8,scale:1})};O(ot,w=>{e($)&&e(F)&&e(oe)&&w(Nt)})}var Ht=u(ot);{var Ft=w=>{var ae=Ya(),se=I(ae),Pe=u(se);be(()=>{q(se,"y1",e(V).y),q(se,"x2",n().data.width),q(se,"y2",e(V).y),q(se,"stroke",e(Te)),q(Pe,"x1",e(V).x),q(Pe,"x2",e(V).x),q(Pe,"y2",n().data.height),q(Pe,"stroke",e(Te))}),i(w,ae)};O(Ht,w=>{e(V)&&e(De)&&w(Ft)})}p(Ie);var zt=u(Ie);{var Xt=w=>{var ae=Oa();it(ae,se=>r(z,se),()=>e(z)),be(()=>{q(ae,"width",n().data.width),q(ae,"height",n().data.height)}),i(w,ae)};O(zt,w=>{e(De)&&w(Xt)})}be(w=>at=ca(Ie,0,"",null,at,w),[()=>({invisible:l()})]),i(Ye,tt)};O(Tt,Ye=>{n().data&&Ye(Dt)})}be(()=>q(et,"href",e(H))),i(_e,$e)},$$slots:{zoomableContent:!0}}),p(Xe),it(Xe,le=>r(We,le),()=>e(We)),p(ze),i(Fe,ze)},$$slots:{default:!0}})},$$slots:{default:!0}}),p(C);var Y=u(C,2),Ne=x(Y);{var He=me=>{en(me,{get sample(){return n().data},get annotationsIdsToHide(){return e(Ae)},get selectedAnnotationId(){return e(R)},onAnnotationClick:we,onToggleShowAnnotation:yt,onDeleteAnnotation:$t,onRemoveTag:It,get onUpdate(){return e(A)},get addAnnotationEnabled(){return e(B)},set addAnnotationEnabled(he){r(B,he,!0)},get addAnnotationLabel(){return e(oe)},set addAnnotationLabel(he){r(oe,he,!0)}})};O(Ne,me=>{n().data&&me(He)})}p(Y),p(U),p(s),i(a,s)},Bt=a=>{ea(a,{})};O(Et,a=>{n().data?a(Mt):a(Bt,!1)})}i(m,qe),ve(),ne()}var Wa=Z('<label class="flex w-full flex-col gap-3 text-muted-foreground"><div class="text-sm">Select or create a label for a new annotation.</div> <!></label>'),qa=Z('<div class="items-left mb-2 flex flex-col justify-between space-y-2 bg-muted p-2"><div class="mb-2 w-full"><!></div> <!></div>'),Ja=Z('<div class="flex flex-col gap-3 space-y-4"><!> <div class="flex flex-col gap-2"></div></div>'),Qa=Z('<div class="flex h-full min-h-0 flex-col space-y-4 overflow-y-auto dark:[color-scheme:dark]"><!> <!> <!></div>');function en(m,t){ge(t,!0);const g=()=>J(y,"$annotationLabels",n),d=()=>J(T,"$isEditingMode",n),[n,c]=Ce();let l=Ve(t,"addAnnotationEnabled",15,!1),h=Ve(t,"addAnnotationLabel",15,void 0);const ne=o(()=>t.sample.tags.map(_=>({tagId:_.tag_id,name:_.name}))??[]),de=o(()=>t.sample.annotations?[...t.sample.annotations].sort((_,P)=>_.annotation_label.annotation_label_name.localeCompare(P.annotation_label.annotation_label_name)):[]),{isEditingMode:T}=xe.data.globalStorage,y=mt(),G=o(()=>ia(g().data||[]));gt(m,{className:"h-full",children:(_,P)=>{vt(_,{className:"h-full flex flex-col",children:(Q,ce)=>{var K=Qa(),k=x(K);aa(k,{get tags(){return e(ne)},get onClick(){return t.onRemoveTag}});var D=u(k,2);na(D,{title:"Annotations",children:(N,M)=>{var v=Ja(),b=x(v);{var E=te=>{var f=qa(),H=x(f),R=x(H);{let re=o(()=>l()?"default":"outline");sa(R,{title:"Add annotation",get variant(){return e(re)},"data-testid":"create-rectangle",class:"w-full",onclick:()=>{l(!l())},children:(F,$)=>{Ge();var z=Ke("Add annotation");i(F,z)},$$slots:{default:!0}})}p(H);var fe=u(H,2);{var we=re=>{var F=Wa(),$=u(x(F),2);{const z=(ue,B)=>{let ye=()=>B==null?void 0:B().inputValue;la(ue,{get label(){return ye()}})};let V=o(()=>e(G).find(ue=>{var B;return ue.value===((B=h())==null?void 0:B.value)}));ra($,{get items(){return e(G)},get selectedItem(){return e(V)},name:"annotation-label",label:"Choose or create a label",className:"w-full",contentClassName:"w-full",placeholder:"Select or create a label",onSelect:ue=>{h(ue)},notFound:z,$$slots:{notFound:!0}})}p(F),i(re,F)};O(fe,re=>{l()&&re(we)})}p(f),i(te,f)};O(b,te=>{d()&&te(E)})}var ee=u(b,2);ht(ee,21,()=>e(de),ua,(te,f)=>{{let H=o(()=>t.selectedAnnotationId===e(f).annotation_id),R=o(()=>t.annotationsIdsToHide.has(e(f).annotation_id));oa(te,{get annotation(){return e(f)},get isSelected(){return e(H)},onClick:()=>t.onAnnotationClick(e(f).annotation_id),onDeleteAnnotation:()=>t.onDeleteAnnotation(e(f).annotation_id),get isHidden(){return e(R)},onToggleShowAnnotation:fe=>{fe.stopPropagation(),t.onToggleShowAnnotation(e(f).annotation_id)},get onUpdate(){return t.onUpdate}})}}),p(ee),p(v),i(N,v)}});var A=u(D,2);$a(A,{get sample(){return t.sample}}),p(K),i(Q,K)},$$slots:{default:!0}})},$$slots:{default:!0}}),ve(),c()}var tn=Z('<div class="flex h-full w-full space-x-4 px-4 pb-4" data-testid="sample-details"><div class="h-full w-full space-y-6 rounded-[1vw] bg-card p-4"><!></div></div>');function An(m,t){ge(t,!0);const g=o(()=>xe.params.sampleId),d=xe.data.dataset,n=o(()=>Number(xe.params.sampleIndex));var c=tn(),l=x(c),h=x(l);ja(h,{get sampleId(){return e(g)},get dataset(){return d},get sampleIndex(){return e(n)},children:(ne,de)=>{var T=ie(),y=I(T);{var G=_=>{var P=ie(),Q=I(P);Be(Q,()=>t.children),i(_,P)};O(y,_=>{t.children&&_(G)})}i(ne,T)},$$slots:{default:!0}}),p(l),p(c),i(m,c),ve()}export{An as component};
@@ -1 +1 @@
1
- import{r as s}from"../chunks/ChlxSwqI.js";import{r as d}from"../chunks/BaFFwDFr.js";import{r as n}from"../chunks/B90CZVMX.js";const i=async()=>{const{data:t}=await d();if(!t||t.length===0)throw new Error("No datasets found");const e=t.toSorted((r,o)=>new Date(o.created_at||0).getTime()-new Date(r.created_at||0).getTime())[0],a=e==null?void 0:e.dataset_id;if(!a)throw new Error("No valid dataset ID found");n(307,s.toSamples(a))},m=Object.freeze(Object.defineProperty({__proto__:null,load:i},Symbol.toStringTag,{value:"Module"}));export{m as universal};
1
+ import{r as s}from"../chunks/7XnHnNk_.js";import{r as d}from"../chunks/CEPpkZIV.js";import{r as n}from"../chunks/B90CZVMX.js";const i=async()=>{const{data:t}=await d();if(!t||t.length===0)throw new Error("No datasets found");const e=t.toSorted((r,o)=>new Date(o.created_at||0).getTime()-new Date(r.created_at||0).getTime())[0],a=e==null?void 0:e.dataset_id;if(!a)throw new Error("No valid dataset ID found");n(307,s.toSamples(a))},m=Object.freeze(Object.defineProperty({__proto__:null,load:i},Symbol.toStringTag,{value:"Module"}));export{m as universal};
@@ -1 +1 @@
1
- import"../chunks/CWj6FrbW.js";import{p as f,u as $,g as a,a as _,b as o}from"../chunks/C3xJX0nD.js";import{s as i,a as h}from"../chunks/DmGM9V9Q.js";import{A as S}from"../chunks/CWuDkrMZ.js";import{u as T}from"../chunks/BOmrKuMn.js";import"../chunks/DthpwYR_.js";import"../chunks/ClzkJBWk.js";import"../chunks/BaFFwDFr.js";import"../chunks/DUtlYNuP.js";import"../chunks/69_IOA4Y.js";import"../chunks/D8ZGoCPm.js";import{u as G}from"../chunks/DMJzr1NB.js";import"../chunks/gBp1tBnA.js";function q(n,t){f(t,!0);const p=()=>i(c,"$lastGridType",s),e=()=>i(d,"$sampleSize",s),[s,m]=h(),{datasetId:r,sampleSize:d,selectedAnnotationFilterIds:l}=t.data,{lastGridType:c}=T(),u=o(()=>G({dataset_id:r})),g=o(()=>a(u).clearTagsSelected);$(()=>{p()!=="annotations"&&a(g)()}),S(n,{get itemHeight(){return e().height},get itemWidth(){return e().width},get dataset_id(){return r},get selectedAnnotationFilterIds(){return l}}),_(),m()}export{q as component};
1
+ import"../chunks/CWj6FrbW.js";import{p as f,u as $,g as a,a as _,b as o}from"../chunks/C3xJX0nD.js";import{s as i,a as h}from"../chunks/DmGM9V9Q.js";import{A as S}from"../chunks/DgCXCApo.js";import{u as T}from"../chunks/Bip0vTKl.js";import"../chunks/BDE1kT04.js";import"../chunks/CmNXvs5e.js";import"../chunks/CEPpkZIV.js";import"../chunks/D9WxTSWa.js";import"../chunks/69_IOA4Y.js";import"../chunks/BHoO7UL_.js";import{u as G}from"../chunks/DeAqvaPB.js";import"../chunks/gBp1tBnA.js";function q(n,t){f(t,!0);const p=()=>i(c,"$lastGridType",s),e=()=>i(d,"$sampleSize",s),[s,m]=h(),{datasetId:r,sampleSize:d,selectedAnnotationFilterIds:l}=t.data,{lastGridType:c}=T(),u=o(()=>G({dataset_id:r})),g=o(()=>a(u).clearTagsSelected);$(()=>{p()!=="annotations"&&a(g)()}),S(n,{get itemHeight(){return e().height},get itemWidth(){return e().width},get dataset_id(){return r},get selectedAnnotationFilterIds(){return l}}),_(),m()}export{q as component};
@@ -0,0 +1,20 @@
1
+ import{p as F,f as T,n as Yt,a as z,w as Tt,m as et,$ as gt,g as t,b as n,c as A,r as b,s as S,t as V,am as pt,u as Qt,al as Et,Z as tt}from"../chunks/C3xJX0nD.js";import{n as ta}from"../chunks/CEPpkZIV.js";import{u as bt}from"../chunks/Bip0vTKl.js";import"../chunks/CWj6FrbW.js";import{c as X,a as v,f as C,t as _t,d as aa}from"../chunks/CAPx0Bfm.js";import{i as U,s as L,a as q}from"../chunks/DmGM9V9Q.js";import{e as ht}from"../chunks/SiegjVo0.js";import{c as xt,e as ea,u as na,k as oa,b as sa,t as ia}from"../chunks/BDE1kT04.js";import{g as nt,b as ra,a as da}from"../chunks/BHoO7UL_.js";import{I as la,w as ca,r as ot,K as ua,M as va,N as ma,O as fa,o as Dt,G as ga,t as pa,C as Lt,B as jt,F as _a,J as ha,n as Ut,v as ba,D as xa,q as Ia}from"../chunks/DgCXCApo.js";import"../chunks/CmNXvs5e.js";import{p as H}from"../chunks/D9WxTSWa.js";import"../chunks/69_IOA4Y.js";import{S as Aa}from"../chunks/BTpMiPuk.js";import"../chunks/gBp1tBnA.js";import{r as K}from"../chunks/7XnHnNk_.js";import{S as $a,B as wa,a as Sa,b as at,c as mt,H as ya,d as ft,D as Ma,e as Na,g as Pa,Z as ka,h as Ca,f as Ba,u as Ea}from"../chunks/ChO13USc.js";import{S as Ra}from"../chunks/DNJnBfHs.js";import{f as Rt}from"../chunks/DELrRF6e.js";import{s as Z}from"../chunks/CpbA3HU7.js";import{f as Ta}from"../chunks/DqhovIS0.js";import{C as Da}from"../chunks/DFib3GIP.js";import{s as La}from"../chunks/DoEId1MK.js";import{s as ja,r as Ua}from"../chunks/xQhUoIl9.js";function Ha(l,a){F(a,!0);/**
2
+ * @license @lucide/svelte v0.482.0 - ISC
3
+ *
4
+ * ISC License
5
+ *
6
+ * Copyright (c) for portions of Lucide are held by Cole Bemis 2013-2022 as part of Feather (MIT). All other copyright (c) for Lucide are held by Lucide Contributors 2022.
7
+ *
8
+ * Permission to use, copy, modify, and/or distribute this software for any
9
+ * purpose with or without fee is hereby granted, provided that the above
10
+ * copyright notice and this permission notice appear in all copies.
11
+ *
12
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
13
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
14
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
15
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
16
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
17
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
18
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
19
+ *
20
+ */let e=Ua(a,["$$slots","$$events","$$legacy"]);const c=[["path",{d:"M5 3a2 2 0 0 0-2 2"}],["path",{d:"M19 3a2 2 0 0 1 2 2"}],["path",{d:"M21 19a2 2 0 0 1-2 2"}],["path",{d:"M5 21a2 2 0 0 1-2-2"}],["path",{d:"M9 3h1"}],["path",{d:"M9 21h1"}],["path",{d:"M14 3h1"}],["path",{d:"M14 21h1"}],["path",{d:"M3 9v1"}],["path",{d:"M21 9v1"}],["path",{d:"M3 14v1"}],["path",{d:"M21 14v1"}]];la(l,ja({name:"square-dashed"},()=>e,{get iconNode(){return c},children:(o,r)=>{var s=X(),x=T(s);La(x,()=>a.children??Yt),v(o,s)},$$slots:{default:!0}})),z()}const Fa=({annotationIndex:l,...a})=>{const e=Tt({isLoading:!1});return(async()=>{e.update(o=>({...o,isLoading:!0}));try{const{data:o}=await ta({path:{dataset_id:a.dataset_id},query:{cursor:l>0?l-1:0,limit:3,annotation_label_ids:a.annotation_label_ids,tag_ids:a.tag_ids}});if(!o){e.update(i=>({...i,isLoading:!1,error:"No annotations data received",data:void 0}));return}const{setfilteredAnnotationCount:r}=bt();r(o.total_count);let s;const x=l>0?o.data[0]:void 0;o.data.length>1&&(s=l===0?o.data[1]:o.data[2]),e.update(i=>({...i,isLoading:!1,error:void 0,data:{annotationNext:s,annotationPrevious:x}}))}catch(o){e.update(r=>({...r,isLoading:!1,error:String(o)}))}})(),e},za=async({parent:l,params:{dataset_id:a,annotationId:e,annotationIndex:c}})=>{const{annotationsSelectedTagsIds:o,annotationsSelectedAnnotationLabelsIds:r,dataset:s}=await l(),x=parseInt(c,10),i=Tt();if(!s)throw new Error("Dataset data not found");return Fa({annotationIndex:x,dataset_id:a,currentAnnotationId:e,annotation_label_ids:Array.from(et(r)),tag_ids:Array.from(et(o))}).subscribe(({data:B})=>{i.set(B)}),{annotationAdjacents:i,annotationIndex:x,annotationId:e,dataset:s}},Ue=Object.freeze(Object.defineProperty({__proto__:null,load:za},Symbol.toStringTag,{value:"Module"}));function Oa(l,a){F(a,!0);const e=()=>L(t(s),"$annotationAdjacents",c),[c,o]=q(),r=n(()=>H.data.annotationIndex),s=n(()=>H.data.annotationAdjacents),x=()=>{e().annotationNext&&nt(K.toSampleWithAnnotation({datasetId:e().annotationNext.dataset_id,sampleId:e().annotationNext.sample_id,annotationId:e().annotationNext.annotation_id,annotationIndex:t(r)+1}),{invalidateAll:!0})},i=()=>{e().annotationPrevious&&nt(K.toSampleWithAnnotation({datasetId:e().annotationPrevious.dataset_id,sampleId:e().annotationPrevious.sample_id,annotationId:e().annotationPrevious.annotation_id,annotationIndex:t(r)-1}),{invalidateAll:!0})},B=w=>{switch(w.key){case"ArrowRight":x();break;case"ArrowLeft":i();break}};var $=X();ht("keydown",gt,B);var g=T($);{var E=w=>{{let d=n(()=>!!e().annotationPrevious),I=n(()=>!!e().annotationNext);Ra(w,{get hasPrevious(){return t(d)},get hasNext(){return t(I)},onPrevious:i,onNext:x})}};U(g,w=>{e()&&w(E)})}v(l,$),z(),o()}const Ga={object_detection:"Object Detection",instance_segmentation:"Instance Segmentation",semantic_segmentation:"Semantic Segmentation",classification:"Classification"};var Ka=C('<span class="text-sm"> </span> <span class="break-all text-sm"> </span>',1);function qa(l,a){var e=Ka(),c=T(e),o=A(c,!0);b(c);var r=S(c,2),s=A(r,!0);b(r),V(()=>{Z(o,a.label),xt(r,"data-testid",`annotation-metadata-${a.id}`),Z(s,a.value)}),v(l,e)}var Wa=C('<span class="break-all text-sm"> </span>'),Va=C('<span class="text-sm"> </span> <!>',1);function Za(l,a){F(a,!0);const e=()=>L(s,"$result",o),c=()=>L(a.isEditingMode,"$isEditingMode",o),[o,r]=q(),s=ca(),{updateAnnotation:x}=ot({datasetId:a.datasetId,annotationId:a.annotationId,onUpdate:a.onUpdate}),i=n(()=>ma(e().data||[])),B=n(()=>{const f=t(i).find(p=>p.value===a.value);return f||{value:a.value,label:a.value}});var $=Va(),g=T($),E=A(g,!0);b(g);var w=S(g,2);{var d=f=>{{const p=(y,m)=>{let k=()=>m==null?void 0:m().inputValue;va(y,{get label(){return k()}})};let _=n(()=>t(i).find(y=>{var m;return y.value===((m=t(B))==null?void 0:m.value)}));ua(f,{get items(){return t(i)},get selectedItem(){return t(_)},name:"annotation-label",placeholder:"Select or create a label",onSelect:y=>{x({annotation_id:a.annotationId,dataset_id:a.datasetId,label_name:y.value})},notFound:p,$$slots:{notFound:!0}})}},I=f=>{var p=Wa();xt(p,"data-testid","annotation-metadata-label");var _=A(p,!0);b(p),V(()=>Z(_,a.value)),v(f,p)};U(w,f=>{c()?f(d):f(I,!1)})}V(()=>Z(E,a.label)),v(l,$),z(),r()}var Ja=C('<div class="flex flex-col gap-4"><div class="grid grid-cols-[6rem_1fr] gap-y-3 text-diffuse-foreground"></div></div>');function Xa(l,a){F(a,!0);const e=()=>L(t(x),"$annotationResp",c),[c,o]=q(),{datasetId:r}=H.data,s=n(()=>ot({datasetId:r,annotationId:a.annotationId})),x=n(()=>t(s).annotation);let i=n(()=>e().data);const B=n(()=>{var I,f;if(!t(i))return[];let d=[{id:"label",label:"Label:",value:(f=(I=t(i))==null?void 0:I.annotation_label)==null?void 0:f.annotation_label_name},{id:"type",label:"Type:",value:Ga[t(i).annotation_type]||"Unknown"}];if(t(i)&&!fa(t(i))){const{height:p,width:_}=Dt(t(i));d=[{id:"height",label:"Height:",value:Rt(Math.round(p))+"px"},{id:"width",label:"Width:",value:Rt(Math.round(_))+"px"},...d]}return d}),{isEditingMode:$}=H.data.globalStorage;var g=X(),E=T(g);{var w=d=>{ga(d,{title:"Annotation details",children:(I,f)=>{var p=Ja(),_=A(p);ea(_,21,()=>t(B),({label:y,value:m,id:k})=>y,(y,m)=>{let k=()=>t(m).label,D=()=>t(m).value,M=()=>t(m).id;var h=X(),R=T(h);{var u=N=>{Za(N,{get onUpdate(){return a.onUpdate},get annotationId(){return a.annotationId},get datasetId(){return r},get label(){return k()},get value(){return D()},get isEditingMode(){return $}})},O=N=>{qa(N,{get label(){return k()},get id(){return M()},get value(){return D()}})};U(R,N=>{M()==="label"&&$?N(u):N(O,!1)})}v(y,h)}),b(_),b(p),v(I,p)}})};U(E,d=>{t(B).length>0&&d(w)})}v(l,g),z(),o()}const Ya=()=>{const l=pa(Ta());return l.subscribe(()=>{}),{removeTagFromAnnotation:(e,c)=>new Promise((o,r)=>{et(l).mutate({path:{annotation_id:e,tag_id:c}},{onSuccess:()=>o(),onError:s=>r(s)})})}};var Qa=C("<!> <!>",1),te=C('<div class="flex h-full w-full items-center justify-center"><!></div>'),ae=C('<div class="flex h-full min-h-0 flex-col space-y-4 overflow-hidden dark:[color-scheme:dark]"><!> <!> <!></div>');function ee(l,a){F(a,!0);const e=()=>L(t(i),"$annotationResp",c),[c,o]=q(),{removeTagFromAnnotation:r}=Ya(),{datasetId:s}=H.data,x=n(()=>ot({datasetId:s,annotationId:a.annotationId})),i=n(()=>t(x).annotation),B=n(()=>t(x).refetch);let $=n(()=>e().data),g=n(()=>{var d;return(d=t($))==null?void 0:d.sample});const E=n(()=>{var d,I;return((I=(d=t($))==null?void 0:d.tags)==null?void 0:I.map(f=>({tagId:f.tag_id,name:f.name})))??[]}),w=async d=>{await r(t($).annotation_id,d),t(B)()};Lt(l,{className:"h-full",children:(d,I)=>{jt(d,{className:"h-full flex flex-col",children:(f,p)=>{var _=ae(),y=A(_);_a(y,{get tags(){return t(E)},onClick:w});var m=S(y,2);Xa(m,{get annotationId(){return a.annotationId},get onUpdate(){return a.onUpdate}});var k=S(m,2);{var D=h=>{var R=Qa(),u=T(R);$a(u,{get sample(){return t(g)},showCustomMetadata:!1});var O=S(u,2);{let N=n(()=>K.toSample({sampleId:t(g).sample_id,datasetId:t(g).dataset_id}));ha(O,{variant:"secondary",get href(){return t(N)},children:(j,It)=>{pt();var st=_t("View sample");v(j,st)},$$slots:{default:!0}})}v(h,R)},M=h=>{var R=te(),u=A(R);Ut(u,{size:"large",align:"center"}),b(R),v(h,R)};U(k,h=>{t(g)?h(D):h(M,!1)})}b(_),v(f,_)},$$slots:{default:!0}})},$$slots:{default:!0}}),z(),o()}var ne=C('<!> <span class="hidden sm:inline">Home</span>',1),oe=C('<!> <span class="max-w-[150px] truncate"> </span>',1),se=C('<!> <span class="hidden sm:inline">Annotations</span>',1),ie=C('<!> <span class="max-w-[200px] truncate"><!></span>',1),re=C("<!> <!> <!> <!> <!> <!> <!>",1);function de(l,a){F(a,!0);const e=()=>L(r,"$filteredAnnotationCount",c),[c,o]=q(),{filteredAnnotationCount:r}=bt();wa(l,{class:"mb-2",children:(s,x)=>{Sa(s,{children:(i,B)=>{var $=re(),g=T($);at(g,{children:(_,y)=>{{let m=n(()=>K.toHome());mt(_,{get href(){return t(m)},class:"flex items-center gap-2",children:(k,D)=>{var M=ne(),h=T(M);ya(h,{class:"h-4 w-4"}),pt(2),v(k,M)},$$slots:{default:!0}})}},$$slots:{default:!0}});var E=S(g,2);ft(E,{});var w=S(E,2);at(w,{children:(_,y)=>{{let m=n(()=>K.toAnnotations(a.dataset.dataset_id));mt(_,{get href(){return t(m)},class:"flex items-center gap-2",children:(k,D)=>{var M=oe(),h=T(M);Ma(h,{class:"h-4 w-4"});var R=S(h,2),u=A(R,!0);b(R),V(()=>Z(u,a.dataset.name)),v(k,M)},$$slots:{default:!0}})}},$$slots:{default:!0}});var d=S(w,2);ft(d,{});var I=S(d,2);at(I,{children:(_,y)=>{{let m=n(()=>K.toAnnotations(a.dataset.dataset_id));mt(_,{get href(){return t(m)},class:"flex items-center gap-2",children:(k,D)=>{var M=se(),h=T(M);Da(h,{class:"h-4 w-4"}),pt(2),v(k,M)},$$slots:{default:!0}})}},$$slots:{default:!0}});var f=S(I,2);ft(f,{});var p=S(f,2);at(p,{children:(_,y)=>{Na(_,{class:"flex items-center gap-2",children:(m,k)=>{var D=ie(),M=T(D);Ha(M,{class:"h-4 w-4"});var h=S(M,2),R=A(h);{var u=N=>{var j=_t();V(()=>Z(j,`Annotation ${a.annotationIndex+1} of ${e()??""}`)),v(N,j)},O=N=>{var j=_t("Annotation");v(N,j)};U(R,N=>{a.annotationIndex!==void 0?N(u):N(O,!1)})}b(h),v(m,D)},$$slots:{default:!0}})},$$slots:{default:!0}}),v(i,$)},$$slots:{default:!0}})},$$slots:{default:!0}}),z(),o()}var le=aa("<image></image><g><!></g>",1),ce=C('<div class="h-full w-full overflow-hidden"><div class="sample relative h-full w-full"><div class="absolute right-4 top-2 z-30"><!></div> <!> <!></div></div>'),ue=C('<div class="flex h-full w-full items-center justify-center"><!></div>'),ve=C('<div class="flex h-full w-full flex-col space-y-4"><div class="flex w-full items-center"><!></div> <!> <div class="flex min-h-0 flex-1 gap-4"><div class="flex-1"><!></div> <div class="relative w-[375px]"><!></div></div></div>');function me(l,a){F(a,!0);const e=()=>L(j,"$isEditingMode",s),c=()=>L(t(M),"$annotationResp",s),o=()=>L(B,"$selectedSampleAnnotationCropIds",s),r=()=>L(E,"$isHidden",s),[s,x]=q(),{toggleSampleAnnotationCropSelection:i,selectedSampleAnnotationCropIds:B,clearReversibleActionsByGroupId:$,addReversibleAction:g}=bt(),{isHidden:E,handleKeyEvent:w}=ba(),{settingsStore:d}=na(),I=" ",f=et(d).key_go_back;let p=Et(!1);const _=()=>{var P;(P=a.sample)!=null&&P.dataset_id?nt(K.toAnnotations(a.sample.dataset_id)):nt("/")},y=P=>{switch(P.key){case f:_();break;case" ":P.preventDefault(),e()?tt(p,!0):i(a.annotationId);break;case I:P.preventDefault(),i(a.annotationId);break}w(P)},m=P=>{P.key===" "&&tt(p,!1),w(P)},k=H.data.datasetId,D=n(()=>ot({datasetId:k,annotationId:a.annotationId})),M=n(()=>t(D).annotation),h=n(()=>t(D).updateAnnotation);ra(()=>{$(Pa)});const R=P=>{if(t(u)){const J={annotation_id:t(u).annotation_id,dataset_id:t(u).dataset_id,bounding_box:P};(async()=>{try{await t(h)(J),Ba({annotation:t(u),addReversibleAction:g,updateAnnotation:t(h)})}catch(yt){ia.error("Failed to update annotations:"+yt.message)}})()}};let u=n(()=>c().data),O=n(()=>{var P,J;return Ca(((J=(P=t(u))==null?void 0:P.sample)==null?void 0:J.sample_id)||"")}),N=n(()=>t(u)?Dt(t(u)):void 0);const{isEditingMode:j}=H.data.globalStorage,It=n(()=>t(p)?"grab":"auto"),st=n(()=>e()&&!t(p));let Y=Et(void 0);Qt(()=>{!t(Y)&&t(N)&&tt(Y,t(N),!0)}),da(()=>{tt(Y,void 0)});var it=ve();ht("keydown",gt,y),ht("keyup",gt,m);var rt=A(it),Ht=A(rt);de(Ht,{get dataset(){return a.dataset},get annotationIndex(){return a.annotationIndex}}),b(rt);var At=S(rt,2);Aa(At,{class:"mb-4 bg-border-hard"});var $t=S(At,2),dt=A($t),Ft=A(dt);Lt(Ft,{className:"h-full",children:(P,J)=>{jt(P,{className:"h-full",children:(St,yt)=>{var Mt=X(),Ot=T(Mt);{var Gt=W=>{var G=ce(),Q=A(G),lt=A(Q),qt=A(lt);{let Pt=n(()=>o().has(a.annotationId));xa(qt,{onSelect:()=>i(a.annotationId),get isSelected(){return t(Pt)}})}b(lt);var Nt=S(lt,2);Oa(Nt,{});var Wt=S(Nt,2);ka(Wt,{get width(){return t(u).sample.width},get height(){return t(u).sample.height},get cursor(){return t(It)},get boundingBox(){return t(Y)},zoomableContent:(Vt,ct)=>{let Zt=()=>ct==null?void 0:ct().scale;var kt=le(),Ct=T(kt),ut=S(Ct);let Bt;var Jt=A(ut);oa(Jt,()=>c().dataUpdatedAt,vt=>{{let Xt=n(()=>({x:0,y:0,width:t(u).sample.width,height:t(u).sample.height}));Ia(vt,{get annotation(){return t(u)},showLabel:!0,get scale(){return Zt()},get imageWidth(){return t(u).sample.width},get isResizable(){return t(st)},onBoundingBoxChanged:R,get constraintBox(){return t(Xt)}})}}),b(ut),V(vt=>{xt(Ct,"href",t(O)),Bt=sa(ut,0,"",null,Bt,vt)},[()=>({invisible:r()})]),v(Vt,kt)},$$slots:{zoomableContent:!0}}),b(Q),b(G),v(W,G)},Kt=W=>{var G=ue(),Q=A(G);Ut(Q,{size:"large",align:"center"}),b(G),v(W,G)};U(Ot,W=>{t(u)?W(Gt):W(Kt,!1)})}v(St,Mt)},$$slots:{default:!0}})},$$slots:{default:!0}}),b(dt);var wt=S(dt,2),zt=A(wt);ee(zt,{get annotationId(){return a.annotationId}}),b(wt),b($t),b(it),v(l,it),z(),x()}var fe=C('<div class="flex h-full w-full space-x-4 px-4 pb-4" data-testid="annotation-details"><div class="h-full w-full space-y-6 rounded-[1vw] bg-card p-4"><!></div></div>');function He(l,a){F(a,!0);const e=()=>L(t($),"$sample",c),[c,o]=q(),r=n(()=>a.data.annotationId),s=n(()=>a.data.dataset),x=n(()=>a.data.annotationIndex),i=n(()=>H.params.sampleId),B=n(()=>Ea({sampleId:t(i),datasetId:t(s).dataset_id})),$=n(()=>t(B).sample);var g=fe(),E=A(g),w=A(E);{var d=I=>{me(I,{get annotationId(){return t(r)},get annotationIndex(){return t(x)},get dataset(){return t(s)},get sample(){return e().data}})};U(w,I=>{e().data&&t(r)&&t(s)&&I(d)})}b(E),b(g),v(l,g),z(),o()}export{He as component,Ue as universal};
@@ -1 +1 @@
1
- import"../chunks/CWj6FrbW.js";import{p as Se,al as I,ab as ze,u as xe,g as e,b as d,Z as h,c as v,s as V,f as R,r as f,t as le,a as ye,w as He,m as _e,am as Ne}from"../chunks/C3xJX0nD.js";import{f as T,c as D,a as l}from"../chunks/CAPx0Bfm.js";import{i as W,a as Te,s as ve}from"../chunks/DmGM9V9Q.js";import{a as We,S as qe,e as Fe,s as oe,u as Oe,k as je,b as Ke}from"../chunks/DthpwYR_.js";import{p as P,r as Qe,b as ke}from"../chunks/xQhUoIl9.js";import{r as Re,u as Ve}from"../chunks/DyIcJj6J.js";import{h as Ae,i as te,s as Be,j as Ge,k as Ee,l as Ye,n as Ie,L as Ze}from"../chunks/CWuDkrMZ.js";import{S as De}from"../chunks/BiGQqqJP.js";import{u as Je}from"../chunks/BOmrKuMn.js";import"../chunks/ClzkJBWk.js";import"../chunks/BaFFwDFr.js";import"../chunks/DUtlYNuP.js";import"../chunks/69_IOA4Y.js";import"../chunks/D8ZGoCPm.js";import"../chunks/gBp1tBnA.js";import{I as Ue}from"../chunks/CP9M7pei.js";import{s as Z}from"../chunks/DoEId1MK.js";import{s as Xe}from"../chunks/CpbA3HU7.js";const $e=Be(),et=Ge();var tt=T("<div><!></div>"),it=T("<div><!></div>"),at=T("<div><!></div>"),rt=T("<div><!></div>"),st=T("<div><!></div>"),ot=T("<div><!> <div><!> <!></div> <!></div>");function lt(q,i){Se(i,!0);let m=P(i,"height",3,"100%"),k=P(i,"width",3,"100%"),p=P(i,"stickyIndices",19,()=>[]),M=P(i,"overScan",3,1),b=P(i,"marginLeft",3,0),o=P(i,"marginTop",3,0),O=P(i,"layout",3,"vertical"),w=P(i,"scrollPosition",15,0),ie=P(i,"scrollAlignment",3,"auto"),z=P(i,"scrollBehavior",3,"auto"),fe=P(i,"getKey",3,t=>t),ae=Qe(i,["$$slots","$$events","$$legacy","itemCount","itemSize","height","width","stickyIndices","overScan","marginLeft","marginTop","layout","scrollPosition","scrollAlignment","scrollBehavior","getKey","onscroll","header","item","placeholder","footer"]),_=I(void 0),j=I(ze(w())),re=I(0),A=I(0),ne=I(0),de=I(0),J=I(0),U=I(0),B=I(ze([])),K=!1,X=!1,G=I(!1);function me(t,r=ie(),g=z()){u(ue(t,r),g)}function he(t,r=z()){u(t,r)}const ue=(t,r)=>{const g=e(c)?o()+e(re):b()+e(A),S=t*i.itemSize+g,N=S-e(L)+i.itemSize+g;let a;switch(r){case"start":a=S;break;case"center":a=S-(e(L)-i.itemSize)/2;break;case"end":a=N;break;default:a=Math.max(N,Math.min(S,w()));break}return Math.max(0,Math.min(e(ce)-e(L),a))},u=(t,r=z())=>{e(_)&&(K=!0,e(_).scrollTo({[e(c)?"top":"left"]:t,behavior:r}),K=!1)},Q=t=>{e(_)&&!K&&!X&&(K=!0,e(_).scrollTo({top:t,behavior:z()}),K=!1)},se=t=>{const r=t*i.itemSize;return`position: absolute; transform: translate3d(${e(c)?`${b()}px, ${r+o()}px`:`${e(A)+r+b()}px, ${o()}px`}, 0px); ${e(pe)} will-change: transform;`},ge=t=>{X=!0,K||(e(c)?(h(j,Math.max(0,t.currentTarget.scrollTop-e(re)),!0),w(t.currentTarget.scrollTop)):(h(j,Math.max(0,t.currentTarget.scrollLeft-e(A)),!0),w(t.currentTarget.scrollLeft)),e(C)(e(j))),$e(()=>{X=!1})};let c=d(()=>O()==="vertical"),ce=d(()=>i.itemCount*i.itemSize),pe=d(()=>e(c)?`height: ${i.itemSize}px; width: ${b()>0?`${e(U)-b()}px`:"100%"};`:`height: ${o()>0?`${e(de)-o()}px`:"100%"}; width: ${i.itemSize}px;`),L=d(()=>e(c)?e(ne):e(J));xe(()=>{e(L)&&h(B,Ae(i.itemCount,i.itemSize,e(L),M(),e(j)),!0)}),xe(()=>{e(_)&&Q(w())});let C=d(()=>et(e(L),{fast:()=>{h(G,!0)},slow:()=>{h(G,!1)}}));var $={scrollToIndex:me,scrollToPosition:he},x=ot(),F=t=>{var r;ge(t),(r=i.onscroll)==null||r.call(i,t)};We(x,t=>({onscroll:F,...ae,[qe]:t}),[()=>({position:"relative",overflow:"auto",height:typeof m()=="number"?`${m()}px`:m(),width:typeof k()!="number"?k():`${k()}px`})]);var H=v(x);{var E=t=>{var r=D(),g=R(r);{var S=a=>{var s=tt(),n=v(s);Z(n,()=>i.header),f(s),te(s,"offsetHeight",y=>h(re,y)),l(a,s)},N=a=>{var s=it();oe(s,"",{},{position:"absolute"});var n=v(s);Z(n,()=>i.header),f(s),te(s,"offsetWidth",y=>h(A,y)),l(a,s)};W(g,a=>{e(c)?a(S):a(N,!1)})}l(t,r)};W(H,t=>{i.header&&t(E)})}var ee=V(H,2);let be;var we=v(ee);{var Ce=t=>{const r=d(()=>Math.max(...p().filter(a=>a<e(B)[0])));var g=D(),S=R(g);{var N=a=>{var s=at();let n;var y=v(s);Z(y,()=>i.item,()=>({index:e(r),style:""})),f(s),le(Y=>n=oe(s,"",n,Y),[()=>({position:"sticky",top:e(c)?`${o()}px`:"0px",left:e(c)?"0px":`${b()}px`,"z-index":"1"})]),l(a,s)};W(S,a=>{e(r)>=0&&a(N)})}l(t,g)};W(we,t=>{p().length&&e(B).length&&t(Ce)})}var Pe=V(we,2);Fe(Pe,17,()=>e(B),t=>fe()(t),(t,r)=>{const g=d(()=>se(e(r)));var S=D(),N=R(S);{var a=n=>{var y=D(),Y=R(y);Z(Y,()=>i.item,()=>({index:e(r),style:e(g)})),l(n,y)},s=n=>{var y=D(),Y=R(y);Z(Y,()=>i.placeholder,()=>({index:e(r),style:e(g)})),l(n,y)};W(N,n=>{!e(G)||!i.placeholder?n(a):n(s,!1)})}l(t,S)}),f(ee);var Me=V(ee,2);{var Le=t=>{var r=D(),g=R(r);{var S=a=>{var s=rt(),n=v(s);Z(n,()=>i.footer),f(s),l(a,s)},N=a=>{var s=st();let n;var y=v(s);Z(y,()=>i.footer),f(s),le(Y=>n=oe(s,"",n,Y),[()=>({position:"absolute",top:"0px",left:`${e(A)+i.itemCount*i.itemSize+b()}px`})]),l(a,s)};W(g,a=>{e(c)?a(S):a(N,!1)})}l(t,r)};W(Me,t=>{i.footer&&t(Le)})}return f(x),ke(x,t=>h(_,t),()=>e(_)),le(t=>be=oe(ee,"",be,t),[()=>({height:e(c)?`${e(ce)}px`:"100%",width:e(c)?"100%":`${e(ce)}px`})]),te(x,"offsetHeight",t=>h(ne,t)),te(x,"clientHeight",t=>h(de,t)),te(x,"offsetWidth",t=>h(J,t)),te(x,"clientWidth",t=>h(U,t)),l(q,x),ye($)}const nt=(...q)=>{const i=Re(...q),m=Ee({...i,getNextPageParam:o=>o.nextCursor||void 0}),k=Ve(),p=()=>{k.invalidateQueries({queryKey:i.queryKey})},M=He([]);return m.subscribe(o=>{if(o.isSuccess){const O=o.data.pages.flatMap(w=>w.data);M.set(O)}}),{data:M,loadMore:()=>{_e(m).hasNextPage&&!_e(m).isFetchingNextPage&&_e(m).fetchNextPage()},query:m,refresh:p}};var dt=T('<div class="flex flex-row items-center gap-10"><!> <div class="flex-1 text-sm text-foreground"> </div></div>');function ct(q,i){Se(i,!0);const m=()=>ve(M,"$gridViewSampleRenderingStore",k),[k,p]=Te(),{gridViewSampleRenderingStore:M}=Oe();let b=d(m);var o=dt(),O=v(o);Ye(O,{get sample(){return i.item.sample},get objectFit(){return e(b)}});var w=V(O,2),ie=v(w,!0);f(w),f(o),le(()=>Xe(ie,i.item.text)),l(q,o),ye(),p()}var vt=T('<div class="flex h-full w-full items-center justify-center"><!> <div>Loading samples...</div></div>'),ft=T("<div><!></div>"),mt=T('<div class="flex justify-center p-4"><!></div>'),ht=T("<!> <!>",1),ut=T('<div class="flex flex-1 flex-col space-y-4"><div class="my-2 flex items-center space-x-4"><div class="flex-1"><div class="text-2xl font-semibold">Captions</div></div> <div class="w-4/12"><!></div></div> <!> <div class="h-full w-full flex-1 overflow-hidden"><!></div></div>');function gt(q,i){Se(i,!0);const m=()=>ve(e(O),"$data",M),k=()=>ve(fe,"$sampleSize",M),p=()=>ve(e(w),"$query",M),[M,b]=Te(),o=d(()=>nt({path:{dataset_id:i.datasetId}})),O=d(()=>e(o).data),w=d(()=>e(o).query),ie=d(()=>e(o).loadMore);let z=I(null);const{sampleSize:fe}=Je();let ae=I(0);xe(()=>{if(!e(z))return;h(ae,e(z).clientHeight,!0);const u=new ResizeObserver(()=>{e(z)&&h(ae,e(z).clientHeight,!0)});return u.observe(e(z)),()=>{u.disconnect()}});let _=d(m);const j=16,re=d(()=>k().height+j),A=d(()=>k().width),ne=d(()=>k().height),de=d(()=>e(ae)+j);var J=ut(),U=v(J),B=V(v(U),2),K=v(B);Ue(K,{}),f(B),f(U);var X=V(U,2);De(X,{class:"mb-4 bg-border-hard"});var G=V(X,2),me=v(G);{var he=u=>{var Q=vt(),se=v(Q);Ie(se,{}),Ne(2),f(Q),l(u,Q)},ue=u=>{var Q=D(),se=R(Q);{var ge=c=>{lt(c,{get itemCount(){return e(_).length},get itemSize(){return e(re)},get height(){return e(de)},class:"dark:[color-scheme:dark]",get style(){return`--sample-width: ${e(A)??""}px; --sample-height: ${e(ne)??""}px;`},item:(L,C)=>{let $=()=>C==null?void 0:C().index,x=()=>C==null?void 0:C().style;var F=ft();Ke(F,1,`pb-[${j}]`);var H=v(F);ct(H,{get item(){return e(_)[$()]}}),f(F),le(()=>oe(F,x())),l(L,F)},footer:L=>{var C=ht(),$=R(C);je($,()=>e(_).length,H=>{{let E=d(()=>!p().hasNextPage||p().isFetchingNextPage);Ze(H,{get onIntersect(){return e(ie)},get disabled(){return e(E)}})}});var x=V($,2);{var F=H=>{var E=mt(),ee=v(E);Ie(ee,{}),f(E),l(H,E)};W(x,H=>{p().isFetchingNextPage&&H(F)})}l(L,C)},$$slots:{item:!0,footer:!0}})};W(se,c=>{p().isSuccess&&e(_).length>0&&c(ge)},!0)}l(u,Q)};W(me,u=>{p().isPending&&e(_).length===0?u(he):u(ue,!1)})}f(G),ke(G,u=>h(z,u),()=>e(z)),f(J),l(q,J),ye(),b()}function Ft(q,i){const{datasetId:m}=i.data;gt(q,{get datasetId(){return m}})}export{Ft as component};
1
+ import"../chunks/CWj6FrbW.js";import{p as Se,al as I,ab as ze,u as xe,g as e,b as d,Z as h,c as v,s as V,f as R,r as f,t as le,a as ye,w as He,m as _e,am as Ne}from"../chunks/C3xJX0nD.js";import{f as T,c as D,a as l}from"../chunks/CAPx0Bfm.js";import{i as W,a as Te,s as ve}from"../chunks/DmGM9V9Q.js";import{a as We,S as qe,e as Fe,s as oe,u as Oe,k as je,b as Ke}from"../chunks/BDE1kT04.js";import{p as P,r as Qe,b as ke}from"../chunks/xQhUoIl9.js";import{r as Re,u as Ve}from"../chunks/DqhovIS0.js";import{h as Ae,i as te,s as Be,j as Ge,k as Ee,l as Ye,n as Ie,L as Ze}from"../chunks/DgCXCApo.js";import{S as De}from"../chunks/BTpMiPuk.js";import{u as Je}from"../chunks/Bip0vTKl.js";import"../chunks/CmNXvs5e.js";import"../chunks/CEPpkZIV.js";import"../chunks/D9WxTSWa.js";import"../chunks/69_IOA4Y.js";import"../chunks/BHoO7UL_.js";import"../chunks/gBp1tBnA.js";import{I as Ue}from"../chunks/C5oezL0m.js";import{s as Z}from"../chunks/DoEId1MK.js";import{s as Xe}from"../chunks/CpbA3HU7.js";const $e=Be(),et=Ge();var tt=T("<div><!></div>"),it=T("<div><!></div>"),at=T("<div><!></div>"),rt=T("<div><!></div>"),st=T("<div><!></div>"),ot=T("<div><!> <div><!> <!></div> <!></div>");function lt(q,i){Se(i,!0);let m=P(i,"height",3,"100%"),k=P(i,"width",3,"100%"),p=P(i,"stickyIndices",19,()=>[]),M=P(i,"overScan",3,1),b=P(i,"marginLeft",3,0),o=P(i,"marginTop",3,0),O=P(i,"layout",3,"vertical"),w=P(i,"scrollPosition",15,0),ie=P(i,"scrollAlignment",3,"auto"),z=P(i,"scrollBehavior",3,"auto"),fe=P(i,"getKey",3,t=>t),ae=Qe(i,["$$slots","$$events","$$legacy","itemCount","itemSize","height","width","stickyIndices","overScan","marginLeft","marginTop","layout","scrollPosition","scrollAlignment","scrollBehavior","getKey","onscroll","header","item","placeholder","footer"]),_=I(void 0),j=I(ze(w())),re=I(0),A=I(0),ne=I(0),de=I(0),J=I(0),U=I(0),B=I(ze([])),K=!1,X=!1,G=I(!1);function me(t,r=ie(),g=z()){u(ue(t,r),g)}function he(t,r=z()){u(t,r)}const ue=(t,r)=>{const g=e(c)?o()+e(re):b()+e(A),S=t*i.itemSize+g,N=S-e(L)+i.itemSize+g;let a;switch(r){case"start":a=S;break;case"center":a=S-(e(L)-i.itemSize)/2;break;case"end":a=N;break;default:a=Math.max(N,Math.min(S,w()));break}return Math.max(0,Math.min(e(ce)-e(L),a))},u=(t,r=z())=>{e(_)&&(K=!0,e(_).scrollTo({[e(c)?"top":"left"]:t,behavior:r}),K=!1)},Q=t=>{e(_)&&!K&&!X&&(K=!0,e(_).scrollTo({top:t,behavior:z()}),K=!1)},se=t=>{const r=t*i.itemSize;return`position: absolute; transform: translate3d(${e(c)?`${b()}px, ${r+o()}px`:`${e(A)+r+b()}px, ${o()}px`}, 0px); ${e(pe)} will-change: transform;`},ge=t=>{X=!0,K||(e(c)?(h(j,Math.max(0,t.currentTarget.scrollTop-e(re)),!0),w(t.currentTarget.scrollTop)):(h(j,Math.max(0,t.currentTarget.scrollLeft-e(A)),!0),w(t.currentTarget.scrollLeft)),e(C)(e(j))),$e(()=>{X=!1})};let c=d(()=>O()==="vertical"),ce=d(()=>i.itemCount*i.itemSize),pe=d(()=>e(c)?`height: ${i.itemSize}px; width: ${b()>0?`${e(U)-b()}px`:"100%"};`:`height: ${o()>0?`${e(de)-o()}px`:"100%"}; width: ${i.itemSize}px;`),L=d(()=>e(c)?e(ne):e(J));xe(()=>{e(L)&&h(B,Ae(i.itemCount,i.itemSize,e(L),M(),e(j)),!0)}),xe(()=>{e(_)&&Q(w())});let C=d(()=>et(e(L),{fast:()=>{h(G,!0)},slow:()=>{h(G,!1)}}));var $={scrollToIndex:me,scrollToPosition:he},x=ot(),F=t=>{var r;ge(t),(r=i.onscroll)==null||r.call(i,t)};We(x,t=>({onscroll:F,...ae,[qe]:t}),[()=>({position:"relative",overflow:"auto",height:typeof m()=="number"?`${m()}px`:m(),width:typeof k()!="number"?k():`${k()}px`})]);var H=v(x);{var E=t=>{var r=D(),g=R(r);{var S=a=>{var s=tt(),n=v(s);Z(n,()=>i.header),f(s),te(s,"offsetHeight",y=>h(re,y)),l(a,s)},N=a=>{var s=it();oe(s,"",{},{position:"absolute"});var n=v(s);Z(n,()=>i.header),f(s),te(s,"offsetWidth",y=>h(A,y)),l(a,s)};W(g,a=>{e(c)?a(S):a(N,!1)})}l(t,r)};W(H,t=>{i.header&&t(E)})}var ee=V(H,2);let be;var we=v(ee);{var Ce=t=>{const r=d(()=>Math.max(...p().filter(a=>a<e(B)[0])));var g=D(),S=R(g);{var N=a=>{var s=at();let n;var y=v(s);Z(y,()=>i.item,()=>({index:e(r),style:""})),f(s),le(Y=>n=oe(s,"",n,Y),[()=>({position:"sticky",top:e(c)?`${o()}px`:"0px",left:e(c)?"0px":`${b()}px`,"z-index":"1"})]),l(a,s)};W(S,a=>{e(r)>=0&&a(N)})}l(t,g)};W(we,t=>{p().length&&e(B).length&&t(Ce)})}var Pe=V(we,2);Fe(Pe,17,()=>e(B),t=>fe()(t),(t,r)=>{const g=d(()=>se(e(r)));var S=D(),N=R(S);{var a=n=>{var y=D(),Y=R(y);Z(Y,()=>i.item,()=>({index:e(r),style:e(g)})),l(n,y)},s=n=>{var y=D(),Y=R(y);Z(Y,()=>i.placeholder,()=>({index:e(r),style:e(g)})),l(n,y)};W(N,n=>{!e(G)||!i.placeholder?n(a):n(s,!1)})}l(t,S)}),f(ee);var Me=V(ee,2);{var Le=t=>{var r=D(),g=R(r);{var S=a=>{var s=rt(),n=v(s);Z(n,()=>i.footer),f(s),l(a,s)},N=a=>{var s=st();let n;var y=v(s);Z(y,()=>i.footer),f(s),le(Y=>n=oe(s,"",n,Y),[()=>({position:"absolute",top:"0px",left:`${e(A)+i.itemCount*i.itemSize+b()}px`})]),l(a,s)};W(g,a=>{e(c)?a(S):a(N,!1)})}l(t,r)};W(Me,t=>{i.footer&&t(Le)})}return f(x),ke(x,t=>h(_,t),()=>e(_)),le(t=>be=oe(ee,"",be,t),[()=>({height:e(c)?`${e(ce)}px`:"100%",width:e(c)?"100%":`${e(ce)}px`})]),te(x,"offsetHeight",t=>h(ne,t)),te(x,"clientHeight",t=>h(de,t)),te(x,"offsetWidth",t=>h(J,t)),te(x,"clientWidth",t=>h(U,t)),l(q,x),ye($)}const nt=(...q)=>{const i=Re(...q),m=Ee({...i,getNextPageParam:o=>o.nextCursor||void 0}),k=Ve(),p=()=>{k.invalidateQueries({queryKey:i.queryKey})},M=He([]);return m.subscribe(o=>{if(o.isSuccess){const O=o.data.pages.flatMap(w=>w.data);M.set(O)}}),{data:M,loadMore:()=>{_e(m).hasNextPage&&!_e(m).isFetchingNextPage&&_e(m).fetchNextPage()},query:m,refresh:p}};var dt=T('<div class="flex flex-row items-center gap-10"><!> <div class="flex-1 text-sm text-foreground"> </div></div>');function ct(q,i){Se(i,!0);const m=()=>ve(M,"$gridViewSampleRenderingStore",k),[k,p]=Te(),{gridViewSampleRenderingStore:M}=Oe();let b=d(m);var o=dt(),O=v(o);Ye(O,{get sample(){return i.item.sample},get objectFit(){return e(b)}});var w=V(O,2),ie=v(w,!0);f(w),f(o),le(()=>Xe(ie,i.item.text)),l(q,o),ye(),p()}var vt=T('<div class="flex h-full w-full items-center justify-center"><!> <div>Loading samples...</div></div>'),ft=T("<div><!></div>"),mt=T('<div class="flex justify-center p-4"><!></div>'),ht=T("<!> <!>",1),ut=T('<div class="flex flex-1 flex-col space-y-4"><div class="my-2 flex items-center space-x-4"><div class="flex-1"><div class="text-2xl font-semibold">Captions</div></div> <div class="w-4/12"><!></div></div> <!> <div class="h-full w-full flex-1 overflow-hidden"><!></div></div>');function gt(q,i){Se(i,!0);const m=()=>ve(e(O),"$data",M),k=()=>ve(fe,"$sampleSize",M),p=()=>ve(e(w),"$query",M),[M,b]=Te(),o=d(()=>nt({path:{dataset_id:i.datasetId}})),O=d(()=>e(o).data),w=d(()=>e(o).query),ie=d(()=>e(o).loadMore);let z=I(null);const{sampleSize:fe}=Je();let ae=I(0);xe(()=>{if(!e(z))return;h(ae,e(z).clientHeight,!0);const u=new ResizeObserver(()=>{e(z)&&h(ae,e(z).clientHeight,!0)});return u.observe(e(z)),()=>{u.disconnect()}});let _=d(m);const j=16,re=d(()=>k().height+j),A=d(()=>k().width),ne=d(()=>k().height),de=d(()=>e(ae)+j);var J=ut(),U=v(J),B=V(v(U),2),K=v(B);Ue(K,{}),f(B),f(U);var X=V(U,2);De(X,{class:"mb-4 bg-border-hard"});var G=V(X,2),me=v(G);{var he=u=>{var Q=vt(),se=v(Q);Ie(se,{}),Ne(2),f(Q),l(u,Q)},ue=u=>{var Q=D(),se=R(Q);{var ge=c=>{lt(c,{get itemCount(){return e(_).length},get itemSize(){return e(re)},get height(){return e(de)},class:"dark:[color-scheme:dark]",get style(){return`--sample-width: ${e(A)??""}px; --sample-height: ${e(ne)??""}px;`},item:(L,C)=>{let $=()=>C==null?void 0:C().index,x=()=>C==null?void 0:C().style;var F=ft();Ke(F,1,`pb-[${j}]`);var H=v(F);ct(H,{get item(){return e(_)[$()]}}),f(F),le(()=>oe(F,x())),l(L,F)},footer:L=>{var C=ht(),$=R(C);je($,()=>e(_).length,H=>{{let E=d(()=>!p().hasNextPage||p().isFetchingNextPage);Ze(H,{get onIntersect(){return e(ie)},get disabled(){return e(E)}})}});var x=V($,2);{var F=H=>{var E=mt(),ee=v(E);Ie(ee,{}),f(E),l(H,E)};W(x,H=>{p().isFetchingNextPage&&H(F)})}l(L,C)},$$slots:{item:!0,footer:!0}})};W(se,c=>{p().isSuccess&&e(_).length>0&&c(ge)},!0)}l(u,Q)};W(me,u=>{p().isPending&&e(_).length===0?u(he):u(ue,!1)})}f(G),ke(G,u=>h(z,u),()=>e(z)),f(J),l(q,J),ye(),b()}function Ft(q,i){const{datasetId:m}=i.data;gt(q,{get datasetId(){return m}})}export{Ft as component};
@@ -1 +1 @@
1
- {"version":"1761033043766"}
1
+ {"version":"1761579667220"}
@@ -5,17 +5,16 @@
5
5
  <link rel="icon" href="/favicon.png" />
6
6
  <meta name="viewport" content="width=device-width, initial-scale=1" />
7
7
 
8
- <link rel="modulepreload" href="/_app/immutable/entry/start.CvxVp0Cu.js">
9
- <link rel="modulepreload" href="/_app/immutable/chunks/D8ZGoCPm.js">
8
+ <link rel="modulepreload" href="/_app/immutable/entry/start.D6UcpqyO.js">
9
+ <link rel="modulepreload" href="/_app/immutable/chunks/BHoO7UL_.js">
10
10
  <link rel="modulepreload" href="/_app/immutable/chunks/C3xJX0nD.js">
11
11
  <link rel="modulepreload" href="/_app/immutable/chunks/DIeogL5L.js">
12
12
  <link rel="modulepreload" href="/_app/immutable/chunks/CYgJF_JY.js">
13
- <link rel="modulepreload" href="/_app/immutable/entry/app.Y-sSoz5q.js">
13
+ <link rel="modulepreload" href="/_app/immutable/entry/app.CED-eiXl.js">
14
14
  <link rel="modulepreload" href="/_app/immutable/chunks/C1FmrZbK.js">
15
- <link rel="modulepreload" href="/_app/immutable/chunks/WEyXQRi6.js">
15
+ <link rel="modulepreload" href="/_app/immutable/chunks/BbG6fgnL.js">
16
16
  <link rel="modulepreload" href="/_app/immutable/chunks/CWj6FrbW.js">
17
17
  <link rel="modulepreload" href="/_app/immutable/chunks/69_IOA4Y.js">
18
- <link rel="modulepreload" href="/_app/immutable/chunks/BPpOWbDa.js">
19
18
  <link rel="modulepreload" href="/_app/immutable/chunks/CpbA3HU7.js">
20
19
  <link rel="modulepreload" href="/_app/immutable/chunks/SiegjVo0.js">
21
20
  <link rel="modulepreload" href="/_app/immutable/chunks/CAPx0Bfm.js">
@@ -26,15 +25,15 @@
26
25
  <div style="display: contents">
27
26
  <script>
28
27
  {
29
- __sveltekit_6ycv9w = {
28
+ __sveltekit_r7iyvs = {
30
29
  base: ""
31
30
  };
32
31
 
33
32
  const element = document.currentScript.parentElement;
34
33
 
35
34
  Promise.all([
36
- import("/_app/immutable/entry/start.CvxVp0Cu.js"),
37
- import("/_app/immutable/entry/app.Y-sSoz5q.js")
35
+ import("/_app/immutable/entry/start.D6UcpqyO.js"),
36
+ import("/_app/immutable/entry/app.CED-eiXl.js")
38
37
  ]).then(([kit, app]) => {
39
38
  kit.start(app, element);
40
39
  });
@@ -135,17 +135,26 @@ class AnnotationView(SQLModel):
135
135
 
136
136
  annotation_label_name: str
137
137
 
138
+ class AnnotationViewTag(SQLModel):
139
+ """Tag view inside Annotation view."""
140
+
141
+ tag_id: UUID
142
+ name: str
143
+
138
144
  sample_id: UUID
139
145
  dataset_id: UUID
140
146
  annotation_id: UUID
141
147
  annotation_type: AnnotationType
142
148
  annotation_label: AnnotationLabel
143
149
  confidence: Optional[float] = None
150
+ created_at: datetime
144
151
 
145
152
  object_detection_details: Optional[ObjectDetectionAnnotationView] = None
146
153
  instance_segmentation_details: Optional[InstanceSegmentationAnnotationView] = None
147
154
  semantic_segmentation_details: Optional[SemanticSegmentationAnnotationView] = None
148
155
 
156
+ tags: List[AnnotationViewTag] = []
157
+
149
158
 
150
159
  class AnnotationWithSampleView(AnnotationView):
151
160
  """Response model for bounding box annotation."""
@@ -34,6 +34,12 @@ class DatasetView(DatasetBase):
34
34
  updated_at: datetime
35
35
 
36
36
 
37
+ class DatasetViewWithCount(DatasetView):
38
+ """Dataset view with total sample count."""
39
+
40
+ total_sample_count: int
41
+
42
+
37
43
  class DatasetTable(DatasetBase, table=True):
38
44
  """This class defines the Dataset model."""
39
45
 
@@ -49,7 +49,7 @@ class SampleBase(SQLModel):
49
49
  dataset_id: UUID = Field(default=None, foreign_key="datasets.dataset_id")
50
50
 
51
51
  """The dataset image path."""
52
- file_path_abs: str = Field(default=None, unique=True)
52
+ file_path_abs: str = Field(default=None)
53
53
 
54
54
 
55
55
  class SampleCreate(SampleBase):
@@ -0,0 +1,16 @@
1
+ """Database table storing cached 2D embeddings."""
2
+
3
+ from __future__ import annotations
4
+
5
+ from sqlalchemy import ARRAY, Float
6
+ from sqlmodel import Column, Field, SQLModel
7
+
8
+
9
+ class TwoDimEmbeddingTable(SQLModel, table=True):
10
+ """Persisted 2D embedding projection identified by a deterministic hash."""
11
+
12
+ __tablename__ = "two_dim_embeddings"
13
+
14
+ hash: str = Field(primary_key=True)
15
+ x: list[float] = Field(sa_column=Column(ARRAY(Float)))
16
+ y: list[float] = Field(sa_column=Column(ARRAY(Float)))
@@ -11,6 +11,7 @@ from lightly_studio.api.routes.api.validators import Paginated
11
11
  from lightly_studio.models.annotation.annotation_base import (
12
12
  AnnotationBaseTable,
13
13
  )
14
+ from lightly_studio.models.sample import SampleTable
14
15
  from lightly_studio.resolvers.annotations.annotations_filter import (
15
16
  AnnotationsFilter,
16
17
  )
@@ -43,7 +44,8 @@ def get_all(
43
44
  """
44
45
  annotations_statement = select(AnnotationBaseTable)
45
46
 
46
- annotations_statement = annotations_statement.order_by(
47
+ annotations_statement = annotations_statement.join(AnnotationBaseTable.sample).order_by(
48
+ col(SampleTable.file_path_abs).asc(),
47
49
  col(AnnotationBaseTable.created_at).asc(),
48
50
  col(AnnotationBaseTable.annotation_id).asc(),
49
51
  )
@@ -10,7 +10,7 @@ from sqlmodel import Session, and_, col, func, or_, select
10
10
  from sqlmodel.sql.expression import SelectOfScalar
11
11
 
12
12
  from lightly_studio.models.annotation.annotation_base import AnnotationBaseTable
13
- from lightly_studio.models.dataset import DatasetCreate, DatasetTable
13
+ from lightly_studio.models.dataset import DatasetCreate, DatasetTable, DatasetViewWithCount
14
14
  from lightly_studio.models.sample import SampleTable
15
15
  from lightly_studio.models.tag import TagTable
16
16
 
@@ -75,6 +75,23 @@ def get_by_name(session: Session, name: str) -> DatasetTable | None:
75
75
  return session.exec(select(DatasetTable).where(DatasetTable.name == name)).one_or_none()
76
76
 
77
77
 
78
+ def get_dataset_details(session: Session, dataset: DatasetTable) -> DatasetViewWithCount:
79
+ """Convert a DatasetTable to DatasetViewWithCount with computed sample count."""
80
+ sample_count = (
81
+ session.exec(
82
+ select(func.count("*")).where(SampleTable.dataset_id == dataset.dataset_id)
83
+ ).one()
84
+ or 0
85
+ )
86
+ return DatasetViewWithCount(
87
+ dataset_id=dataset.dataset_id,
88
+ name=dataset.name,
89
+ created_at=dataset.created_at,
90
+ updated_at=dataset.updated_at,
91
+ total_sample_count=sample_count,
92
+ )
93
+
94
+
78
95
  def update(session: Session, dataset_id: UUID, dataset_data: DatasetCreate) -> DatasetTable:
79
96
  """Update an existing dataset."""
80
97
  dataset = get_by_id(session=session, dataset_id=dataset_id)
@@ -2,9 +2,10 @@
2
2
 
3
3
  from __future__ import annotations
4
4
 
5
+ import hashlib
5
6
  from uuid import UUID
6
7
 
7
- from sqlalchemy import String, cast
8
+ from sqlalchemy import String, cast, func
8
9
  from sqlmodel import Session, col, select
9
10
 
10
11
  from lightly_studio.models.sample import SampleTable
@@ -81,6 +82,47 @@ def get_all_by_dataset_id(
81
82
  .where(SampleEmbeddingTable.sample_id == SampleTable.sample_id)
82
83
  .where(SampleTable.dataset_id == dataset_id)
83
84
  .where(SampleEmbeddingTable.embedding_model_id == embedding_model_id)
84
- .order_by(col(SampleTable.created_at).asc())
85
+ .order_by(col(SampleTable.file_path_abs).asc())
85
86
  )
86
87
  return list(session.exec(query).all())
88
+
89
+
90
+ def get_hash_by_sample_ids(
91
+ session: Session,
92
+ sample_ids_ordered: list[UUID],
93
+ embedding_model_id: UUID,
94
+ ) -> tuple[str, list[UUID]]:
95
+ """Return a combined hash and the ordered sample IDs with stored embeddings.
96
+
97
+ Args:
98
+ session: Database session.
99
+ sample_ids_ordered: Sample IDs to consider, order defines deterministic hash.
100
+ embedding_model_id: Embedding model identifier.
101
+
102
+ Returns:
103
+ Tuple of (combined hash, ordered sample IDs that have stored embeddings).
104
+ """
105
+ if not sample_ids_ordered:
106
+ return "empty", []
107
+
108
+ rows = session.exec(
109
+ select(
110
+ SampleEmbeddingTable.sample_id,
111
+ func.hash(SampleEmbeddingTable.embedding).label("hash_column"),
112
+ )
113
+ .where(col(SampleEmbeddingTable.sample_id).in_(set(sample_ids_ordered)))
114
+ .where(SampleEmbeddingTable.embedding_model_id == embedding_model_id)
115
+ ).all()
116
+
117
+ # Mypy does not get that 'hash_column' is an attribute of the returned rows
118
+ sample_id_to_hash = {row.sample_id: row.hash_column for row in rows} # type: ignore[attr-defined]
119
+ sample_ids_of_samples_with_embeddings = [
120
+ sample_id for sample_id in sample_ids_ordered if sample_id in sample_id_to_hash
121
+ ]
122
+ hashes_ordered = [
123
+ sample_id_to_hash[sample_id] for sample_id in sample_ids_of_samples_with_embeddings
124
+ ]
125
+
126
+ hasher = hashlib.sha256()
127
+ hasher.update("".join(str(h) for h in hashes_ordered).encode("utf-8"))
128
+ return hasher.hexdigest(), sample_ids_of_samples_with_embeddings
@@ -156,9 +156,7 @@ def get_all_by_dataset_id( # noqa: PLR0913
156
156
  col(SampleTable.sample_id) == col(SampleEmbeddingTable.sample_id),
157
157
  ).where(SampleEmbeddingTable.embedding_model_id == embedding_model_id)
158
158
  else:
159
- samples_query = samples_query.order_by(
160
- col(SampleTable.created_at).asc(), col(SampleTable.sample_id).asc()
161
- )
159
+ samples_query = samples_query.order_by(col(SampleTable.file_path_abs).asc())
162
160
 
163
161
  # Apply pagination if provided
164
162
  if pagination is not None:
@@ -1,14 +1,104 @@
1
- """Handler for getting 2D embeddings from high-dimensional embeddings."""
1
+ """Handler for getting cached 2D embeddings from high-dimensional embeddings."""
2
2
 
3
3
  from __future__ import annotations
4
4
 
5
+ from uuid import UUID
6
+
7
+ import numpy as np
5
8
  from lightly_mundig import TwoDimEmbedding # type: ignore[import-untyped]
9
+ from numpy.typing import NDArray
10
+ from sqlmodel import Session, col, select
6
11
 
7
12
  from lightly_studio.dataset.env import LIGHTLY_STUDIO_LICENSE_KEY
13
+ from lightly_studio.models.embedding_model import EmbeddingModelTable
14
+ from lightly_studio.models.sample import SampleTable
15
+ from lightly_studio.models.two_dim_embedding import TwoDimEmbeddingTable
16
+ from lightly_studio.resolvers import sample_embedding_resolver
17
+
18
+
19
+ def get_twodim_embeddings(
20
+ session: Session,
21
+ dataset_id: UUID,
22
+ embedding_model_id: UUID,
23
+ ) -> tuple[NDArray[np.float32], NDArray[np.float32], list[UUID]]:
24
+ """Return cached 2D embeddings together with their sample identifiers.
25
+
26
+ Uses a cache to avoid recomputing the 2D embeddings. The cache key combines the sorted
27
+ sample identifiers with a deterministic 64-bit hash over the stored high-dimensional
28
+ embeddings.
29
+
30
+ Args:
31
+ session: Database session.
32
+ dataset_id: Dataset identifier.
33
+ embedding_model_id: Embedding model identifier.
34
+
35
+ Returns:
36
+ Tuple of (x coordinates, y coordinates, ordered sample IDs).
37
+ """
38
+ embedding_model = session.get(EmbeddingModelTable, embedding_model_id)
39
+ if embedding_model is None:
40
+ raise ValueError(f"Embedding model {embedding_model_id} not found.")
41
+
42
+ # Define a fixed order of sample IDs for the cache key.
43
+ sample_ids_ordered = list(
44
+ session.exec(
45
+ select(SampleTable.sample_id)
46
+ .where(SampleTable.dataset_id == dataset_id)
47
+ .order_by(col(SampleTable.sample_id).asc())
48
+ ).all()
49
+ )
50
+
51
+ # Check if we have a cached 2D embedding for the given samples and embedding model.
52
+ # The order is defined by sample_ids_ordered.
53
+ cache_key, sample_ids_of_samples_with_embeddings = (
54
+ sample_embedding_resolver.get_hash_by_sample_ids(
55
+ session=session,
56
+ sample_ids_ordered=sample_ids_ordered,
57
+ embedding_model_id=embedding_model_id,
58
+ )
59
+ )
60
+
61
+ if not sample_ids_of_samples_with_embeddings:
62
+ empty = np.array([], dtype=np.float32)
63
+ return empty, empty, []
64
+
65
+ # If there is a cached entry, return it.
66
+ cached = session.get(TwoDimEmbeddingTable, cache_key)
67
+ if cached is not None:
68
+ x_values = np.array(cached.x, dtype=np.float32)
69
+ y_values = np.array(cached.y, dtype=np.float32)
70
+ return x_values, y_values, sample_ids_of_samples_with_embeddings
71
+
72
+ # No cached entry found - load the high-dimensional embeddings.
73
+ # The order is defined by sample_ids_of_samples_with_embeddings.
74
+ sample_embeddings = sample_embedding_resolver.get_by_sample_ids(
75
+ session=session,
76
+ sample_ids=sample_ids_of_samples_with_embeddings,
77
+ embedding_model_id=embedding_model_id,
78
+ )
79
+
80
+ # If there are no embeddings, return empty arrays.
81
+ if not sample_embeddings:
82
+ empty = np.array([], dtype=np.float32)
83
+ return empty, empty, []
84
+
85
+ # Compute the 2D embedding from the high-dimensional embeddings.
86
+ # The order is now defined by sample_embeddings. They are the ordered subset of the
87
+ # sample_ids_of_samples_with_embeddings that have embeddings.
88
+ sample_ids_of_samples_with_embeddings = [embedding.sample_id for embedding in sample_embeddings]
89
+ embedding_values = [embedding.embedding for embedding in sample_embeddings]
90
+ planar_embeddings = _calculate_2d_embeddings(embedding_values)
91
+ embeddings_2d = np.asarray(planar_embeddings, dtype=np.float32)
92
+ x_values, y_values = embeddings_2d[:, 0], embeddings_2d[:, 1]
93
+
94
+ # Write the computed 2D embeddings to the cache.
95
+ cache_entry = TwoDimEmbeddingTable(hash=cache_key, x=list(x_values), y=list(y_values))
96
+ session.add(cache_entry)
97
+ session.commit()
98
+
99
+ return x_values, y_values, sample_ids_of_samples_with_embeddings
8
100
 
9
101
 
10
- # TODO(Malte, 10/2025): Add the get_twodim_embeddings function here that handles the
11
- # caching in the DB and calls _calculate_2d_embeddings when needed.
12
102
  def _calculate_2d_embeddings(embedding_values: list[list[float]]) -> list[tuple[float, float]]:
13
103
  n_samples = len(embedding_values)
14
104
  # For 0, 1 or 2 samples we hard-code deterministic coordinates.