cubevis 1.0.38__py3-none-any.whl → 1.0.44__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.
@@ -42,15 +42,15 @@
42
42
  }
43
43
  })
44
44
  ({
45
- "07c9fde72b": function _(e,a,t,o,c){o();const i=e("tslib"),n=e("4406a037f1");c("DataPipe",n.DataPipe);c("activeDataPipes",e("5179d11e71").activeDataPipes);const p=e("2889e0dd45");c("ImagePipe",p.ImagePipe);const s=e("de65005924");c("ImageDataSource",s.ImageDataSource);const r=e("02e3c3e46c");c("SpectraDataSource",r.SpectraDataSource);const S=e("64b16deff9");c("UpdatableDataSource",S.UpdatableDataSource);const d=e("b6ae454f0d");c("WcsTicks",d.WcsTicks);const l=e("cb7d28d6b3");c("DragTool",l.DragTool);const D=e("9d3c34ff8e");c("CBResetTool",D.CBResetTool);const T=e("e3901fa9f2");c("serialize",T.serialize),c("deserialize",T.deserialize);const b=e("9f961622ce");c("TipButton",b.TipButton);const u=e("ca4c845905");c("Tip",u.Tip);const f=e("a6e757a69a");c("Showable",f.Showable);const P=e("467d2716b0");c("BokehAppContext",P.BokehAppContext);const g=e("50a1e32f01");c("SharedDict",g.SharedDict);const h=e("b55081402e");c("EditSpan",h.EditSpan);const B=e("9144bfc7a5");c("EvTextInput",B.EvTextInput);const E=e("74e0abef8a");c("EvPolyAnnotation",E.EvPolyAnnotation);const I=i.__importStar(e("484bb85d20"));t.find=I;(0,e("@bokehjs/base").register_models)({DataPipe:n.DataPipe,ImagePipe:p.ImagePipe,ImageDataSource:s.ImageDataSource,SpectraDataSource:r.SpectraDataSource,UpdatableDataSource:S.UpdatableDataSource,WcsTicks:d.WcsTicks,DragTool:l.DragTool,CBResetTool:D.CBResetTool,Tip:u.Tip,TipButton:b.TipButton,SharedDict:g.SharedDict,Showable:f.Showable,BokehAppContext:P.BokehAppContext,EditSpan:h.EditSpan,EvTextInput:B.EvTextInput,EvPolyAnnotation:E.EvPolyAnnotation})},
46
- "4406a037f1": function _(e,s,t,o,i){var n;o();const c=e("@bokehjs/models/sources/data_source"),a=e("e3901fa9f2"),l=e("@bokehjs/core/util/callbacks"),r=e("5179d11e71");class d extends c.DataSource{constructor(e){super(e),this.send_queue={},this.connection_queue=[],this.pending={},this.incoming_callbacks={},this.session_id=casalib.object_id(this)}isColab(){return void 0!==window.google&&void 0!==window.google.colab&&void 0!==window.google.colab.kernel}async getWebSocketUrl(){const[e,s]=this.address;if(this.isColab())try{const e=window.google,t=(await e.colab.kernel.proxyPort(s,{cache:!0})).replace(/^https:/,"wss:");return console.log(`Colab proxy URL for port ${s}: ${t}`),t}catch(t){return console.error("Error getting Colab proxy URL:",t),`ws://${e}:${s}`}return`ws://${e}:${s}`}checkSessionConflict(){try{if("undefined"==typeof Storage)return console.warn("localStorage not available, skipping session conflict detection"),!0;const e=localStorage.getItem(this.session_storage_key);if(e){const s=JSON.parse(e);if(s.sessionId!==this.session_id&&Date.now()-s.timestamp<12e4){if(this.conflict_check){const e=`CubeVis DataPipe (${this.instance_key}) is already running in another browser window or tab.\n\nPlease close other instances and refresh this page, or\nclose this window to continue using the other instance.`;return alert(e),window.opener||1===window.history.length?window.close():window.location.href="about:blank",!1}console.group(`DataPipe ${this.instance_key} conflict detected in Jupyter context`),console.log("Current session ID:",this.session_id),console.log("Existing session ID:",s.sessionId),console.log("Existing timestamp:",new Date(s.timestamp).toISOString()),console.log("Age of existing session (ms):",Date.now()-s.timestamp),console.log("Address:",this.address),console.log("Instance key:",this.instance_key),console.log("Storage key:",this.session_storage_key),console.log("Existing data:",s),console.log("All localStorage keys:",Object.keys(localStorage).filter((e=>e.startsWith("cubevis_datapipe_")))),console.groupEnd()}}return this.updateSessionHeartbeat(),!0}catch(e){return console.warn("Session conflict detection failed:",e),!0}}updateSessionHeartbeat(){try{"undefined"!=typeof Storage&&localStorage.setItem(this.session_storage_key,JSON.stringify({sessionId:this.session_id,timestamp:Date.now(),instanceKey:this.instance_key}))}catch(e){console.warn("Session heartbeat update failed:",e)}}startHeartbeat(){this.heartbeat_interval=window.setInterval((()=>{this.updateSessionHeartbeat()}),3e4)}stopHeartbeat(){this.heartbeat_interval&&(clearInterval(this.heartbeat_interval),this.heartbeat_interval=void 0)}cleanupSession(){try{if("undefined"!=typeof Storage){const e=localStorage.getItem(this.session_storage_key);if(e){JSON.parse(e).sessionId===this.session_id&&localStorage.removeItem(this.session_storage_key)}}}catch(e){console.warn("Session cleanup failed:",e)}this.stopHeartbeat()}handleSessionConflictMessage(e){console.error("Session conflict detected by server:",e);let s="Session conflict detected by server.";"session_conflict"===e.type?s=e.error||s:"session_corruption"===e.type&&(s=`Session corruption detected.\nExpected: ${e.expected}\nReceived: ${e.received}`),alert(s+"\n\nThis window will be closed to prevent data corruption."),this.cleanupSession();const t=new CustomEvent("cubevis_session_conflict",{detail:{message:e,sessionId:this.session_id}});window.dispatchEvent(t),setTimeout((()=>{window.opener||1===window.history.length?window.close():window.location.href="about:blank"}),2e3)}generateInstanceKey(){const e=`${this.address[0]}_${this.address[1]}`;return`${this.instance_id}_${e}`}async initializeWebSocket(){let e;if(this.isColab()){const[s,t]=this.address;console.log("=== Colab WebSocket Debug ==="),console.log("Port:",t);try{let s=null;const o=document.referrer;console.log("Referrer:",o),window.colab&&window.colab.global&&window.colab.global.config&&console.log("Colab config:",window.colab.global.config);try{window.parent&&window.parent.location&&console.log("Parent location:",window.parent.location.href)}catch(e){console.log("Cannot access parent location (CORS)")}const i=window.location.hostname.match(/([^-]+)-([^-]+)-\d+-colab/);if(i){const e=i[1],s=i[2];console.log("Session ID:",e,"Hash:",s)}const n=window.google;if(n&&n.colab&&n.colab.kernel){const e=Object.keys(n.colab.kernel);console.log("Available kernel properties:",e);for(const s of e){const e=n.colab.kernel[s];console.log(` ${s}:`,typeof e,e)}n.colab.kernel.websocketUrl&&(console.log("Kernel WebSocket URL:",n.colab.kernel.websocketUrl),s=n.colab.kernel.websocketUrl)}if(s){const o=s.match(/wss?:\/\/([^\/]+)/);o?(e=`wss://${o[1]}/_proxy/${t}/`,console.log("Constructed kernel proxy URL:",e)):e=`wss://${s}/_proxy/${t}/`}else{console.log("Could not determine kernel domain, trying message passing..."),window.parent.postMessage({type:"request_kernel_domain"},"*");const s=await n.colab.kernel.proxyPort(t,{cache:!0});e=s.replace(/^https:/,"wss:"),console.log("Using googleusercontent proxy (may not work):",e)}}catch(o){console.error("Error in Colab proxy detection:",o),e=`ws://${s}:${t}`}console.log("=== End Debug ===")}else e=`ws://${this.address[0]}:${this.address[1]}`;console.log("Final datapipe url:",e);var s=void 0;document.shutdown_in_progress_=!1;var t=()=>{void 0!==this.websocket&&this.websocket.close(),this.websocket=new WebSocket(e),this.websocket.binaryType="arraybuffer",this.websocket.addEventListener("error",(e=>{console.log("error encountered:",e)})),this.websocket.onmessage=e=>{if("string"==typeof e.data||e.data instanceof String){let s=(0,a.deserialize)(e.data);if("id"in s&&"direction"in s&&"message"in s){let{id:e,message:t,direction:o}=s;if("error"===o&&("session_conflict"===e||e===this.session_id)&&t&&("session_conflict"===t.type||"session_corruption"===t.type||"close_duplicate"===t.action))return void this.handleSessionConflictMessage(t);if(void 0===t&&console.log("Error, event failure",s),"j2p"==o)if(e in this.pending){let{cb:o}=this.pending[e];if(delete this.pending[e],e in this.send_queue&&this.send_queue[e].length>0){let{cb:s,msg:t}=this.send_queue[e].shift();this.pending[e]={cb:s},this.websocket.send((0,a.serialize)(t))}void 0===t?console.log("DROPPING ERROR FOR NOW (maybe need error callbacks)",s):o(t)}else console.log("message received but could not find id");else if(e in this.incoming_callbacks){let s=this.incoming_callbacks[e](t);this.websocket.send((0,a.serialize)({id:e,direction:o,message:s,session:this.session_id}))}}else console.log(`datapipe received message without one of 'id', 'message' or 'direction': ${s}`)}else console.log("datapipe received binary data",e.data.byteLength,"bytes")},this.websocket.onopen=()=>{for(s?0==s.connected&&console.log(`connection reestablished at ${new Date}`):(this.websocket.send((0,a.serialize)({id:"initialize",direction:"j2p",session:this.session_id})),this.startHeartbeat()),s=new casalib.ReconnectState;this.connection_queue.length>0;){let e=this.connection_queue.shift();this.send.apply(e[0],e[1])}},this.websocket.onclose=()=>{if(s&&1==s.connected&&(console.log(`connection lost at ${new Date}`),s.connected=!1,!document.shutdown_in_progress_)){console.log(`connection lost at ${new Date}`);var e=s;function o(i){0==s.connected&&(console.log(`${i+1}\treconnection attempt ${new Date}`),t(),e.backoff(),e.retries>0?setTimeout(o,e.timeout,i+1):0==s.connected&&console.log(`aborting reconnection after ${i} attempts ${new Date}`))}o(0)}}};window.addEventListener("beforeunload",(()=>{this.cleanupSession()})),document.addEventListener("visibilitychange",(()=>{"hidden"===document.visibilityState?this.stopHeartbeat():"visible"===document.visibilityState&&(this.updateSessionHeartbeat(),this.startHeartbeat())})),t()}initialize(){if(super.initialize(),r.activeDataPipes.register(this),this.instance_key=this.generateInstanceKey(),this.session_storage_key=`cubevis_datapipe_${this.instance_key}`,!this.checkSessionConflict())return;this.initializeWebSocket();(()=>{null!=this.init_script&&(0,l.execute)(this.init_script,this)})()}destroy(){r.activeDataPipes.unregister(this),super.destroy()}register(e,s){this.incoming_callbacks[e]=s}send(e,s,t,o=!1){let i={id:e,message:s,direction:"j2p",session:this.session_id};if(!this.websocket||e in this.pending)if(e in this.send_queue)if("boolean"==typeof o&&o&&this.send_queue[e].length>0)this.send_queue[e][0].msg=i,this.send_queue[e][0].cb=t;else if("function"==typeof o&&this.send_queue[e].length>0){let n=!1;for(const c of this.send_queue[e])o(c.msg.message)&&(c.msg=i,c.cb=t,n=!0);n||this.send_queue[e].push({cb:t,msg:i})}else this.send_queue[e].push({cb:t,msg:i});else this.send_queue[e]=[{cb:t,msg:i}];else if(this.websocket.readyState===WebSocket.CONNECTING)this.connection_queue.push([this,[e,s,t]]);else if(e in this.send_queue&&this.send_queue[e].length>0){this.send_queue[e].push({cb:t,msg:i});{let{cb:l,msg:r}=this.send_queue[e].shift();if(this.pending[e]={cb:l},this.websocket.readyState===WebSocket.OPEN)this.websocket.send((0,a.serialize)(r));else{let d=20,h=this;function g(){h.websocket.readyState===WebSocket.OPEN?h.websocket.send((0,a.serialize)(r)):(d-=1,d>0&&setTimeout(g,3e3))}setTimeout(g,3e3)}}}else if(this.websocket.readyState===WebSocket.OPEN)this.pending[e]={cb:t},this.websocket.send((0,a.serialize)(i));else{let u=20,b=this;function p(){b.websocket.readyState===WebSocket.OPEN?(b.pending[e]={cb:t},b.websocket.send((0,a.serialize)(i))):(u-=1,u>0&&setTimeout(p,3e3))}setTimeout(p,3e3)}}}t.DataPipe=d,n=d,d.__name__="DataPipe",d.__module__="cubevis.bokeh.sources._data_pipe",n.define((({Any:e,Tuple:s,String:t,Number:o,Bool:i})=>({init_script:[e,null],address:[s(t,o)],instance_id:[t],conflict_check:[i,!0]})))},
45
+ "07c9fde72b": function _(e,a,t,o,c){o();const i=e("tslib"),n=e("7a1eeba81e");c("DataPipe",n.DataPipe);c("activeDataPipes",e("5179d11e71").activeDataPipes);const p=e("2889e0dd45");c("ImagePipe",p.ImagePipe);const s=e("de65005924");c("ImageDataSource",s.ImageDataSource);const r=e("02e3c3e46c");c("SpectraDataSource",r.SpectraDataSource);const S=e("64b16deff9");c("UpdatableDataSource",S.UpdatableDataSource);const d=e("b6ae454f0d");c("WcsTicks",d.WcsTicks);const l=e("cb7d28d6b3");c("DragTool",l.DragTool);const D=e("9d3c34ff8e");c("CBResetTool",D.CBResetTool);const T=e("e3901fa9f2");c("serialize",T.serialize),c("deserialize",T.deserialize);const b=e("9f961622ce");c("TipButton",b.TipButton);const u=e("ca4c845905");c("Tip",u.Tip);const P=e("a6e757a69a");c("Showable",P.Showable);const f=e("467d2716b0");c("BokehAppContext",f.BokehAppContext);const g=e("50a1e32f01");c("SharedDict",g.SharedDict);const h=e("b55081402e");c("EditSpan",h.EditSpan);const B=e("9144bfc7a5");c("EvTextInput",B.EvTextInput);const E=e("74e0abef8a");c("EvPolyAnnotation",E.EvPolyAnnotation);const I=i.__importStar(e("484bb85d20"));t.find=I;(0,e("@bokehjs/base").register_models)({DataPipe:n.DataPipe,ImagePipe:p.ImagePipe,ImageDataSource:s.ImageDataSource,SpectraDataSource:r.SpectraDataSource,UpdatableDataSource:S.UpdatableDataSource,WcsTicks:d.WcsTicks,DragTool:l.DragTool,CBResetTool:D.CBResetTool,Tip:u.Tip,TipButton:b.TipButton,SharedDict:g.SharedDict,Showable:P.Showable,BokehAppContext:f.BokehAppContext,EditSpan:h.EditSpan,EvTextInput:B.EvTextInput,EvPolyAnnotation:E.EvPolyAnnotation})},
46
+ "7a1eeba81e": function _(e,t,s,i,n){var o;i();const a=e("@bokehjs/models/sources/data_source"),c=e("e3901fa9f2"),r=e("@bokehjs/core/util/callbacks"),l=e("5179d11e71");class d extends a.DataSource{constructor(e){super(e),this.send_queue={},this.connection_queue=[],this.pending={},this.incoming_callbacks={},this.session_id=casalib.object_id(this)}checkSessionConflict(){try{if("undefined"==typeof Storage)return console.warn("localStorage not available, skipping session conflict detection"),!0;const e=localStorage.getItem(this.session_storage_key);if(e){const t=JSON.parse(e);if(t.sessionId!==this.session_id&&Date.now()-t.timestamp<12e4){if(this.conflict_check){const e=`CubeVis DataPipe (${this.instance_key}) is already running in another browser window or tab.\n\nPlease close other instances and refresh this page, or\nclose this window to continue using the other instance.`;return alert(e),window.opener||1===window.history.length?window.close():window.location.href="about:blank",!1}console.group(`DataPipe ${this.instance_key} conflict detected in Jupyter context`),console.log("Current session ID:",this.session_id),console.log("Existing session ID:",t.sessionId),console.log("Existing timestamp:",new Date(t.timestamp).toISOString()),console.log("Age of existing session (ms):",Date.now()-t.timestamp),console.log("Backend IP:",this.backend_ip),console.log("Backend Port:",this.backend_port),console.log("Backend URL:",this.backend_url),console.log("Instance key:",this.instance_key),console.log("Storage key:",this.session_storage_key),console.log("Existing data:",t),console.log("All localStorage keys:",Object.keys(localStorage).filter((e=>e.startsWith("cubevis_datapipe_")))),console.groupEnd()}}return this.updateSessionHeartbeat(),!0}catch(e){return console.warn("Session conflict detection failed:",e),!0}}updateSessionHeartbeat(){try{"undefined"!=typeof Storage&&localStorage.setItem(this.session_storage_key,JSON.stringify({sessionId:this.session_id,timestamp:Date.now(),instanceKey:this.instance_key}))}catch(e){console.warn("Session heartbeat update failed:",e)}}startHeartbeat(){this.heartbeat_interval=window.setInterval((()=>{this.updateSessionHeartbeat()}),3e4)}stopHeartbeat(){this.heartbeat_interval&&(clearInterval(this.heartbeat_interval),this.heartbeat_interval=void 0)}cleanupSession(){try{if("undefined"!=typeof Storage){const e=localStorage.getItem(this.session_storage_key);if(e){JSON.parse(e).sessionId===this.session_id&&localStorage.removeItem(this.session_storage_key)}}}catch(e){console.warn("Session cleanup failed:",e)}this.stopHeartbeat()}handleSessionConflictMessage(e){console.error("Session conflict detected by server:",e);let t="Session conflict detected by server.";"session_conflict"===e.type?t=e.error||t:"session_corruption"===e.type&&(t=`Session corruption detected.\nExpected: ${e.expected}\nReceived: ${e.received}`),alert(t+"\n\nThis window will be closed to prevent data corruption."),this.cleanupSession();const s=new CustomEvent("cubevis_session_conflict",{detail:{message:e,sessionId:this.session_id}});window.dispatchEvent(s),setTimeout((()=>{window.opener||1===window.history.length?window.close():window.location.href="about:blank"}),2e3)}generateInstanceKey(){return`${this.instance_id}_${this.backend_port}`}async initializeWebSocket(){console.log(" datapipe url:",this.backend_url),console.log(`datapipe ip/port: ${this.backend_ip}/${this.backend_port}`);var e=void 0;document.shutdown_in_progress_=!1;var t=async()=>{void 0!==this.websocket&&this.websocket.close();const s=this.backend_url,i=s.replace("wss://","https://");try{console.log(" priming proxy session..."),await fetch(i,{mode:"no-cors"}),this.websocket=new WebSocket(s),this.websocket.binaryType="arraybuffer"}catch(e){console.error("Proxy wake-up failed",e),this.websocket=new WebSocket(s),this.websocket.binaryType="arraybuffer"}this.websocket.addEventListener("error",(e=>{console.log("error encountered:",e)})),this.websocket.onmessage=e=>{if("string"==typeof e.data||e.data instanceof String){let t=(0,c.deserialize)(e.data);if("id"in t&&"direction"in t&&"message"in t){let{id:e,message:s,direction:i}=t;if("error"===i&&("session_conflict"===e||e===this.session_id)&&s&&("session_conflict"===s.type||"session_corruption"===s.type||"close_duplicate"===s.action))return void this.handleSessionConflictMessage(s);if(void 0===s&&console.log("Error, event failure",t),"j2p"==i)if(e in this.pending){let{cb:i}=this.pending[e];if(delete this.pending[e],e in this.send_queue&&this.send_queue[e].length>0){let{cb:t,msg:s}=this.send_queue[e].shift();this.pending[e]={cb:t},this.websocket.send((0,c.serialize)(s))}void 0===s?console.log("DROPPING ERROR FOR NOW (maybe need error callbacks)",t):i(s)}else console.log("message received but could not find id");else if(e in this.incoming_callbacks){let t=this.incoming_callbacks[e](s);this.websocket.send((0,c.serialize)({id:e,direction:i,message:t,session:this.session_id}))}}else console.log(`datapipe received message without one of 'id', 'message' or 'direction': ${t}`)}else console.log("datapipe received binary data",e.data.byteLength,"bytes")},this.websocket.onopen=()=>{for(console.log(">>> DATAPIPE CONNECTED"),e?0==e.connected&&console.log(`connection reestablished at ${new Date}`):(this.websocket.send((0,c.serialize)({id:"initialize",direction:"j2p",session:this.session_id})),this.startHeartbeat()),e=new casalib.ReconnectState;this.connection_queue.length>0;){let e=this.connection_queue.shift();this.send.apply(e[0],e[1])}},this.websocket.onclose=()=>{if(e&&1==e.connected&&(console.log(`connection lost at ${new Date}`),e.connected=!1,!document.shutdown_in_progress_)){console.log(`connection lost at ${new Date}`);var s=e;function i(n){0==e.connected&&(console.log(`${n+1}\treconnection attempt ${new Date}`),t(),s.backoff(),s.retries>0?setTimeout(i,s.timeout,n+1):0==e.connected&&console.log(`aborting reconnection after ${n} attempts ${new Date}`))}i(0)}}};window.addEventListener("beforeunload",(()=>{this.cleanupSession()})),document.addEventListener("visibilitychange",(()=>{"hidden"===document.visibilityState?this.stopHeartbeat():"visible"===document.visibilityState&&(this.updateSessionHeartbeat(),this.startHeartbeat())})),t()}initialize(){if(super.initialize(),l.activeDataPipes.register(this),this.instance_key=this.generateInstanceKey(),this.session_storage_key=`cubevis_datapipe_${this.instance_key}`,!this.checkSessionConflict())return;this.initializeWebSocket();(()=>{null!=this.init_script&&(0,r.execute)(this.init_script,this)})()}destroy(){l.activeDataPipes.unregister(this),super.destroy()}register(e,t){this.incoming_callbacks[e]=t}send(e,t,s,i=!1){let n={id:e,message:t,direction:"j2p",session:this.session_id};if(!this.websocket||e in this.pending)if(e in this.send_queue)if("boolean"==typeof i&&i&&this.send_queue[e].length>0)this.send_queue[e][0].msg=n,this.send_queue[e][0].cb=s;else if("function"==typeof i&&this.send_queue[e].length>0){let o=!1;for(const a of this.send_queue[e])i(a.msg.message)&&(a.msg=n,a.cb=s,o=!0);o||this.send_queue[e].push({cb:s,msg:n})}else this.send_queue[e].push({cb:s,msg:n});else this.send_queue[e]=[{cb:s,msg:n}];else if(this.websocket.readyState===WebSocket.CONNECTING)this.connection_queue.push([this,[e,t,s]]);else if(e in this.send_queue&&this.send_queue[e].length>0){this.send_queue[e].push({cb:s,msg:n});{let{cb:r,msg:l}=this.send_queue[e].shift();if(this.pending[e]={cb:r},this.websocket.readyState===WebSocket.OPEN)this.websocket.send((0,c.serialize)(l));else{let d=20,h=this;function u(){h.websocket.readyState===WebSocket.OPEN?h.websocket.send((0,c.serialize)(l)):(d-=1,d>0&&setTimeout(u,3e3))}setTimeout(u,3e3)}}}else if(this.websocket.readyState===WebSocket.OPEN)this.pending[e]={cb:s},this.websocket.send((0,c.serialize)(n));else{let b=20,g=this;function p(){g.websocket.readyState===WebSocket.OPEN?(g.pending[e]={cb:s},g.websocket.send((0,c.serialize)(n))):(b-=1,b>0&&setTimeout(p,3e3))}setTimeout(p,3e3)}}}s.DataPipe=d,o=d,d.__name__="DataPipe",d.__module__="cubevis.bokeh.sources._data_pipe",o.define((({Any:e,Str:t,Int:s,Bool:i,Nullable:n})=>({init_script:[n(e),null],backend_ip:[t,"127.0.0.1"],backend_port:[s],backend_url:[t],instance_id:[t],conflict_check:[i,!0]})))},
47
47
  "e3901fa9f2": function _(e,r,s,i,o){i();const l=e("@bokehjs/base"),a=e("@bokehjs/core/resolvers"),t=e("@bokehjs/core/serialization/deserializer"),n=e("@bokehjs/core/serialization/serializer"),{deserialize:c}=new class{constructor(){this.resolver=new a.ModelResolver(l.default_resolver),this.deserializer=new t.Deserializer(this.resolver),this.deserialize=e=>{try{return this.deserializer.decode(JSON.parse(e))}catch(r){return console.group("deserialize error"),console.log(e),console.log(r),console.groupEnd(),{}}}}};s.deserialize=c;const{serialize:z}=new class{constructor(){this.serializer=new n.Serializer,this.serialize=e=>JSON.stringify(this.serializer.encode(e))}};s.serialize=z},
48
48
  "5179d11e71": function _(a,e,n,c,t){c();const i=a("30b45c52a1");n.activeDataPipes=new i.ModelManager},
49
49
  "30b45c52a1": function _(e,n,s,t,i){t();class r{constructor(){this.instances=new Map}register(e){this.instances.set(e.id,e),console.log(`registered instance ${e.id}`)}unregister(e){this.instances.delete(e.id),console.log(`unregistered instance ${e.id}`)}getInstances(){return Array.from(this.instances.values())}getInstance(e){return this.instances.get(e)}}s.ModelManager=r,r.__name__="ModelManager"},
50
- "2889e0dd45": function _(i,s,e,t,n){var a;t();const o=i("@bokehjs/models/sources/column_data_source"),d=i("4406a037f1");class r extends d.DataPipe{constructor(i){super(i),this.position={},this._wcs=null}initialize(){super.initialize(),this.fits_header_json&&(this._wcs=new casalib.coordtxl.WCSTransform(new casalib.coordtxl.MapKeywordProvider(JSON.parse(this.fits_header_json))))}channel(i,s,e){this.position[e]={index:i};let t={action:"channel",index:i,id:e};super.send(this.dataid,t,(i=>{null!=this._histogram_source&&"hist"in i&&"top"in i.hist&&"bottom"in i.hist&&"left"in i.hist&&"right"in i.hist&&(this._histogram_source.data=i.hist),s(i)}))}spectrum(i,s,e,t=!1){let n={action:"spectrum",index:i,id:e};super.send(this.dataid,n,s,t)}adjust_colormap(i,s,e,t,n=!1){const a={action:"adjust-colormap",bounds:i,transfer:s,id:t};super.send(this.dataid,a,e,n)}refresh(i,s,e=[0,0]){let{index:t}=s in this.position?this.position[s]:{index:e};if(2===t.length){let e={action:"channel",index:t,id:s};super.send(this.dataid,e,i)}else if(3===t.length){let e={action:"spectrum",index:t,id:s};super.send(this.dataid,e,i)}}wcs(){return this._wcs}}e.ImagePipe=r,a=r,r.__name__="ImagePipe",r.__module__="cubevis.bokeh.sources._image_pipe",a.define((({Number:i,Nullable:s,String:e,Tuple:t,Ref:n})=>({dataid:[e],shape:[t(i,i,i,i)],fits_header_json:[s(e),null],_histogram_source:[s(n(o.ColumnDataSource)),null]})))},
50
+ "2889e0dd45": function _(i,e,s,t,n){var a;t();const o=i("@bokehjs/models/sources/column_data_source"),d=i("7a1eeba81e");class r extends d.DataPipe{constructor(i){super(i),this.position={},this._wcs=null}initialize(){super.initialize(),this.fits_header_json&&(this._wcs=new casalib.coordtxl.WCSTransform(new casalib.coordtxl.MapKeywordProvider(JSON.parse(this.fits_header_json))))}channel(i,e,s){this.position[s]={index:i};let t={action:"channel",index:i,id:s};super.send(this.dataid,t,(i=>{null!=this._histogram_source&&"hist"in i&&"top"in i.hist&&"bottom"in i.hist&&"left"in i.hist&&"right"in i.hist&&(this._histogram_source.data=i.hist),e(i)}))}spectrum(i,e,s,t=!1){let n={action:"spectrum",index:i,id:s};super.send(this.dataid,n,e,t)}adjust_colormap(i,e,s,t,n=!1){const a={action:"adjust-colormap",bounds:i,transfer:e,id:t};super.send(this.dataid,a,s,n)}refresh(i,e,s=[0,0]){let{index:t}=e in this.position?this.position[e]:{index:s};if(2===t.length){let s={action:"channel",index:t,id:e};super.send(this.dataid,s,i)}else if(3===t.length){let s={action:"spectrum",index:t,id:e};super.send(this.dataid,s,i)}}wcs(){return this._wcs}}s.ImagePipe=r,a=r,r.__name__="ImagePipe",r.__module__="cubevis.bokeh.sources._image_pipe",a.define((({Number:i,Nullable:e,String:s,Tuple:t,Ref:n})=>({dataid:[s],shape:[t(i,i,i,i)],fits_header_json:[e(s),null],_histogram_source:[e(n(o.ColumnDataSource)),null]})))},
51
51
  "de65005924": function _(s,a,t,c,i){var o;c();const e=s("@bokehjs/models/sources/column_data_source"),n=s("@bokehjs/core/util/string"),u=s("2889e0dd45"),h=s("@bokehjs/core/util/callbacks");class r extends e.ColumnDataSource{constructor(s){super(s),this.imid=(0,n.uuid4)()}_mask_contour(s){const a=casalib.d3.contours().size(this.image_source.shape.slice(0,2)).thresholds([1])(s[0])[0].coordinates.map((s=>s.map((s=>s.reduce(((s,a)=>(s[0].push(a[0]),s[1].push(a[1]),s)),[[],[]])))));return{xs:[a.map((s=>s.map((s=>s[0]))))],ys:[a.map((s=>s.map((s=>s[1]))))]}}initialize(){if(super.initialize(),null!=this._mask_contour_source&&"msk"in this.data&&this.data.msk.length>0&&this.data.msk[0].length>0){const s=this.data.msk;this._mask_contour_source.data=this._mask_contour(s)}void 0===this.last_chan&&(this.last_chan=[this.cur_chan[0].valueOf(),this.cur_chan[1].valueOf()]);(()=>{null!=this.init_script&&(0,h.execute)(this.init_script,this)})()}channel(s,a=0,t){this.image_source.channel([a,s],(c=>{void 0!==c&&void 0!==c.chan||console.log("ImageDataSource ERROR ENCOUNTERED <1>",c),this.last_chan=[this.cur_chan[0].valueOf(),this.cur_chan[1].valueOf()],this.cur_chan=[a,s],null!=this._mask_contour_source&&"chan"in c&&"msk"in c.chan&&(c.msk_contour=this._mask_contour(c.chan.msk),this._mask_contour_source.data=c.msk_contour),t&&t(c),this.data=c.chan}),this.imid)}adjust_colormap(s,a,t){this.image_source.adjust_colormap(s,a,t,this.imid,!0)}signal_change(){this.change.emit()}refresh(s){this.image_source.refresh((a=>{void 0!==a&&void 0!==a.chan||console.log("ImageDataSource ERROR ENCOUNTERED <2>",a),null!=this._mask_contour_source&&"chan"in a&&"msk"in a.chan&&(a.msk_contour=this._mask_contour(a.chan.msk),this._mask_contour_source.data=a.msk_contour),s&&s(a),this.data=a.chan}),this.imid,[0,0])}wcs(){return this.image_source.wcs()}}t.ImageDataSource=r,o=r,r.__name__="ImageDataSource",r.__module__="cubevis.bokeh.sources._image_data_source",o.define((({Tuple:s,Number:a,Ref:t,Nullable:c,Any:i})=>({init_script:[i,null],image_source:[t(u.ImagePipe)],_mask_contour_source:[c(t(e.ColumnDataSource)),null],num_chans:[s(a,a)],cur_chan:[s(a,a)]})))},
52
52
  "02e3c3e46c": function _(e,s,i,t,r){var a;t();const c=e("@bokehjs/models/sources/column_data_source"),u=e("@bokehjs/core/util/string"),o=e("2889e0dd45");class _ extends c.ColumnDataSource{constructor(e){super(e),this.imid=(0,u.uuid4)()}initialize(){super.initialize()}spectra(e,s,i=0,t=!1){this.image_source.spectrum([e,s,i],(e=>this.data=e.spectrum),this.imid,t)}refresh(){this.image_source.refresh((e=>this.data=e.spectrum),this.imid,[0,0,0])}}i.SpectraDataSource=_,a=_,_.__name__="SpectraDataSource",_.__module__="cubevis.bokeh.sources._spectra_data_source",a.define((({Ref:e})=>({image_source:[e(o.ImagePipe)]})))},
53
- "64b16deff9": function _(e,s,i,t,a){var n;t();const u=e("@bokehjs/models/sources/column_data_source"),l=e("4406a037f1"),o=e("@bokehjs/core/util/callbacks");class c extends u.ColumnDataSource{constructor(e){super(e)}send(e,s){this.pipe.send(this.session_id.valueOf(),{action:"callback",message:e},(e=>{s("result"in e?e.result:{error:`expected to find a "result" in "${e}"`,msg:e})}))}initialize(){super.initialize();(()=>{null!=this.js_init&&(0,o.execute)(this.js_init,this)})()}}i.UpdatableDataSource=c,n=c,c.__name__="UpdatableDataSource",c.__module__="cubevis.bokeh.sources._updatable_data_source",n.define((({Ref:e,Any:s,String:i})=>({js_init:[s,null],js_update:[s,null],pipe:[e(l.DataPipe)],session_id:[i]})))},
53
+ "64b16deff9": function _(e,s,i,a,t){var n;a();const u=e("@bokehjs/models/sources/column_data_source"),l=e("7a1eeba81e"),o=e("@bokehjs/core/util/callbacks");class c extends u.ColumnDataSource{constructor(e){super(e)}send(e,s){this.pipe.send(this.session_id.valueOf(),{action:"callback",message:e},(e=>{s("result"in e?e.result:{error:`expected to find a "result" in "${e}"`,msg:e})}))}initialize(){super.initialize();(()=>{null!=this.js_init&&(0,o.execute)(this.js_init,this)})()}}i.UpdatableDataSource=c,n=c,c.__name__="UpdatableDataSource",c.__module__="cubevis.bokeh.sources._updatable_data_source",n.define((({Ref:e,Any:s,String:i})=>({js_init:[s,null],js_update:[s,null],pipe:[e(l.DataPipe)],session_id:[i]})))},
54
54
  "b6ae454f0d": function _(s,i,o,t,e){var r;t();const a=s("@bokehjs/models/formatters/tick_formatter"),c=s("de65005924");class l extends a.TickFormatter{constructor(s){super(s),this._axis=null,this._coord="world"}initialize(){super.initialize(),"x"==this.axis||"X"==this.axis||"y"==this.axis||"Y"==this.axis?this._axis="x"==this.axis||"X"==this.axis?"x":"y":console.log("ERROR: WcsTicks formatter created with invalid axis:",this.axis)}doFormat(s){const i=[];if(this._axis&&this.image_source.wcs()&&"world"==this._coord)for(let o=0,t=s.length;o<t;o++)if("x"==this._axis){const t=new casalib.coordtxl.Point2D(Number(s[o]),0);this.image_source.wcs().imageToWorldCoords(t,!1),i.push(new casalib.coordtxl.WorldCoords(t.getX(),t.getY()).format(2e3)[0])}else{const t=new casalib.coordtxl.Point2D(0,Number(s[o]));this.image_source.wcs().imageToWorldCoords(t,!1),i.push(new casalib.coordtxl.WorldCoords(t.getX(),t.getY()).format(2e3)[1])}else for(let o=0,t=s.length;o<t;o++)i.push(""+s[o]);return i}coordinates(s){return s!=this._coord&&("world"!=s&&"pixel"!=s||(this._coord=s)),this._coord}}o.WcsTicks=l,r=l,l.__name__="WcsTicks",l.__module__="cubevis.bokeh.format._wcs_ticks",r.define((({Ref:s,String:i})=>({axis:[i],image_source:[s(c.ImageDataSource)]})))},
55
55
  "cb7d28d6b3": function _(i,e,t,o,s){var d;o();const l=i("@bokehjs/models/tools/gestures/gesture_tool"),r=i("8fc7a9e935"),_=i("484bb85d20"),m=i("@bokehjs/core/util/callbacks");class a extends l.GestureToolView{_pan_start(i){var e;null===(e=this.model.document)||void 0===e||e.interactive_start(this.plot_view.model);const t=(0,_.px_from_sx)(this.plot_view,i.sx),o=(0,_.py_from_sy)(this.plot_view,i.sy),s=(0,_.dx_from_px)(this.plot_view,t),d=(0,_.dy_from_py)(this.plot_view,o),{start:l}=this.model;l?(0,m.execute)(l,this.model,{sx:t,sy:o,x:s,y:d,delta_x:i.dx,delta_y:-i.dy,shift:"modifiers"in i?i.modifiers.shift:void 0,ctrl:"modifiers"in i?i.modifiers.ctrl:void 0,alt:"modifiers"in i?i.modifiers.alt:void 0}):this.model.trigger_event(new r.DragStart(t,o,s,d,i.dx,-i.dy,i.modifiers))}_pan(i){var e;null===(e=this.model.document)||void 0===e||e.interactive_start(this.plot_view.model);const t=(0,_.px_from_sx)(this.plot_view,i.sx),o=(0,_.py_from_sy)(this.plot_view,i.sy),s=(0,_.dx_from_px)(this.plot_view,t),d=(0,_.dy_from_py)(this.plot_view,o),{move:l}=this.model;l?(0,m.execute)(l,this.model,{sx:t,sy:o,x:s,y:d,delta_x:i.dx,delta_y:-i.dy,shift:"modifiers"in i?i.modifiers.shift:void 0,ctrl:"modifiers"in i?i.modifiers.ctrl:void 0,alt:"modifiers"in i?i.modifiers.alt:void 0}):this.model.trigger_event(new r.Drag(t,o,s,d,i.dx,-i.dy,i.modifiers))}_pan_end(i){const e=(0,_.px_from_sx)(this.plot_view,i.sx),t=(0,_.py_from_sy)(this.plot_view,i.sy),o=(0,_.dx_from_px)(this.plot_view,e),s=(0,_.dy_from_py)(this.plot_view,t),{end:d}=this.model;d?(0,m.execute)(d,this.model,{sx:e,sy:t,x:o,y:s,delta_x:i.dx,delta_y:-i.dy,shift:"modifiers"in i?i.modifiers.shift:void 0,ctrl:"modifiers"in i?i.modifiers.ctrl:void 0,alt:"modifiers"in i?i.modifiers.alt:void 0}):this.model.trigger_event(new r.DragEnd(e,t,o,s,i.dx,-i.dy,i.modifiers))}}t.DragToolView=a,a.__name__="DragToolView";class n extends l.GestureTool{constructor(i){super(i),this.tool_name="Drag",this.event_type="pan",this.default_order=10}}t.DragTool=n,d=n,n.__name__="DragTool",n.__module__="cubevis.bokeh.tools._drag_tool",d.prototype.default_view=a,d.define((({Any:i,Nullable:e})=>({start:[e(i),null],move:[e(i),null],end:[e(i),null]})))},
56
56
  "8fc7a9e935": function _(e,t,a,s,_){s();const n=e("@bokehjs/core/bokeh_events");class r extends n.Pan{}a.Drag=r,r.__name__="Drag";class l extends n.PanStart{constructor(e,t,a,s,_,n,r){super(e,t,a,s,r),this.delta_x=_,this.delta_y=n}get event_values(){const{delta_x:e,delta_y:t}=this;return{...super.event_values,delta_x:e,delta_y:t}}}a.DragStart=l,l.__name__="DragStart";class d extends n.PanEnd{constructor(e,t,a,s,_,n,r){super(e,t,a,s,r),this.delta_x=_,this.delta_y=n}get event_values(){const{delta_x:e,delta_y:t}=this;return{...super.event_values,delta_x:e,delta_y:t}}}a.DragEnd=d,d.__name__="DragEnd"},
@@ -64,4 +64,4 @@
64
64
  "b55081402e": function _(e,n,t,_,s){var a;_();const o=e("@bokehjs/models/annotations/span"),p=e("@bokehjs/core/bokeh_events");class r extends o.SpanView{on_pan_start(e){const n=super.on_pan_start(e);return this.model.trigger_event(new p.LODStart),n}on_pan(e){super.on_pan(e)}on_pan_end(e){super.on_pan_end(e),this.model.trigger_event(new p.LODEnd)}}t.EditSpanView=r,r.__name__="EditSpanView";class d extends o.Span{constructor(e){super(e)}}t.EditSpan=d,a=d,d.__name__="EditSpan",d.__module__="cubevis.bokeh.models._edit_span",a.prototype.default_view=r},
65
65
  "9144bfc7a5": function _(e,t,s,n,r){var i;n();const l=e("@bokehjs/models/widgets/text_input"),o=e("@bokehjs/core/dom"),u=e("@bokehjs/core/bokeh_events");class _ extends l.TextInputView{stylesheets(){return[...super.stylesheets(),new o.InlineStyleSheet(".bk-input-prefix { padding: 0 var(--padding-vertical); }")]}connect_signals(){super.connect_signals(),this.el.addEventListener("mouseenter",(e=>{this.model.trigger_event(new u.MouseEnter(e.screenX,e.screenY,e.x,e.y,{shift:e.shiftKey,ctrl:e.ctrlKey,alt:e.altKey}))})),this.el.addEventListener("mouseleave",(e=>{this.model.trigger_event(new u.MouseLeave(e.screenX,e.screenY,e.x,e.y,{shift:e.shiftKey,ctrl:e.ctrlKey,alt:e.altKey}))}))}render(){super.render()}}s.EvTextInputView=_,_.__name__="EvTextInputView";class c extends l.TextInput{constructor(e){super(e)}}s.EvTextInput=c,i=c,c.__name__="EvTextInput",c.__module__="cubevis.bokeh.models._ev_text_input",i.prototype.default_view=_},
66
66
  "74e0abef8a": function _(e,t,n,s,o){var i;s();const r=e("@bokehjs/models/annotations/poly_annotation"),a=e("@bokehjs/core/bokeh_events");class _ extends r.PolyAnnotationView{on_enter(e){const{x_scale:t,y_scale:n}=this.plot_view.frame,s=new a.MouseEnter(e.sx,e.sy,t.invert(e.sx),n.invert(e.sy),{shift:e.modifiers.shift,ctrl:e.modifiers.ctrl,alt:e.modifiers.alt}),o=super.on_enter(e);return this.model.trigger_event(s),o}on_leave(e){const{x_scale:t,y_scale:n}=this.plot_view.frame,s=new a.MouseLeave(e.sx,e.sy,t.invert(e.sx),n.invert(e.sy),{shift:e.modifiers.shift,ctrl:e.modifiers.ctrl,alt:e.modifiers.alt});super.on_leave(e),this.model.trigger_event(s)}on_pan_start(e){const{x_scale:t,y_scale:n}=this.plot_view.frame,s=new a.PanStart(e.sx,e.sy,t.invert(e.sx),n.invert(e.sy),{shift:e.modifiers.shift,ctrl:e.modifiers.ctrl,alt:e.modifiers.alt}),o=super.on_pan_start(e);return this.model.trigger_event(s),o}on_pan_end(e){const{x_scale:t,y_scale:n}=this.plot_view.frame,s=new a.PanEnd(e.sx,e.sy,t.invert(e.sx),n.invert(e.sy),{shift:e.modifiers.shift,ctrl:e.modifiers.ctrl,alt:e.modifiers.alt});super.on_pan_end(e),this.model.trigger_event(s)}on_pan(e){super.on_pan(e);const t=new a.RangesUpdate(e.sx,e.sx+e.dx,e.sy,e.sy+e.dy);this.model.trigger_event(t)}}n.EvPolyAnnotationView=_,_.__name__="EvPolyAnnotationView";class l extends r.PolyAnnotation{constructor(e){super(e)}}n.EvPolyAnnotation=l,i=l,l.__name__="EvPolyAnnotation",l.__module__="cubevis.bokeh.annotations._ev_poly_annotation",i.prototype.default_view=_},
67
- }, "07c9fde72b", {"index":"07c9fde72b","src/bokeh/sources/data_pipe":"4406a037f1","src/bokeh/util/conversions":"e3901fa9f2","src/bokeh/sources/active_data_pipes":"5179d11e71","src/bokeh/util/model_manager":"30b45c52a1","src/bokeh/sources/image_pipe":"2889e0dd45","src/bokeh/sources/image_data_source":"de65005924","src/bokeh/sources/spectra_data_source":"02e3c3e46c","src/bokeh/sources/updatable_data_source":"64b16deff9","src/bokeh/format/wcs_ticks":"b6ae454f0d","src/bokeh/tools/drag_tool":"cb7d28d6b3","src/bokeh/events":"8fc7a9e935","src/bokeh/util/find":"484bb85d20","src/bokeh/tools/cbreset_tool":"9d3c34ff8e","src/bokeh/models/tip_button":"9f961622ce","src/bokeh/models/tip":"ca4c845905","src/bokeh/models/showable":"a6e757a69a","src/bokeh/models/bokeh_app_context":"467d2716b0","src/bokeh/models/shared_dict":"50a1e32f01","src/bokeh/models/edit_span":"b55081402e","src/bokeh/models/ev_text_input":"9144bfc7a5","src/bokeh/annotations/ev_poly_annotation":"74e0abef8a"}, {});});
67
+ }, "07c9fde72b", {"index":"07c9fde72b","src/bokeh/sources/data_pipe":"7a1eeba81e","src/bokeh/util/conversions":"e3901fa9f2","src/bokeh/sources/active_data_pipes":"5179d11e71","src/bokeh/util/model_manager":"30b45c52a1","src/bokeh/sources/image_pipe":"2889e0dd45","src/bokeh/sources/image_data_source":"de65005924","src/bokeh/sources/spectra_data_source":"02e3c3e46c","src/bokeh/sources/updatable_data_source":"64b16deff9","src/bokeh/format/wcs_ticks":"b6ae454f0d","src/bokeh/tools/drag_tool":"cb7d28d6b3","src/bokeh/events":"8fc7a9e935","src/bokeh/util/find":"484bb85d20","src/bokeh/tools/cbreset_tool":"9d3c34ff8e","src/bokeh/models/tip_button":"9f961622ce","src/bokeh/models/tip":"ca4c845905","src/bokeh/models/showable":"a6e757a69a","src/bokeh/models/bokeh_app_context":"467d2716b0","src/bokeh/models/shared_dict":"50a1e32f01","src/bokeh/models/edit_span":"b55081402e","src/bokeh/models/ev_text_input":"9144bfc7a5","src/bokeh/annotations/ev_poly_annotation":"74e0abef8a"}, {});});
cubevis/__version__.py CHANGED
@@ -1 +1 @@
1
- __version__ = '1.0.38'
1
+ __version__ = '1.0.44'
@@ -314,10 +314,6 @@ class Showable(LayoutDOM,BokehInit):
314
314
  for url in js_paths
315
315
  ])
316
316
 
317
- print( "-----scripts-being-used-----------------------------------------------" )
318
- print( all_scripts )
319
- print( "----------------------------------------------------------------------" )
320
-
321
317
  # Use json_item approach which is more reliable in iframes
322
318
  item = json_item(self, target=f"bokeh-{self.id}")
323
319
  item_json = json_lib.dumps(item)
@@ -71,7 +71,9 @@ class DataPipe(DataSource,BokehInit):
71
71
  JavaScript to be run during initialization of an instance of an DataPipe object.
72
72
  """)
73
73
 
74
- address = Tuple( String, Int, help="two integer sequence representing the address and port to use for the websocket" )
74
+ backend_ip = String(default="127.0.0.1", help="the IP address that the Python server binds to locally" )
75
+ backend_port = Int( help="the port that the Python server listens on" )
76
+ backend_url = String( help="the full URL used by the browser to connect to the Python server" )
75
77
 
76
78
  instance_id = String( help="Unique ID for each DataPipe object" )
77
79
 
@@ -86,101 +88,17 @@ class DataPipe(DataSource,BokehInit):
86
88
  ###################################################################
87
89
  #__javascript__ = [ casalib_url( ), cubevisjs_url( ) ]
88
90
 
89
- def _expose_colab_port(self):
90
- """Expose the WebSocket port through Colab's proxy"""
91
- try:
92
- from google.colab import output
93
- import os
94
- import json
95
- port = self.address[1]
96
-
97
- # Expose the port
98
- output.serve_kernel_port_as_iframe(port)
99
-
100
- # Try to get kernel connection info
101
- # Colab stores connection info in environment variables or files
102
- kernel_info = {}
103
-
104
- # Check various environment variables
105
- for key in ['COLAB_KERNEL_ID', 'JPY_SESSION_NAME', 'KERNEL_ID',
106
- 'COLAB_GPU', 'COLAB_TPU_ADDR', 'HOSTNAME']:
107
- value = os.environ.get(key)
108
- if value:
109
- kernel_info[key] = value
110
-
111
- # Try to read kernel connection file
112
- try:
113
- # Jupyter/Colab stores connection info in runtime files
114
- runtime_dir = os.environ.get('JUPYTER_RUNTIME_DIR', '/root/.local/share/jupyter/runtime')
115
- if os.path.exists(runtime_dir):
116
- import glob
117
- connection_files = glob.glob(os.path.join(runtime_dir, 'kernel-*.json'))
118
- if connection_files:
119
- with open(connection_files[0], 'r') as f:
120
- conn_info = json.load(f)
121
- kernel_info['connection'] = conn_info
122
- except Exception as e:
123
- print(f" Could not read kernel connection file: {e}")
124
-
125
- # Get the actual WebSocket URL by checking where requests go
126
- # This is hacky but might work
127
- try:
128
- import socket
129
- hostname = socket.gethostname()
130
- kernel_info['hostname'] = hostname
131
-
132
- # Try to get external URL
133
- import requests
134
- # Colab has an internal metadata service
135
- try:
136
- # This might reveal the actual kernel URL
137
- metadata_url = "http://metadata.google.internal/computeMetadata/v1/instance/"
138
- headers = {"Metadata-Flavor": "Google"}
139
-
140
- # Try to get instance info
141
- instance_info = {}
142
- for key in ['hostname', 'name', 'zone', 'id']:
143
- try:
144
- resp = requests.get(metadata_url + key, headers=headers, timeout=1)
145
- if resp.status_code == 200:
146
- instance_info[key] = resp.text
147
- except:
148
- pass
149
-
150
- if instance_info:
151
- kernel_info['instance'] = instance_info
152
- except:
153
- pass
154
-
155
- except Exception as e:
156
- print(f" Could not get hostname: {e}")
157
-
158
- print(f"✓ Colab: Exposed WebSocket port {port} via iframe proxy")
159
- print(f" Kernel info: {json.dumps(kernel_info, indent=2)}")
160
-
161
- # Inject whatever we found into JavaScript
162
- from IPython.display import display, Javascript
163
-
164
- display(Javascript(f"""
165
- window.CUBEVIS_COLAB_PORT_{port} = {{
166
- port: {port},
167
- kernelInfo: {json.dumps(kernel_info)}
168
- }};
169
- console.log('Colab port info injected:', window.CUBEVIS_COLAB_PORT_{port});
170
- """))
171
-
172
- except Exception as e:
173
- print(f"⚠ Warning: Could not expose port {port} in Colab: {e}")
174
- import traceback
175
- traceback.print_exc()
176
-
177
- def __init__( self, *args, abort=None, **kwargs ):
91
+ def __init__( self, *args, abort=None, address=None, **kwargs ):
178
92
 
179
93
  if 'conflict_check' not in kwargs:
180
94
  kwargs['conflict_check'] = not is_interactive_jupyter( )
181
95
  if 'instance_id' not in kwargs:
182
96
  kwargs['instance_id'] = str(uuid4( ))
183
97
 
98
+ if address is not None:
99
+ kwargs['backend_ip'] = address[0]
100
+ kwargs['backend_port'] = address[1]
101
+
184
102
  super( ).__init__( *args, **kwargs )
185
103
 
186
104
  self.__send_queue = { }
@@ -194,9 +112,15 @@ class DataPipe(DataSource,BokehInit):
194
112
  if self.__abort is not None and not callable(self.__abort):
195
113
  raise RuntimeError(f'abort function must be callable ({type(self.__abort)} is not)')
196
114
 
197
- # Expose port in Colab
115
+ # Fetch URL in Colab
198
116
  if is_colab( ):
199
- self._expose_colab_port()
117
+ from google.colab.output import eval_js
118
+ # Colab maps the internal port to a secure external URL
119
+ external_https = eval_js(f"google.colab.kernel.proxyPort({self.backend_port})")
120
+ self.backend_url = external_https.replace("https://", "wss://")
121
+ else:
122
+ # Standard local/remote access
123
+ self.backend_url = f"ws://{self.backend_ip}:{self.backend_port}"
200
124
 
201
125
  def __enqueue_send( self, ident, msg, callback ):
202
126
  ### it is assumed that this is called AFTER the lock has been aquired
@@ -358,7 +282,7 @@ class DataPipe(DataSource,BokehInit):
358
282
  self.__websocket = websocket
359
283
  session_established = False
360
284
 
361
- print(f"✓ WebSocket server received connection on port {self.address[1]}")
285
+ print(f"✓ WebSocket server received connection on port {self.backend_port}")
362
286
 
363
287
  async for message in websocket:
364
288
  msg = deserialize(message)
@@ -34,10 +34,10 @@ from bokeh.plotting import ColumnDataSource
34
34
  from bokeh.core.properties import Instance, String, Nullable
35
35
  from bokeh.models.callbacks import Callback
36
36
  from bokeh.models import CustomJS
37
- import websockets
38
37
  from ._data_pipe import DataPipe
39
38
  from ..state import casalib_url, cubevisjs_url
40
39
  from ...utils import find_ws_address
40
+ from .transport import create_ws_server
41
41
  from .. import BokehInit
42
42
 
43
43
  class UpdatableDataSource(ColumnDataSource,BokehInit):
@@ -189,5 +189,5 @@ class UpdatableDataSource(ColumnDataSource,BokehInit):
189
189
  raise RuntimeError( 'UpdatableDataSource.serve should only be called for when a "pipe" is NOT supplied as part of initialization' )
190
190
 
191
191
  self._stop_serving_function = stop_function
192
- async with websockets.serve( self.pipe.process_messages, self.pipe.address[0], self.pipe.address[1] ) as msgpipe:
192
+ async with create_ws_server( self.pipe.process_messages, self.pipe.backend_ip, self.pipe.backend_port ) as msgpipe:
193
193
  yield { 'msgpipe': msgpipe }
@@ -0,0 +1,12 @@
1
+ import websockets
2
+ from cubevis.utils import is_colab
3
+
4
+ def create_ws_server(callback, ip_address, port):
5
+ """
6
+ Uniform wrapper for creating a WebSocket server.
7
+ """
8
+ if is_colab( ):
9
+ print( f"websocket startup: {ip_address}/{port} (bind IP 0.0.0.0)" )
10
+ return websockets.serve( callback, "0.0.0.0", port, origins=None )
11
+ else:
12
+ return websockets.serve( callback, ip_address, port )
cubevis/toolbox/_cube.py CHANGED
@@ -38,7 +38,6 @@ import asyncio
38
38
  from uuid import uuid4
39
39
  from sys import platform
40
40
  from os.path import dirname, join
41
- import websockets
42
41
  from contextlib import asynccontextmanager
43
42
  from bokeh.core.enums import HatchPattern as _hatch_patterns
44
43
  from bokeh.core.enums import DashPattern as _dash_patterns
@@ -59,6 +58,7 @@ from ..bokeh.models import EvTextInput, SharedDict
59
58
  from ..bokeh.tools import CBResetTool
60
59
  from ..bokeh.state import available_palettes, find_palette, default_palette
61
60
  from ..bokeh.annotations import EvPolyAnnotation
61
+ from ..bokeh.sources.transport import create_ws_server
62
62
  from bokeh.layouts import row, column
63
63
  from bokeh.models.dom import HTML
64
64
  from bokeh.models import Tooltip
@@ -2301,8 +2301,8 @@ class CubeMask:
2301
2301
  @asynccontextmanager
2302
2302
  async def serve( self, stop_function ):
2303
2303
  self._stop_serving_function = stop_function
2304
- async with websockets.serve( self._pipe['image'].process_messages, self._pipe['image'].address[0], self._pipe['image'].address[1] ) as im, \
2305
- websockets.serve( self._pipe['control'].process_messages, self._pipe['control'].address[0], self._pipe['control'].address[1] ) as ctrl:
2304
+ async with create_ws_server( self._pipe['image'].process_messages, self._pipe['image'].backend_ip, self._pipe['image'].backend_port ) as im, \
2305
+ create_ws_server( self._pipe['control'].process_messages, self._pipe['control'].backend_ip, self._pipe['control'].backend_port ) as ctrl:
2306
2306
  yield { 'im': im, 'ctrl': ctrl }
2307
2307
  #pass
2308
2308
 
@@ -34,7 +34,6 @@ import sys
34
34
  import copy
35
35
  import asyncio
36
36
  import shutil
37
- import websockets
38
37
  from os.path import basename, abspath, exists, join
39
38
  import numpy as np
40
39
  from uuid import uuid4
@@ -65,6 +64,7 @@ from cubevis.utils import find_ws_address, convert_masks
65
64
  from cubevis.toolbox import CubeMask
66
65
  from cubevis.bokeh.utils import svg_icon
67
66
  from cubevis.bokeh.sources import DataPipe
67
+ from cubevis.bokeh.sources.transport import create_ws_server
68
68
  from cubevis.utils import DocEnum
69
69
  from cubevis import exe
70
70
 
@@ -142,11 +142,11 @@ class InteractiveCleanUI:
142
142
  ###
143
143
  ### need to add extra cube ports here for multifield imaging
144
144
  ###
145
- ports = [ self._pipe['control'].address[1], self._clean['converge']['pipe'].address[1] ]
145
+ ports = [ self._pipe['control'].backend_port, self._clean['converge']['pipe'].backend_port ]
146
146
 
147
147
  for imid, imdetails in self._clean_targets.items( ):
148
- ports.append( imdetails['gui']['cube']._pipe['image'].address[1] )
149
- ports.append( imdetails['gui']['cube']._pipe['control'].address[1] )
148
+ ports.append( imdetails['gui']['cube']._pipe['image'].backend_port )
149
+ ports.append( imdetails['gui']['cube']._pipe['control'].backend_port )
150
150
 
151
151
  # Also forward http port if serving webpage
152
152
  #if not self._is_notebook:
@@ -1155,12 +1155,12 @@ class InteractiveCleanUI:
1155
1155
  [
1156
1156
  self._clean_targets[img]['gui']['cube'].serve(self.__stop),
1157
1157
  ]
1158
- ] + [ websockets.serve( self._pipe['control'].process_messages,
1159
- self._pipe['control'].address[0],
1160
- self._pipe['control'].address[1] ),
1161
- websockets.serve( self._clean['converge']['pipe'].process_messages,
1162
- self._clean['converge']['pipe'].address[0],
1163
- self._clean['converge']['pipe'].address[1] ) ]
1158
+ ] + [ create_ws_server( self._pipe['control'].process_messages,
1159
+ self._pipe['control'].backend_ip,
1160
+ self._pipe['control'].backend_port ),
1161
+ create_ws_server( self._clean['converge']['pipe'].process_messages,
1162
+ self._clean['converge']['pipe'].backend_ip,
1163
+ self._clean['converge']['pipe'].backend_port ) ]
1164
1164
  ) ):
1165
1165
  self.__result_future = asyncio.Future( )
1166
1166
  yield self.__result_future
@@ -33,7 +33,6 @@ import sys
33
33
  import copy
34
34
  import asyncio
35
35
  import shutil
36
- import websockets
37
36
  from os.path import basename, abspath, exists, join
38
37
  import numpy as np
39
38
  from uuid import uuid4
@@ -64,6 +63,7 @@ from cubevis.utils import find_ws_address, convert_masks
64
63
  from cubevis.toolbox import CubeMask
65
64
  from cubevis.bokeh.utils import svg_icon
66
65
  from cubevis.bokeh.sources import DataPipe
66
+ from cubevis.bokeh.sources.transport import create_ws_server
67
67
  from cubevis.utils import DocEnum
68
68
  from cubevis import exe
69
69
 
@@ -141,11 +141,11 @@ class InteractiveCleanUI:
141
141
  ###
142
142
  ### need to add extra cube ports here for multifield imaging
143
143
  ###
144
- ports = [ self._pipe['control'].address[1], self._clean['converge']['pipe'].address[1] ]
144
+ ports = [ self._pipe['control'].backend_port, self._clean['converge']['pipe'].backend_port ]
145
145
 
146
146
  for imid, imdetails in self._clean_targets.items( ):
147
- ports.append( imdetails['gui']['cube']._pipe['image'].address[1] )
148
- ports.append( imdetails['gui']['cube']._pipe['control'].address[1] )
147
+ ports.append( imdetails['gui']['cube']._pipe['image'].backend_port )
148
+ ports.append( imdetails['gui']['cube']._pipe['control'].backend_port )
149
149
 
150
150
  # Also forward http port if serving webpage
151
151
  #if not self._is_notebook:
@@ -1154,12 +1154,12 @@ class InteractiveCleanUI:
1154
1154
  [
1155
1155
  self._clean_targets[img]['gui']['cube'].serve(self.__stop),
1156
1156
  ]
1157
- ] + [ websockets.serve( self._pipe['control'].process_messages,
1158
- self._pipe['control'].address[0],
1159
- self._pipe['control'].address[1] ),
1160
- websockets.serve( self._clean['converge']['pipe'].process_messages,
1161
- self._clean['converge']['pipe'].address[0],
1162
- self._clean['converge']['pipe'].address[1] ) ]
1157
+ ] + [ create_ws_server( self._pipe['control'].process_messages,
1158
+ self._pipe['control'].backend_ip,
1159
+ self._pipe['control'].backend_port ),
1160
+ create_ws_server( self._clean['converge']['pipe'].process_messages,
1161
+ self._clean['converge']['pipe'].backend_ip,
1162
+ self._clean['converge']['pipe'].backend_port ) ]
1163
1163
  ) ):
1164
1164
  self.__result_future = asyncio.Future( )
1165
1165
  yield self.__result_future
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: cubevis
3
- Version: 1.0.38
3
+ Version: 1.0.44
4
4
  Summary: visualization toolkit and apps for casa
5
5
  License: LGPL
6
6
  Author-email: Darrell Schiebel <darrell@schiebel.us>,Pam Harris <pharris@nrao.edu>
@@ -32,7 +32,7 @@ cubevis/__icons__/zoom-to-fit.svg,sha256=NtYorWvH4s68iAMriqCPGuTBX5SsgVN310UXGKD
32
32
  cubevis/__init__.py,sha256=c_7j2VgZ9yeRJOoFlzzQt-bQ_awlBMaaPJPSB0MNfcg,3233
33
33
  cubevis/__js__/bokeh-3.6/cubevisjs.min.js,sha256=bZ8IjciHZwcUMrrc_6a3n965WlPCMeQedZjb4-0Ln34,42526
34
34
  cubevis/__js__/bokeh-3.7/cubevisjs.min.js,sha256=bZ8IjciHZwcUMrrc_6a3n965WlPCMeQedZjb4-0Ln34,42526
35
- cubevis/__js__/bokeh-3.8/cubevisjs.min.js,sha256=mcFlKW5TDcwwxGTqYtvh3OL8bRtnDI0RyTsYQngeQkg,44523
35
+ cubevis/__js__/bokeh-3.8/cubevisjs.min.js,sha256=m1rbPbXW4WpprKctLWN4Lo8rGCT35tsnqxdb2TAa1kI,43034
36
36
  cubevis/__js__/casalib.min.js,sha256=J9Uvlat_Vf6cjcvftOG5COk3YH6A371MJ7s5u_ZS2_4,91133
37
37
  cubevis/bokeh/__init__.py,sha256=dDIV8jBZji-bD8TQQKBMaF5UuabaJ5NICWn6g_QHxvs,1885
38
38
  cubevis/bokeh/annotations/__init__.py,sha256=tjDIPKbg-rh7Iu3coFWvmX-j2yNj9KuKmRp1aTo71ww,50
@@ -46,15 +46,16 @@ cubevis/bokeh/models/_bokeh_app_context.py,sha256=iHCFAJzFinX8I6ty3Vdw6w0Za-5qpo
46
46
  cubevis/bokeh/models/_edit_span.py,sha256=7o59ZS0bF_Q_WtstvViWXP-2PiY_F7_zCecTqKcmz0E,196
47
47
  cubevis/bokeh/models/_ev_text_input.py,sha256=SGtefXkWK6jHEk4EneZ_hEUGwoIWwVGjwqLjGsAXMpY,158
48
48
  cubevis/bokeh/models/_shared_dict.py,sha256=AWjLMOKVAXWHSF4gcK2RbxF442QlzQ7hMR0oaODCqB0,901
49
- cubevis/bokeh/models/_showable.py,sha256=7BtQgl0tMSqcZrPrH4FnC2ei_FOVnO-SIhBH1_ry2ZI,18696
49
+ cubevis/bokeh/models/_showable.py,sha256=uzLf8hhITweJnBB5Sm-XjLb1H-RGYfrSSuWVI1UekUc,18474
50
50
  cubevis/bokeh/models/_tip.py,sha256=yNoUWods0xxva1WOfh5It_Y8hbpVy8RVXUmm8p7a58M,1431
51
51
  cubevis/bokeh/models/_tip_button.py,sha256=mwk1C7BMVlZrAAyQLn45S4Q9GEQfU_wU2MWpO0Gwzj4,1610
52
52
  cubevis/bokeh/sources/__init__.py,sha256=4FsudFuVU4o7VG5OG3K1tiMoxIXcJWNz_K9yzMDE8ls,1581
53
- cubevis/bokeh/sources/_data_pipe.py,sha256=7M6D5grIVI5iNI-_E3EsCyDGL46hTR93RGGkHqt8t8c,23630
53
+ cubevis/bokeh/sources/_data_pipe.py,sha256=73VTxdpYOOgTF3H0Q_sRC-32pXjr320mzdA7zTMX1F4,20704
54
54
  cubevis/bokeh/sources/_image_data_source.py,sha256=5sEWdfqoMk08HQ0JWg6bHJ34dWmphHm52nOZywSAE5c,3789
55
55
  cubevis/bokeh/sources/_image_pipe.py,sha256=pQ05VynLuJbedGja7aXDbVXFkOYbdMceOuOEj-QuluQ,28692
56
56
  cubevis/bokeh/sources/_spectra_data_source.py,sha256=qL1IOjSefWlycaqS4Pz5EHwg-1EwCVmNwxysP9lxDeM,2451
57
- cubevis/bokeh/sources/_updatable_data_source.py,sha256=Kib2DPPIA0abqOywzdme98GxI8KBukszbSC5K65wxv0,10961
57
+ cubevis/bokeh/sources/_updatable_data_source.py,sha256=mjV1u3ZpRE5KCHtZA4tV1JxMf09Ifh4elSWlf6jNXQo,10985
58
+ cubevis/bokeh/sources/transport/__init__.py,sha256=Yix_OCatb4W19BDD4qpHbguJO_u745UwWscA5a7Aups,417
58
59
  cubevis/bokeh/state/__init__.py,sha256=PZ2-7I5XHkMTc-vguYarYCYSJ1pKyEYnSAFa-n8AuTE,1826
59
60
  cubevis/bokeh/state/_current.py,sha256=owPMQTme5SBYvIVP3Q4y9hpWHPmyhLHsS2O0sCAAqqo,967
60
61
  cubevis/bokeh/state/_initialize.py,sha256=eX06VU1KyTEyoFiAdPBA_XucCKFEgNImv1qVXfXaIkE,12881
@@ -106,9 +107,9 @@ cubevis/remote/_local.py,sha256=PcPCFcwttTFZd3O33-5pqDuGKQKK6CA0gz1MTIkTiNI,1032
106
107
  cubevis/remote/_remote_kernel.py,sha256=wfu7ZzKn-oCxZxzDIkC5puBvGf8WbCLYL3CzM56_FNc,2652
107
108
  cubevis/toolbox/__init__.py,sha256=sEN80BX91q_Z2zImDlT8oZ-0o8sE-iH7n3i4S1lmRLo,1450
108
109
  cubevis/toolbox/_app_context.py,sha256=rkjddiE4Ynf2HeyI0Hf8DOUt89bF67-2IlgD1uKSdOI,2908
109
- cubevis/toolbox/_cube.py,sha256=ZqprhC7Ps9hGGcd3BLK3zp5wySy2QhnqyAXBkeMxtzY,308257
110
- cubevis/toolbox/_interactive_clean_ui.mustache,sha256=IVTcqkxIyw7SzfU92_70dG7bF9UapromDdmeukQ90cg,114113
111
- cubevis/toolbox/_interactive_clean_ui.py,sha256=98KnLZnDXqO5xl7Ie7WpirogtKL0a5myHejsC89CVSU,114024
110
+ cubevis/toolbox/_cube.py,sha256=sojBdhcX95AUUblJBh4d3s9WqUpXehzA8HH67ph-MkQ,308298
111
+ cubevis/toolbox/_interactive_clean_ui.mustache,sha256=ihz9YM0UA4lIpkAc2v4VvWWBvvB822KMcNB8AaxnoKg,114168
112
+ cubevis/toolbox/_interactive_clean_ui.py,sha256=Ms-120Bs3tEcjcZyXUYbGMg7lwi6t1vefLYws0al4Uw,114079
112
113
  cubevis/toolbox/_interactiveclean_wrappers.py,sha256=XqyCGz33CMDhszTxnwZ_3-64GszUK1XYnGKUOxl9sas,5071
113
114
  cubevis/toolbox/_region_list.py,sha256=_1RvnXwqMoaAq8CPy-6IyhabLi_snXqO566onehI2y0,8957
114
115
  cubevis/utils/_ResourceManager.py,sha256=SaaR29etabRiKxmUK-aWvAm4v_OPFJH8CX7bNFm0Lgo,3410
@@ -127,8 +128,8 @@ cubevis/utils/_pkgs.py,sha256=mu2CCzndmJZYP81UkFhxveW_CisWLUvagJVolHOEVgM,2294
127
128
  cubevis/utils/_regions.py,sha256=TdAg4ZUUyhg3nFmX9_KLboqmc0LkyOdEW8M1WDR5Udk,1669
128
129
  cubevis/utils/_static.py,sha256=rN-sqXNqQ5R2M3wmPHU1GPP5OTyyWQlUPRuimCrht-g,2347
129
130
  cubevis/utils/_tiles.py,sha256=A9W1X61VOhBMTOKXVajzOIoiV2FBdO5N2SFB9SUpDOo,7336
130
- cubevis/__version__.py,sha256=PxK7trj3XRaJAWKdUXKTshZP_6DU3CFjTcHnfhWOFrA,22
131
- cubevis-1.0.38.dist-info/WHEEL,sha256=B19PGBCYhWaz2p_UjAoRVh767nYQfk14Sn4TpIZ-nfU,87
132
- cubevis-1.0.38.dist-info/METADATA,sha256=Ug9X2LLzH_zLtIUKbzy2O5Omq5uHNSXxnkbVoEsXlFc,2632
133
- cubevis-1.0.38.dist-info/licenses/LICENSE,sha256=IMF9i4xIpgCADf0U-V1cuf9HBmqWQd3qtI3FSuyW4zE,26526
134
- cubevis-1.0.38.dist-info/RECORD,,
131
+ cubevis/__version__.py,sha256=-CH3SKmwnkRFogc6NbKW3B5uf72hpFBiDX1J8lKh-D8,22
132
+ cubevis-1.0.44.dist-info/WHEEL,sha256=B19PGBCYhWaz2p_UjAoRVh767nYQfk14Sn4TpIZ-nfU,87
133
+ cubevis-1.0.44.dist-info/METADATA,sha256=kiR5vfiuNz_2VTJxJcigSBl9XfWkjaKQonBfPpfQpI0,2632
134
+ cubevis-1.0.44.dist-info/licenses/LICENSE,sha256=IMF9i4xIpgCADf0U-V1cuf9HBmqWQd3qtI3FSuyW4zE,26526
135
+ cubevis-1.0.44.dist-info/RECORD,,