diff --git a/.nojekyll b/.nojekyll new file mode 100644 index 0000000..e69de29 diff --git a/404.html b/404.html new file mode 100644 index 0000000..98c57ed --- /dev/null +++ b/404.html @@ -0,0 +1,387 @@ + + + + + + + + + + + + + + + + + + + + ZodiPy + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+ + + +
+
+ +

404 - Not found

+ +
+
+ + +
+ +
+ + + +
+
+
+
+ + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/assets/_mkdocstrings.css b/assets/_mkdocstrings.css new file mode 100644 index 0000000..57a23e1 --- /dev/null +++ b/assets/_mkdocstrings.css @@ -0,0 +1,114 @@ + +/* Avoid breaking parameter names, etc. in table cells. */ +.doc-contents td code { + word-break: normal !important; +} + +/* No line break before first paragraph of descriptions. */ +.doc-md-description, +.doc-md-description>p:first-child { + display: inline; +} + +/* Max width for docstring sections tables. */ +.doc .md-typeset__table, +.doc .md-typeset__table table { + display: table !important; + width: 100%; +} + +.doc .md-typeset__table tr { + display: table-row; +} + +/* Defaults in Spacy table style. */ +.doc-param-default { + float: right; +} + +/* Symbols in Navigation and ToC. */ +:root, +[data-md-color-scheme="default"] { + --doc-symbol-attribute-fg-color: #953800; + --doc-symbol-function-fg-color: #8250df; + --doc-symbol-method-fg-color: #8250df; + --doc-symbol-class-fg-color: #0550ae; + --doc-symbol-module-fg-color: #5cad0f; + + --doc-symbol-attribute-bg-color: #9538001a; + --doc-symbol-function-bg-color: #8250df1a; + --doc-symbol-method-bg-color: #8250df1a; + --doc-symbol-class-bg-color: #0550ae1a; + --doc-symbol-module-bg-color: #5cad0f1a; +} + +[data-md-color-scheme="slate"] { + --doc-symbol-attribute-fg-color: #ffa657; + --doc-symbol-function-fg-color: #d2a8ff; + --doc-symbol-method-fg-color: #d2a8ff; + --doc-symbol-class-fg-color: #79c0ff; + --doc-symbol-module-fg-color: #baff79; + + --doc-symbol-attribute-bg-color: #ffa6571a; + --doc-symbol-function-bg-color: #d2a8ff1a; + --doc-symbol-method-bg-color: #d2a8ff1a; + --doc-symbol-class-bg-color: #79c0ff1a; + --doc-symbol-module-bg-color: #baff791a; +} + +code.doc-symbol { + border-radius: .1rem; + font-size: .85em; + padding: 0 .3em; + font-weight: bold; +} + +code.doc-symbol-attribute { + color: var(--doc-symbol-attribute-fg-color); + background-color: var(--doc-symbol-attribute-bg-color); +} + +code.doc-symbol-attribute::after { + content: "attr"; +} + +code.doc-symbol-function { + color: var(--doc-symbol-function-fg-color); + background-color: var(--doc-symbol-function-bg-color); +} + +code.doc-symbol-function::after { + content: "func"; +} + +code.doc-symbol-method { + color: var(--doc-symbol-method-fg-color); + background-color: var(--doc-symbol-method-bg-color); +} + +code.doc-symbol-method::after { + content: "meth"; +} + +code.doc-symbol-class { + color: var(--doc-symbol-class-fg-color); + background-color: var(--doc-symbol-class-bg-color); +} + +code.doc-symbol-class::after { + content: "class"; +} + +code.doc-symbol-module { + color: var(--doc-symbol-module-fg-color); + background-color: var(--doc-symbol-module-bg-color); +} + +code.doc-symbol-module::after { + content: "mod"; +} + +.doc-signature .autorefs { + color: inherit; + border-bottom: 1px dotted currentcolor; +} diff --git a/assets/images/favicon.png b/assets/images/favicon.png new file mode 100644 index 0000000..1cf13b9 Binary files /dev/null and b/assets/images/favicon.png differ diff --git a/assets/javascripts/bundle.220ee61c.min.js b/assets/javascripts/bundle.220ee61c.min.js new file mode 100644 index 0000000..116072a --- /dev/null +++ b/assets/javascripts/bundle.220ee61c.min.js @@ -0,0 +1,29 @@ +"use strict";(()=>{var Ci=Object.create;var gr=Object.defineProperty;var Ri=Object.getOwnPropertyDescriptor;var ki=Object.getOwnPropertyNames,Ht=Object.getOwnPropertySymbols,Hi=Object.getPrototypeOf,yr=Object.prototype.hasOwnProperty,nn=Object.prototype.propertyIsEnumerable;var rn=(e,t,r)=>t in e?gr(e,t,{enumerable:!0,configurable:!0,writable:!0,value:r}):e[t]=r,P=(e,t)=>{for(var r in t||(t={}))yr.call(t,r)&&rn(e,r,t[r]);if(Ht)for(var r of Ht(t))nn.call(t,r)&&rn(e,r,t[r]);return e};var on=(e,t)=>{var r={};for(var n in e)yr.call(e,n)&&t.indexOf(n)<0&&(r[n]=e[n]);if(e!=null&&Ht)for(var n of Ht(e))t.indexOf(n)<0&&nn.call(e,n)&&(r[n]=e[n]);return r};var Pt=(e,t)=>()=>(t||e((t={exports:{}}).exports,t),t.exports);var Pi=(e,t,r,n)=>{if(t&&typeof t=="object"||typeof t=="function")for(let o of ki(t))!yr.call(e,o)&&o!==r&&gr(e,o,{get:()=>t[o],enumerable:!(n=Ri(t,o))||n.enumerable});return e};var yt=(e,t,r)=>(r=e!=null?Ci(Hi(e)):{},Pi(t||!e||!e.__esModule?gr(r,"default",{value:e,enumerable:!0}):r,e));var sn=Pt((xr,an)=>{(function(e,t){typeof xr=="object"&&typeof an!="undefined"?t():typeof define=="function"&&define.amd?define(t):t()})(xr,function(){"use strict";function e(r){var n=!0,o=!1,i=null,s={text:!0,search:!0,url:!0,tel:!0,email:!0,password:!0,number:!0,date:!0,month:!0,week:!0,time:!0,datetime:!0,"datetime-local":!0};function a(O){return!!(O&&O!==document&&O.nodeName!=="HTML"&&O.nodeName!=="BODY"&&"classList"in O&&"contains"in O.classList)}function f(O){var Qe=O.type,De=O.tagName;return!!(De==="INPUT"&&s[Qe]&&!O.readOnly||De==="TEXTAREA"&&!O.readOnly||O.isContentEditable)}function c(O){O.classList.contains("focus-visible")||(O.classList.add("focus-visible"),O.setAttribute("data-focus-visible-added",""))}function u(O){O.hasAttribute("data-focus-visible-added")&&(O.classList.remove("focus-visible"),O.removeAttribute("data-focus-visible-added"))}function p(O){O.metaKey||O.altKey||O.ctrlKey||(a(r.activeElement)&&c(r.activeElement),n=!0)}function m(O){n=!1}function d(O){a(O.target)&&(n||f(O.target))&&c(O.target)}function h(O){a(O.target)&&(O.target.classList.contains("focus-visible")||O.target.hasAttribute("data-focus-visible-added"))&&(o=!0,window.clearTimeout(i),i=window.setTimeout(function(){o=!1},100),u(O.target))}function v(O){document.visibilityState==="hidden"&&(o&&(n=!0),Y())}function Y(){document.addEventListener("mousemove",N),document.addEventListener("mousedown",N),document.addEventListener("mouseup",N),document.addEventListener("pointermove",N),document.addEventListener("pointerdown",N),document.addEventListener("pointerup",N),document.addEventListener("touchmove",N),document.addEventListener("touchstart",N),document.addEventListener("touchend",N)}function B(){document.removeEventListener("mousemove",N),document.removeEventListener("mousedown",N),document.removeEventListener("mouseup",N),document.removeEventListener("pointermove",N),document.removeEventListener("pointerdown",N),document.removeEventListener("pointerup",N),document.removeEventListener("touchmove",N),document.removeEventListener("touchstart",N),document.removeEventListener("touchend",N)}function N(O){O.target.nodeName&&O.target.nodeName.toLowerCase()==="html"||(n=!1,B())}document.addEventListener("keydown",p,!0),document.addEventListener("mousedown",m,!0),document.addEventListener("pointerdown",m,!0),document.addEventListener("touchstart",m,!0),document.addEventListener("visibilitychange",v,!0),Y(),r.addEventListener("focus",d,!0),r.addEventListener("blur",h,!0),r.nodeType===Node.DOCUMENT_FRAGMENT_NODE&&r.host?r.host.setAttribute("data-js-focus-visible",""):r.nodeType===Node.DOCUMENT_NODE&&(document.documentElement.classList.add("js-focus-visible"),document.documentElement.setAttribute("data-js-focus-visible",""))}if(typeof window!="undefined"&&typeof document!="undefined"){window.applyFocusVisiblePolyfill=e;var t;try{t=new CustomEvent("focus-visible-polyfill-ready")}catch(r){t=document.createEvent("CustomEvent"),t.initCustomEvent("focus-visible-polyfill-ready",!1,!1,{})}window.dispatchEvent(t)}typeof document!="undefined"&&e(document)})});var cn=Pt(Er=>{(function(e){var t=function(){try{return!!Symbol.iterator}catch(c){return!1}},r=t(),n=function(c){var u={next:function(){var p=c.shift();return{done:p===void 0,value:p}}};return r&&(u[Symbol.iterator]=function(){return u}),u},o=function(c){return encodeURIComponent(c).replace(/%20/g,"+")},i=function(c){return decodeURIComponent(String(c).replace(/\+/g," "))},s=function(){var c=function(p){Object.defineProperty(this,"_entries",{writable:!0,value:{}});var m=typeof p;if(m!=="undefined")if(m==="string")p!==""&&this._fromString(p);else if(p instanceof c){var d=this;p.forEach(function(B,N){d.append(N,B)})}else if(p!==null&&m==="object")if(Object.prototype.toString.call(p)==="[object Array]")for(var h=0;hd[0]?1:0}),c._entries&&(c._entries={});for(var p=0;p1?i(d[1]):"")}})})(typeof global!="undefined"?global:typeof window!="undefined"?window:typeof self!="undefined"?self:Er);(function(e){var t=function(){try{var o=new e.URL("b","http://a");return o.pathname="c d",o.href==="http://a/c%20d"&&o.searchParams}catch(i){return!1}},r=function(){var o=e.URL,i=function(f,c){typeof f!="string"&&(f=String(f)),c&&typeof c!="string"&&(c=String(c));var u=document,p;if(c&&(e.location===void 0||c!==e.location.href)){c=c.toLowerCase(),u=document.implementation.createHTMLDocument(""),p=u.createElement("base"),p.href=c,u.head.appendChild(p);try{if(p.href.indexOf(c)!==0)throw new Error(p.href)}catch(O){throw new Error("URL unable to set base "+c+" due to "+O)}}var m=u.createElement("a");m.href=f,p&&(u.body.appendChild(m),m.href=m.href);var d=u.createElement("input");if(d.type="url",d.value=f,m.protocol===":"||!/:/.test(m.href)||!d.checkValidity()&&!c)throw new TypeError("Invalid URL");Object.defineProperty(this,"_anchorElement",{value:m});var h=new e.URLSearchParams(this.search),v=!0,Y=!0,B=this;["append","delete","set"].forEach(function(O){var Qe=h[O];h[O]=function(){Qe.apply(h,arguments),v&&(Y=!1,B.search=h.toString(),Y=!0)}}),Object.defineProperty(this,"searchParams",{value:h,enumerable:!0});var N=void 0;Object.defineProperty(this,"_updateSearchParams",{enumerable:!1,configurable:!1,writable:!1,value:function(){this.search!==N&&(N=this.search,Y&&(v=!1,this.searchParams._fromString(this.search),v=!0))}})},s=i.prototype,a=function(f){Object.defineProperty(s,f,{get:function(){return this._anchorElement[f]},set:function(c){this._anchorElement[f]=c},enumerable:!0})};["hash","host","hostname","port","protocol"].forEach(function(f){a(f)}),Object.defineProperty(s,"search",{get:function(){return this._anchorElement.search},set:function(f){this._anchorElement.search=f,this._updateSearchParams()},enumerable:!0}),Object.defineProperties(s,{toString:{get:function(){var f=this;return function(){return f.href}}},href:{get:function(){return this._anchorElement.href.replace(/\?$/,"")},set:function(f){this._anchorElement.href=f,this._updateSearchParams()},enumerable:!0},pathname:{get:function(){return this._anchorElement.pathname.replace(/(^\/?)/,"/")},set:function(f){this._anchorElement.pathname=f},enumerable:!0},origin:{get:function(){var f={"http:":80,"https:":443,"ftp:":21}[this._anchorElement.protocol],c=this._anchorElement.port!=f&&this._anchorElement.port!=="";return this._anchorElement.protocol+"//"+this._anchorElement.hostname+(c?":"+this._anchorElement.port:"")},enumerable:!0},password:{get:function(){return""},set:function(f){},enumerable:!0},username:{get:function(){return""},set:function(f){},enumerable:!0}}),i.createObjectURL=function(f){return o.createObjectURL.apply(o,arguments)},i.revokeObjectURL=function(f){return o.revokeObjectURL.apply(o,arguments)},e.URL=i};if(t()||r(),e.location!==void 0&&!("origin"in e.location)){var n=function(){return e.location.protocol+"//"+e.location.hostname+(e.location.port?":"+e.location.port:"")};try{Object.defineProperty(e.location,"origin",{get:n,enumerable:!0})}catch(o){setInterval(function(){e.location.origin=n()},100)}}})(typeof global!="undefined"?global:typeof window!="undefined"?window:typeof self!="undefined"?self:Er)});var qr=Pt((Mt,Nr)=>{/*! + * clipboard.js v2.0.11 + * https://clipboardjs.com/ + * + * Licensed MIT © Zeno Rocha + */(function(t,r){typeof Mt=="object"&&typeof Nr=="object"?Nr.exports=r():typeof define=="function"&&define.amd?define([],r):typeof Mt=="object"?Mt.ClipboardJS=r():t.ClipboardJS=r()})(Mt,function(){return function(){var e={686:function(n,o,i){"use strict";i.d(o,{default:function(){return Ai}});var s=i(279),a=i.n(s),f=i(370),c=i.n(f),u=i(817),p=i.n(u);function m(j){try{return document.execCommand(j)}catch(T){return!1}}var d=function(T){var E=p()(T);return m("cut"),E},h=d;function v(j){var T=document.documentElement.getAttribute("dir")==="rtl",E=document.createElement("textarea");E.style.fontSize="12pt",E.style.border="0",E.style.padding="0",E.style.margin="0",E.style.position="absolute",E.style[T?"right":"left"]="-9999px";var H=window.pageYOffset||document.documentElement.scrollTop;return E.style.top="".concat(H,"px"),E.setAttribute("readonly",""),E.value=j,E}var Y=function(T,E){var H=v(T);E.container.appendChild(H);var I=p()(H);return m("copy"),H.remove(),I},B=function(T){var E=arguments.length>1&&arguments[1]!==void 0?arguments[1]:{container:document.body},H="";return typeof T=="string"?H=Y(T,E):T instanceof HTMLInputElement&&!["text","search","url","tel","password"].includes(T==null?void 0:T.type)?H=Y(T.value,E):(H=p()(T),m("copy")),H},N=B;function O(j){"@babel/helpers - typeof";return typeof Symbol=="function"&&typeof Symbol.iterator=="symbol"?O=function(E){return typeof E}:O=function(E){return E&&typeof Symbol=="function"&&E.constructor===Symbol&&E!==Symbol.prototype?"symbol":typeof E},O(j)}var Qe=function(){var T=arguments.length>0&&arguments[0]!==void 0?arguments[0]:{},E=T.action,H=E===void 0?"copy":E,I=T.container,q=T.target,Me=T.text;if(H!=="copy"&&H!=="cut")throw new Error('Invalid "action" value, use either "copy" or "cut"');if(q!==void 0)if(q&&O(q)==="object"&&q.nodeType===1){if(H==="copy"&&q.hasAttribute("disabled"))throw new Error('Invalid "target" attribute. Please use "readonly" instead of "disabled" attribute');if(H==="cut"&&(q.hasAttribute("readonly")||q.hasAttribute("disabled")))throw new Error(`Invalid "target" attribute. You can't cut text from elements with "readonly" or "disabled" attributes`)}else throw new Error('Invalid "target" value, use a valid Element');if(Me)return N(Me,{container:I});if(q)return H==="cut"?h(q):N(q,{container:I})},De=Qe;function $e(j){"@babel/helpers - typeof";return typeof Symbol=="function"&&typeof Symbol.iterator=="symbol"?$e=function(E){return typeof E}:$e=function(E){return E&&typeof Symbol=="function"&&E.constructor===Symbol&&E!==Symbol.prototype?"symbol":typeof E},$e(j)}function Ei(j,T){if(!(j instanceof T))throw new TypeError("Cannot call a class as a function")}function tn(j,T){for(var E=0;E0&&arguments[0]!==void 0?arguments[0]:{};this.action=typeof I.action=="function"?I.action:this.defaultAction,this.target=typeof I.target=="function"?I.target:this.defaultTarget,this.text=typeof I.text=="function"?I.text:this.defaultText,this.container=$e(I.container)==="object"?I.container:document.body}},{key:"listenClick",value:function(I){var q=this;this.listener=c()(I,"click",function(Me){return q.onClick(Me)})}},{key:"onClick",value:function(I){var q=I.delegateTarget||I.currentTarget,Me=this.action(q)||"copy",kt=De({action:Me,container:this.container,target:this.target(q),text:this.text(q)});this.emit(kt?"success":"error",{action:Me,text:kt,trigger:q,clearSelection:function(){q&&q.focus(),window.getSelection().removeAllRanges()}})}},{key:"defaultAction",value:function(I){return vr("action",I)}},{key:"defaultTarget",value:function(I){var q=vr("target",I);if(q)return document.querySelector(q)}},{key:"defaultText",value:function(I){return vr("text",I)}},{key:"destroy",value:function(){this.listener.destroy()}}],[{key:"copy",value:function(I){var q=arguments.length>1&&arguments[1]!==void 0?arguments[1]:{container:document.body};return N(I,q)}},{key:"cut",value:function(I){return h(I)}},{key:"isSupported",value:function(){var I=arguments.length>0&&arguments[0]!==void 0?arguments[0]:["copy","cut"],q=typeof I=="string"?[I]:I,Me=!!document.queryCommandSupported;return q.forEach(function(kt){Me=Me&&!!document.queryCommandSupported(kt)}),Me}}]),E}(a()),Ai=Li},828:function(n){var o=9;if(typeof Element!="undefined"&&!Element.prototype.matches){var i=Element.prototype;i.matches=i.matchesSelector||i.mozMatchesSelector||i.msMatchesSelector||i.oMatchesSelector||i.webkitMatchesSelector}function s(a,f){for(;a&&a.nodeType!==o;){if(typeof a.matches=="function"&&a.matches(f))return a;a=a.parentNode}}n.exports=s},438:function(n,o,i){var s=i(828);function a(u,p,m,d,h){var v=c.apply(this,arguments);return u.addEventListener(m,v,h),{destroy:function(){u.removeEventListener(m,v,h)}}}function f(u,p,m,d,h){return typeof u.addEventListener=="function"?a.apply(null,arguments):typeof m=="function"?a.bind(null,document).apply(null,arguments):(typeof u=="string"&&(u=document.querySelectorAll(u)),Array.prototype.map.call(u,function(v){return a(v,p,m,d,h)}))}function c(u,p,m,d){return function(h){h.delegateTarget=s(h.target,p),h.delegateTarget&&d.call(u,h)}}n.exports=f},879:function(n,o){o.node=function(i){return i!==void 0&&i instanceof HTMLElement&&i.nodeType===1},o.nodeList=function(i){var s=Object.prototype.toString.call(i);return i!==void 0&&(s==="[object NodeList]"||s==="[object HTMLCollection]")&&"length"in i&&(i.length===0||o.node(i[0]))},o.string=function(i){return typeof i=="string"||i instanceof String},o.fn=function(i){var s=Object.prototype.toString.call(i);return s==="[object Function]"}},370:function(n,o,i){var s=i(879),a=i(438);function f(m,d,h){if(!m&&!d&&!h)throw new Error("Missing required arguments");if(!s.string(d))throw new TypeError("Second argument must be a String");if(!s.fn(h))throw new TypeError("Third argument must be a Function");if(s.node(m))return c(m,d,h);if(s.nodeList(m))return u(m,d,h);if(s.string(m))return p(m,d,h);throw new TypeError("First argument must be a String, HTMLElement, HTMLCollection, or NodeList")}function c(m,d,h){return m.addEventListener(d,h),{destroy:function(){m.removeEventListener(d,h)}}}function u(m,d,h){return Array.prototype.forEach.call(m,function(v){v.addEventListener(d,h)}),{destroy:function(){Array.prototype.forEach.call(m,function(v){v.removeEventListener(d,h)})}}}function p(m,d,h){return a(document.body,m,d,h)}n.exports=f},817:function(n){function o(i){var s;if(i.nodeName==="SELECT")i.focus(),s=i.value;else if(i.nodeName==="INPUT"||i.nodeName==="TEXTAREA"){var a=i.hasAttribute("readonly");a||i.setAttribute("readonly",""),i.select(),i.setSelectionRange(0,i.value.length),a||i.removeAttribute("readonly"),s=i.value}else{i.hasAttribute("contenteditable")&&i.focus();var f=window.getSelection(),c=document.createRange();c.selectNodeContents(i),f.removeAllRanges(),f.addRange(c),s=f.toString()}return s}n.exports=o},279:function(n){function o(){}o.prototype={on:function(i,s,a){var f=this.e||(this.e={});return(f[i]||(f[i]=[])).push({fn:s,ctx:a}),this},once:function(i,s,a){var f=this;function c(){f.off(i,c),s.apply(a,arguments)}return c._=s,this.on(i,c,a)},emit:function(i){var s=[].slice.call(arguments,1),a=((this.e||(this.e={}))[i]||[]).slice(),f=0,c=a.length;for(f;f{"use strict";/*! + * escape-html + * Copyright(c) 2012-2013 TJ Holowaychuk + * Copyright(c) 2015 Andreas Lubbe + * Copyright(c) 2015 Tiancheng "Timothy" Gu + * MIT Licensed + */var rs=/["'&<>]/;Yo.exports=ns;function ns(e){var t=""+e,r=rs.exec(t);if(!r)return t;var n,o="",i=0,s=0;for(i=r.index;i0&&i[i.length-1])&&(c[0]===6||c[0]===2)){r=0;continue}if(c[0]===3&&(!i||c[1]>i[0]&&c[1]=e.length&&(e=void 0),{value:e&&e[n++],done:!e}}};throw new TypeError(t?"Object is not iterable.":"Symbol.iterator is not defined.")}function W(e,t){var r=typeof Symbol=="function"&&e[Symbol.iterator];if(!r)return e;var n=r.call(e),o,i=[],s;try{for(;(t===void 0||t-- >0)&&!(o=n.next()).done;)i.push(o.value)}catch(a){s={error:a}}finally{try{o&&!o.done&&(r=n.return)&&r.call(n)}finally{if(s)throw s.error}}return i}function D(e,t,r){if(r||arguments.length===2)for(var n=0,o=t.length,i;n1||a(m,d)})})}function a(m,d){try{f(n[m](d))}catch(h){p(i[0][3],h)}}function f(m){m.value instanceof et?Promise.resolve(m.value.v).then(c,u):p(i[0][2],m)}function c(m){a("next",m)}function u(m){a("throw",m)}function p(m,d){m(d),i.shift(),i.length&&a(i[0][0],i[0][1])}}function pn(e){if(!Symbol.asyncIterator)throw new TypeError("Symbol.asyncIterator is not defined.");var t=e[Symbol.asyncIterator],r;return t?t.call(e):(e=typeof Ee=="function"?Ee(e):e[Symbol.iterator](),r={},n("next"),n("throw"),n("return"),r[Symbol.asyncIterator]=function(){return this},r);function n(i){r[i]=e[i]&&function(s){return new Promise(function(a,f){s=e[i](s),o(a,f,s.done,s.value)})}}function o(i,s,a,f){Promise.resolve(f).then(function(c){i({value:c,done:a})},s)}}function C(e){return typeof e=="function"}function at(e){var t=function(n){Error.call(n),n.stack=new Error().stack},r=e(t);return r.prototype=Object.create(Error.prototype),r.prototype.constructor=r,r}var It=at(function(e){return function(r){e(this),this.message=r?r.length+` errors occurred during unsubscription: +`+r.map(function(n,o){return o+1+") "+n.toString()}).join(` + `):"",this.name="UnsubscriptionError",this.errors=r}});function Ve(e,t){if(e){var r=e.indexOf(t);0<=r&&e.splice(r,1)}}var Ie=function(){function e(t){this.initialTeardown=t,this.closed=!1,this._parentage=null,this._finalizers=null}return e.prototype.unsubscribe=function(){var t,r,n,o,i;if(!this.closed){this.closed=!0;var s=this._parentage;if(s)if(this._parentage=null,Array.isArray(s))try{for(var a=Ee(s),f=a.next();!f.done;f=a.next()){var c=f.value;c.remove(this)}}catch(v){t={error:v}}finally{try{f&&!f.done&&(r=a.return)&&r.call(a)}finally{if(t)throw t.error}}else s.remove(this);var u=this.initialTeardown;if(C(u))try{u()}catch(v){i=v instanceof It?v.errors:[v]}var p=this._finalizers;if(p){this._finalizers=null;try{for(var m=Ee(p),d=m.next();!d.done;d=m.next()){var h=d.value;try{ln(h)}catch(v){i=i!=null?i:[],v instanceof It?i=D(D([],W(i)),W(v.errors)):i.push(v)}}}catch(v){n={error:v}}finally{try{d&&!d.done&&(o=m.return)&&o.call(m)}finally{if(n)throw n.error}}}if(i)throw new It(i)}},e.prototype.add=function(t){var r;if(t&&t!==this)if(this.closed)ln(t);else{if(t instanceof e){if(t.closed||t._hasParent(this))return;t._addParent(this)}(this._finalizers=(r=this._finalizers)!==null&&r!==void 0?r:[]).push(t)}},e.prototype._hasParent=function(t){var r=this._parentage;return r===t||Array.isArray(r)&&r.includes(t)},e.prototype._addParent=function(t){var r=this._parentage;this._parentage=Array.isArray(r)?(r.push(t),r):r?[r,t]:t},e.prototype._removeParent=function(t){var r=this._parentage;r===t?this._parentage=null:Array.isArray(r)&&Ve(r,t)},e.prototype.remove=function(t){var r=this._finalizers;r&&Ve(r,t),t instanceof e&&t._removeParent(this)},e.EMPTY=function(){var t=new e;return t.closed=!0,t}(),e}();var Sr=Ie.EMPTY;function jt(e){return e instanceof Ie||e&&"closed"in e&&C(e.remove)&&C(e.add)&&C(e.unsubscribe)}function ln(e){C(e)?e():e.unsubscribe()}var Le={onUnhandledError:null,onStoppedNotification:null,Promise:void 0,useDeprecatedSynchronousErrorHandling:!1,useDeprecatedNextContext:!1};var st={setTimeout:function(e,t){for(var r=[],n=2;n0},enumerable:!1,configurable:!0}),t.prototype._trySubscribe=function(r){return this._throwIfClosed(),e.prototype._trySubscribe.call(this,r)},t.prototype._subscribe=function(r){return this._throwIfClosed(),this._checkFinalizedStatuses(r),this._innerSubscribe(r)},t.prototype._innerSubscribe=function(r){var n=this,o=this,i=o.hasError,s=o.isStopped,a=o.observers;return i||s?Sr:(this.currentObservers=null,a.push(r),new Ie(function(){n.currentObservers=null,Ve(a,r)}))},t.prototype._checkFinalizedStatuses=function(r){var n=this,o=n.hasError,i=n.thrownError,s=n.isStopped;o?r.error(i):s&&r.complete()},t.prototype.asObservable=function(){var r=new F;return r.source=this,r},t.create=function(r,n){return new xn(r,n)},t}(F);var xn=function(e){ie(t,e);function t(r,n){var o=e.call(this)||this;return o.destination=r,o.source=n,o}return t.prototype.next=function(r){var n,o;(o=(n=this.destination)===null||n===void 0?void 0:n.next)===null||o===void 0||o.call(n,r)},t.prototype.error=function(r){var n,o;(o=(n=this.destination)===null||n===void 0?void 0:n.error)===null||o===void 0||o.call(n,r)},t.prototype.complete=function(){var r,n;(n=(r=this.destination)===null||r===void 0?void 0:r.complete)===null||n===void 0||n.call(r)},t.prototype._subscribe=function(r){var n,o;return(o=(n=this.source)===null||n===void 0?void 0:n.subscribe(r))!==null&&o!==void 0?o:Sr},t}(x);var Et={now:function(){return(Et.delegate||Date).now()},delegate:void 0};var wt=function(e){ie(t,e);function t(r,n,o){r===void 0&&(r=1/0),n===void 0&&(n=1/0),o===void 0&&(o=Et);var i=e.call(this)||this;return i._bufferSize=r,i._windowTime=n,i._timestampProvider=o,i._buffer=[],i._infiniteTimeWindow=!0,i._infiniteTimeWindow=n===1/0,i._bufferSize=Math.max(1,r),i._windowTime=Math.max(1,n),i}return t.prototype.next=function(r){var n=this,o=n.isStopped,i=n._buffer,s=n._infiniteTimeWindow,a=n._timestampProvider,f=n._windowTime;o||(i.push(r),!s&&i.push(a.now()+f)),this._trimBuffer(),e.prototype.next.call(this,r)},t.prototype._subscribe=function(r){this._throwIfClosed(),this._trimBuffer();for(var n=this._innerSubscribe(r),o=this,i=o._infiniteTimeWindow,s=o._buffer,a=s.slice(),f=0;f0?e.prototype.requestAsyncId.call(this,r,n,o):(r.actions.push(this),r._scheduled||(r._scheduled=ut.requestAnimationFrame(function(){return r.flush(void 0)})))},t.prototype.recycleAsyncId=function(r,n,o){var i;if(o===void 0&&(o=0),o!=null?o>0:this.delay>0)return e.prototype.recycleAsyncId.call(this,r,n,o);var s=r.actions;n!=null&&((i=s[s.length-1])===null||i===void 0?void 0:i.id)!==n&&(ut.cancelAnimationFrame(n),r._scheduled=void 0)},t}(Wt);var Sn=function(e){ie(t,e);function t(){return e!==null&&e.apply(this,arguments)||this}return t.prototype.flush=function(r){this._active=!0;var n=this._scheduled;this._scheduled=void 0;var o=this.actions,i;r=r||o.shift();do if(i=r.execute(r.state,r.delay))break;while((r=o[0])&&r.id===n&&o.shift());if(this._active=!1,i){for(;(r=o[0])&&r.id===n&&o.shift();)r.unsubscribe();throw i}},t}(Dt);var Oe=new Sn(wn);var M=new F(function(e){return e.complete()});function Vt(e){return e&&C(e.schedule)}function Cr(e){return e[e.length-1]}function Ye(e){return C(Cr(e))?e.pop():void 0}function Te(e){return Vt(Cr(e))?e.pop():void 0}function zt(e,t){return typeof Cr(e)=="number"?e.pop():t}var pt=function(e){return e&&typeof e.length=="number"&&typeof e!="function"};function Nt(e){return C(e==null?void 0:e.then)}function qt(e){return C(e[ft])}function Kt(e){return Symbol.asyncIterator&&C(e==null?void 0:e[Symbol.asyncIterator])}function Qt(e){return new TypeError("You provided "+(e!==null&&typeof e=="object"?"an invalid object":"'"+e+"'")+" where a stream was expected. You can provide an Observable, Promise, ReadableStream, Array, AsyncIterable, or Iterable.")}function zi(){return typeof Symbol!="function"||!Symbol.iterator?"@@iterator":Symbol.iterator}var Yt=zi();function Gt(e){return C(e==null?void 0:e[Yt])}function Bt(e){return un(this,arguments,function(){var r,n,o,i;return $t(this,function(s){switch(s.label){case 0:r=e.getReader(),s.label=1;case 1:s.trys.push([1,,9,10]),s.label=2;case 2:return[4,et(r.read())];case 3:return n=s.sent(),o=n.value,i=n.done,i?[4,et(void 0)]:[3,5];case 4:return[2,s.sent()];case 5:return[4,et(o)];case 6:return[4,s.sent()];case 7:return s.sent(),[3,2];case 8:return[3,10];case 9:return r.releaseLock(),[7];case 10:return[2]}})})}function Jt(e){return C(e==null?void 0:e.getReader)}function U(e){if(e instanceof F)return e;if(e!=null){if(qt(e))return Ni(e);if(pt(e))return qi(e);if(Nt(e))return Ki(e);if(Kt(e))return On(e);if(Gt(e))return Qi(e);if(Jt(e))return Yi(e)}throw Qt(e)}function Ni(e){return new F(function(t){var r=e[ft]();if(C(r.subscribe))return r.subscribe(t);throw new TypeError("Provided object does not correctly implement Symbol.observable")})}function qi(e){return new F(function(t){for(var r=0;r=2;return function(n){return n.pipe(e?A(function(o,i){return e(o,i,n)}):de,ge(1),r?He(t):Dn(function(){return new Zt}))}}function Vn(){for(var e=[],t=0;t=2,!0))}function pe(e){e===void 0&&(e={});var t=e.connector,r=t===void 0?function(){return new x}:t,n=e.resetOnError,o=n===void 0?!0:n,i=e.resetOnComplete,s=i===void 0?!0:i,a=e.resetOnRefCountZero,f=a===void 0?!0:a;return function(c){var u,p,m,d=0,h=!1,v=!1,Y=function(){p==null||p.unsubscribe(),p=void 0},B=function(){Y(),u=m=void 0,h=v=!1},N=function(){var O=u;B(),O==null||O.unsubscribe()};return y(function(O,Qe){d++,!v&&!h&&Y();var De=m=m!=null?m:r();Qe.add(function(){d--,d===0&&!v&&!h&&(p=$r(N,f))}),De.subscribe(Qe),!u&&d>0&&(u=new rt({next:function($e){return De.next($e)},error:function($e){v=!0,Y(),p=$r(B,o,$e),De.error($e)},complete:function(){h=!0,Y(),p=$r(B,s),De.complete()}}),U(O).subscribe(u))})(c)}}function $r(e,t){for(var r=[],n=2;ne.next(document)),e}function K(e,t=document){return Array.from(t.querySelectorAll(e))}function z(e,t=document){let r=ce(e,t);if(typeof r=="undefined")throw new ReferenceError(`Missing element: expected "${e}" to be present`);return r}function ce(e,t=document){return t.querySelector(e)||void 0}function _e(){return document.activeElement instanceof HTMLElement&&document.activeElement||void 0}function tr(e){return L(b(document.body,"focusin"),b(document.body,"focusout")).pipe(ke(1),l(()=>{let t=_e();return typeof t!="undefined"?e.contains(t):!1}),V(e===_e()),J())}function Xe(e){return{x:e.offsetLeft,y:e.offsetTop}}function Kn(e){return L(b(window,"load"),b(window,"resize")).pipe(Ce(0,Oe),l(()=>Xe(e)),V(Xe(e)))}function rr(e){return{x:e.scrollLeft,y:e.scrollTop}}function dt(e){return L(b(e,"scroll"),b(window,"resize")).pipe(Ce(0,Oe),l(()=>rr(e)),V(rr(e)))}var Yn=function(){if(typeof Map!="undefined")return Map;function e(t,r){var n=-1;return t.some(function(o,i){return o[0]===r?(n=i,!0):!1}),n}return function(){function t(){this.__entries__=[]}return Object.defineProperty(t.prototype,"size",{get:function(){return this.__entries__.length},enumerable:!0,configurable:!0}),t.prototype.get=function(r){var n=e(this.__entries__,r),o=this.__entries__[n];return o&&o[1]},t.prototype.set=function(r,n){var o=e(this.__entries__,r);~o?this.__entries__[o][1]=n:this.__entries__.push([r,n])},t.prototype.delete=function(r){var n=this.__entries__,o=e(n,r);~o&&n.splice(o,1)},t.prototype.has=function(r){return!!~e(this.__entries__,r)},t.prototype.clear=function(){this.__entries__.splice(0)},t.prototype.forEach=function(r,n){n===void 0&&(n=null);for(var o=0,i=this.__entries__;o0},e.prototype.connect_=function(){!Wr||this.connected_||(document.addEventListener("transitionend",this.onTransitionEnd_),window.addEventListener("resize",this.refresh),va?(this.mutationsObserver_=new MutationObserver(this.refresh),this.mutationsObserver_.observe(document,{attributes:!0,childList:!0,characterData:!0,subtree:!0})):(document.addEventListener("DOMSubtreeModified",this.refresh),this.mutationEventsAdded_=!0),this.connected_=!0)},e.prototype.disconnect_=function(){!Wr||!this.connected_||(document.removeEventListener("transitionend",this.onTransitionEnd_),window.removeEventListener("resize",this.refresh),this.mutationsObserver_&&this.mutationsObserver_.disconnect(),this.mutationEventsAdded_&&document.removeEventListener("DOMSubtreeModified",this.refresh),this.mutationsObserver_=null,this.mutationEventsAdded_=!1,this.connected_=!1)},e.prototype.onTransitionEnd_=function(t){var r=t.propertyName,n=r===void 0?"":r,o=ba.some(function(i){return!!~n.indexOf(i)});o&&this.refresh()},e.getInstance=function(){return this.instance_||(this.instance_=new e),this.instance_},e.instance_=null,e}(),Gn=function(e,t){for(var r=0,n=Object.keys(t);r0},e}(),Jn=typeof WeakMap!="undefined"?new WeakMap:new Yn,Xn=function(){function e(t){if(!(this instanceof e))throw new TypeError("Cannot call a class as a function.");if(!arguments.length)throw new TypeError("1 argument required, but only 0 present.");var r=ga.getInstance(),n=new La(t,r,this);Jn.set(this,n)}return e}();["observe","unobserve","disconnect"].forEach(function(e){Xn.prototype[e]=function(){var t;return(t=Jn.get(this))[e].apply(t,arguments)}});var Aa=function(){return typeof nr.ResizeObserver!="undefined"?nr.ResizeObserver:Xn}(),Zn=Aa;var eo=new x,Ca=$(()=>k(new Zn(e=>{for(let t of e)eo.next(t)}))).pipe(g(e=>L(ze,k(e)).pipe(R(()=>e.disconnect()))),X(1));function he(e){return{width:e.offsetWidth,height:e.offsetHeight}}function ye(e){return Ca.pipe(S(t=>t.observe(e)),g(t=>eo.pipe(A(({target:r})=>r===e),R(()=>t.unobserve(e)),l(()=>he(e)))),V(he(e)))}function bt(e){return{width:e.scrollWidth,height:e.scrollHeight}}function ar(e){let t=e.parentElement;for(;t&&(e.scrollWidth<=t.scrollWidth&&e.scrollHeight<=t.scrollHeight);)t=(e=t).parentElement;return t?e:void 0}var to=new x,Ra=$(()=>k(new IntersectionObserver(e=>{for(let t of e)to.next(t)},{threshold:0}))).pipe(g(e=>L(ze,k(e)).pipe(R(()=>e.disconnect()))),X(1));function sr(e){return Ra.pipe(S(t=>t.observe(e)),g(t=>to.pipe(A(({target:r})=>r===e),R(()=>t.unobserve(e)),l(({isIntersecting:r})=>r))))}function ro(e,t=16){return dt(e).pipe(l(({y:r})=>{let n=he(e),o=bt(e);return r>=o.height-n.height-t}),J())}var cr={drawer:z("[data-md-toggle=drawer]"),search:z("[data-md-toggle=search]")};function no(e){return cr[e].checked}function Ke(e,t){cr[e].checked!==t&&cr[e].click()}function Ue(e){let t=cr[e];return b(t,"change").pipe(l(()=>t.checked),V(t.checked))}function ka(e,t){switch(e.constructor){case HTMLInputElement:return e.type==="radio"?/^Arrow/.test(t):!0;case HTMLSelectElement:case HTMLTextAreaElement:return!0;default:return e.isContentEditable}}function Ha(){return L(b(window,"compositionstart").pipe(l(()=>!0)),b(window,"compositionend").pipe(l(()=>!1))).pipe(V(!1))}function oo(){let e=b(window,"keydown").pipe(A(t=>!(t.metaKey||t.ctrlKey)),l(t=>({mode:no("search")?"search":"global",type:t.key,claim(){t.preventDefault(),t.stopPropagation()}})),A(({mode:t,type:r})=>{if(t==="global"){let n=_e();if(typeof n!="undefined")return!ka(n,r)}return!0}),pe());return Ha().pipe(g(t=>t?M:e))}function le(){return new URL(location.href)}function ot(e){location.href=e.href}function io(){return new x}function ao(e,t){if(typeof t=="string"||typeof t=="number")e.innerHTML+=t.toString();else if(t instanceof Node)e.appendChild(t);else if(Array.isArray(t))for(let r of t)ao(e,r)}function _(e,t,...r){let n=document.createElement(e);if(t)for(let o of Object.keys(t))typeof t[o]!="undefined"&&(typeof t[o]!="boolean"?n.setAttribute(o,t[o]):n.setAttribute(o,""));for(let o of r)ao(n,o);return n}function fr(e){if(e>999){let t=+((e-950)%1e3>99);return`${((e+1e-6)/1e3).toFixed(t)}k`}else return e.toString()}function so(){return location.hash.substring(1)}function Dr(e){let t=_("a",{href:e});t.addEventListener("click",r=>r.stopPropagation()),t.click()}function Pa(e){return L(b(window,"hashchange"),e).pipe(l(so),V(so()),A(t=>t.length>0),X(1))}function co(e){return Pa(e).pipe(l(t=>ce(`[id="${t}"]`)),A(t=>typeof t!="undefined"))}function Vr(e){let t=matchMedia(e);return er(r=>t.addListener(()=>r(t.matches))).pipe(V(t.matches))}function fo(){let e=matchMedia("print");return L(b(window,"beforeprint").pipe(l(()=>!0)),b(window,"afterprint").pipe(l(()=>!1))).pipe(V(e.matches))}function zr(e,t){return e.pipe(g(r=>r?t():M))}function ur(e,t={credentials:"same-origin"}){return ue(fetch(`${e}`,t)).pipe(fe(()=>M),g(r=>r.status!==200?Ot(()=>new Error(r.statusText)):k(r)))}function We(e,t){return ur(e,t).pipe(g(r=>r.json()),X(1))}function uo(e,t){let r=new DOMParser;return ur(e,t).pipe(g(n=>n.text()),l(n=>r.parseFromString(n,"text/xml")),X(1))}function pr(e){let t=_("script",{src:e});return $(()=>(document.head.appendChild(t),L(b(t,"load"),b(t,"error").pipe(g(()=>Ot(()=>new ReferenceError(`Invalid script: ${e}`))))).pipe(l(()=>{}),R(()=>document.head.removeChild(t)),ge(1))))}function po(){return{x:Math.max(0,scrollX),y:Math.max(0,scrollY)}}function lo(){return L(b(window,"scroll",{passive:!0}),b(window,"resize",{passive:!0})).pipe(l(po),V(po()))}function mo(){return{width:innerWidth,height:innerHeight}}function ho(){return b(window,"resize",{passive:!0}).pipe(l(mo),V(mo()))}function bo(){return G([lo(),ho()]).pipe(l(([e,t])=>({offset:e,size:t})),X(1))}function lr(e,{viewport$:t,header$:r}){let n=t.pipe(ee("size")),o=G([n,r]).pipe(l(()=>Xe(e)));return G([r,t,o]).pipe(l(([{height:i},{offset:s,size:a},{x:f,y:c}])=>({offset:{x:s.x-f,y:s.y-c+i},size:a})))}(()=>{function e(n,o){parent.postMessage(n,o||"*")}function t(...n){return n.reduce((o,i)=>o.then(()=>new Promise(s=>{let a=document.createElement("script");a.src=i,a.onload=s,document.body.appendChild(a)})),Promise.resolve())}var r=class extends EventTarget{constructor(n){super(),this.url=n,this.m=i=>{i.source===this.w&&(this.dispatchEvent(new MessageEvent("message",{data:i.data})),this.onmessage&&this.onmessage(i))},this.e=(i,s,a,f,c)=>{if(s===`${this.url}`){let u=new ErrorEvent("error",{message:i,filename:s,lineno:a,colno:f,error:c});this.dispatchEvent(u),this.onerror&&this.onerror(u)}};let o=document.createElement("iframe");o.hidden=!0,document.body.appendChild(this.iframe=o),this.w.document.open(),this.w.document.write(` + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+ + + +
+
+ + + + + + + +

Overview

+ +

ZodiPy logo

+

astropy +PyPI - Python Version +PyPI +Project Status: Active – The project has reached a stable, usable state and is being actively developed. +Actions Status +GitHub Actions Workflow Status +Codecov +arXiv Paper +ascl:2306.012

+

ZodiPy is an Astropy affiliated package for simulating zodiacal light in intensity for arbitrary Solar system observers. +ZodiPy Logo

+

A simple example

+
import astropy.units as u
+from astropy.time import Time
+
+from zodipy import Zodipy
+
+
+model = Zodipy("dirbe")
+
+emission = model.get_emission_ang(
+    25 * u.micron,
+    theta=[10, 10.1, 10.2] * u.deg,
+    phi=[90, 89, 88] * u.deg,
+    obs_time=Time("2022-01-01 12:00:00"),
+    obs="earth",
+    lonlat=True,
+)
+
+print(emission)
+#> [15.53095493 15.52883577 15.53121942] MJy / sr
+
+

What's going on here:

+
    +
  • We start by initializing the Zodipy class, which is our interface, where we specify that we want to use the DIRBE interplanetary dust model.
  • +
  • We use the get_emission_ang method which is a method to simulate emission from angular sky coordinates (see the reference for other available simulation methods).
  • +
  • The first argument to the get_emission_ang method, 25 * u.micron, specifies the wavelength of the simulated observation. Note that we use Astropy units for many of the input arguments.
  • +
  • theta and phi represent the pointing of the observation (co-latitude and longitude, following the healpy convention). In this example we observe three sky coordinates.
  • +
  • obs_time represents the time of observation, which we need to compute the position of the observer and all other required solar system bodies.
  • +
  • obs represents the observer, and must be an solar system observer supported by the Astropy ephemeris used internally. If we wish to be more specific about the observer position, we can use the obs_pos keyword instead of obs, which takes in a heliocentric cartesian position in units of AU.
  • +
  • Finally, lonlat is a boolean which converts the convention of theta and phi from co-latitude and longitude to longitude and latitude.
  • +
+

For more information on using ZodiPy, see the usage section.

+ + + + + + +
+
+ + +
+ +
+ + + +
+
+
+
+ + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/install/index.html b/install/index.html new file mode 100644 index 0000000..4b5b543 --- /dev/null +++ b/install/index.html @@ -0,0 +1,481 @@ + + + + + + + + + + + + + + + + + + + + + + + + Install - ZodiPy + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+ + + +
+
+ + + + + + + +

Install

+

Installing ZodiPy is as simple as:

+
pip install zodipy
+
+
+

Note

+

ZodiPy supports python versions >=3.9.

+
+

Dependencies

+

ZodiPy has the following dependencies (these are automatically downloaded alongside ZodiPy):

+ + + + + + + +
+
+ + +
+ +
+ + + +
+
+
+
+ + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/introduction/index.html b/introduction/index.html new file mode 100644 index 0000000..6ba4ccc --- /dev/null +++ b/introduction/index.html @@ -0,0 +1,505 @@ + + + + + + + + + + + + + + + + + + + + + + + + Introduction - ZodiPy + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+ + + +
+
+ + + + + + + +

Introduction

+

ZodiPy is an open source Python tool for simulating the zodiacal emission that a solar system observer is predicted to see given an interplanetary dust model. We attempts to make zodiacal emission simulations more accessible by providing the community with a simple interface to existing models. For other zodiacal emission tools, see Zodiacal Light Models on LAMBDA. All contributions are most welcome.

+

Interplanetary Dust Models

+

ZodiPy supports the following interplanetary dust models:

+

1.25-240 \(\boldsymbol{\mu}\)m

+ +

100-857 GHz

+ +
+

Info

+

The Planck and Odegard models extend the DIRBE interplanetary dust model to CMB frequencies by fitting the blackbody emissivity of the dust in the respective DIRBE interplanetary dust components to Planck HFI data. +The distribution of the interplanetary dust is exactly the same as in the DIRBE model.

+
+

If you see a missing model, please feel free to contact us by opening an issue on GitHub.

+

Scientific Paper

+

For an overview of the modeling approach used in ZodiPy and other information regarding zodiacal emission and interplanetary dust modeling we refer to the scientific paper on ZodiPy:

+ + + + + + + +
+
+ + +
+ +
+ + + +
+
+
+
+ + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/javascripts/mathjax.js b/javascripts/mathjax.js new file mode 100644 index 0000000..83beb4d --- /dev/null +++ b/javascripts/mathjax.js @@ -0,0 +1,19 @@ +window.MathJax = { + loader: {load: ['[tex]/boldsymbol']}, + tex: { + inlineMath: [["\\(", "\\)"]], + displayMath: [["\\[", "\\]"]], + processEscapes: true, + processEnvironments: true, + packages: {'[+]': ['boldsymbol']} + }, + options: { + ignoreHtmlClass: ".*|", + processHtmlClass: "arithmatex" + } + }; + + document$.subscribe(() => { + MathJax.typesetPromise() + }) + \ No newline at end of file diff --git a/objects.inv b/objects.inv new file mode 100644 index 0000000..b136e5e Binary files /dev/null and b/objects.inv differ diff --git a/reference/index.html b/reference/index.html new file mode 100644 index 0000000..0efb440 --- /dev/null +++ b/reference/index.html @@ -0,0 +1,3315 @@ + + + + + + + + + + + + + + + + + + + + + + Reference - ZodiPy + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+ + + +
+
+ + + + + + + +

Reference

+ + +
+ + + + +
+ + + +
+ + + + + + + + +
+ + + +

+ Zodipy + + +

+ + +
+ + +

Interface for simulating zodiacal emission.

+

This class provides methods for simulating zodiacal emission given observer pointing +either in sky angles or through HEALPix pixels.

+ + + +

Parameters:

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescriptionDefault
model + str + +
+

Name of the interplanetary dust model to use in the simulations. +Defaults to DIRBE.

+
+
+ 'dirbe' +
gauss_quad_degree + int + +
+

Order of the Gaussian-Legendre quadrature used to evaluate +the line-of-sight integral in the simulations. Default is 50 points.

+
+
+ 50 +
interp_kind + str + +
+

Interpolation kind used to interpolate relevant model parameters. +Defaults to 'linear'. For more information on available interpolation methods, +please visit the Scipy documentation.

+
+
+ 'linear' +
extrapolate + bool + +
+

If True all spectral quantities in the selected model are +extrapolated to the requested frequencies or wavelengths. If False, an +exception is raised on requested frequencies/wavelengths outside of the +valid model range. Default is False.

+
+
+ False +
ephemeris + str + +
+

Ephemeris used to compute the positions of the observer and the +Earth. Defaults to 'de432s', which requires downloading (and caching) a ~10MB +file. For more information on available ephemeridis, please visit the Astropy +documentation

+
+
+ 'de432s' +
solar_cut + Quantity[deg] + +
+

Cutoff angle from the sun in degrees. The emission +for all the pointing with angular distance between the sun smaller than +solar_cutoff are masked. Defaults to None.

+
+
+ None +
solar_cut_fill_value + float + +
+

Fill value for pixels masked with solar_cut. +Defaults to np.nan.

+
+
+ nan +
n_proc + int + +
+

Number of cores to use. If n_proc is greater than 1, the line-of-sight +integrals are parallelized using the multiprocessing module. Defaults to 1.

+
+
+ 1 +
+ +
+ Source code in zodipy/zodipy.py +
 37
+ 38
+ 39
+ 40
+ 41
+ 42
+ 43
+ 44
+ 45
+ 46
+ 47
+ 48
+ 49
+ 50
+ 51
+ 52
+ 53
+ 54
+ 55
+ 56
+ 57
+ 58
+ 59
+ 60
+ 61
+ 62
+ 63
+ 64
+ 65
+ 66
+ 67
+ 68
+ 69
+ 70
+ 71
+ 72
+ 73
+ 74
+ 75
+ 76
+ 77
+ 78
+ 79
+ 80
+ 81
+ 82
+ 83
+ 84
+ 85
+ 86
+ 87
+ 88
+ 89
+ 90
+ 91
+ 92
+ 93
+ 94
+ 95
+ 96
+ 97
+ 98
+ 99
+100
+101
+102
+103
+104
+105
+106
+107
+108
+109
+110
+111
+112
+113
+114
+115
+116
+117
+118
+119
+120
+121
+122
+123
+124
+125
+126
+127
+128
+129
+130
+131
+132
+133
+134
+135
+136
+137
+138
+139
+140
+141
+142
+143
+144
+145
+146
+147
+148
+149
+150
+151
+152
+153
+154
+155
+156
+157
+158
+159
+160
+161
+162
+163
+164
+165
+166
+167
+168
+169
+170
+171
+172
+173
+174
+175
+176
+177
+178
+179
+180
+181
+182
+183
+184
+185
+186
+187
+188
+189
+190
+191
+192
+193
+194
+195
+196
+197
+198
+199
+200
+201
+202
+203
+204
+205
+206
+207
+208
+209
+210
+211
+212
+213
+214
+215
+216
+217
+218
+219
+220
+221
+222
+223
+224
+225
+226
+227
+228
+229
+230
+231
+232
+233
+234
+235
+236
+237
+238
+239
+240
+241
+242
+243
+244
+245
+246
+247
+248
+249
+250
+251
+252
+253
+254
+255
+256
+257
+258
+259
+260
+261
+262
+263
+264
+265
+266
+267
+268
+269
+270
+271
+272
+273
+274
+275
+276
+277
+278
+279
+280
+281
+282
+283
+284
+285
+286
+287
+288
+289
+290
+291
+292
+293
+294
+295
+296
+297
+298
+299
+300
+301
+302
+303
+304
+305
+306
+307
+308
+309
+310
+311
+312
+313
+314
+315
+316
+317
+318
+319
+320
+321
+322
+323
+324
+325
+326
+327
+328
+329
+330
+331
+332
+333
+334
+335
+336
+337
+338
+339
+340
+341
+342
+343
+344
+345
+346
+347
+348
+349
+350
+351
+352
+353
+354
+355
+356
+357
+358
+359
+360
+361
+362
+363
+364
+365
+366
+367
+368
+369
+370
+371
+372
+373
+374
+375
+376
+377
+378
+379
+380
+381
+382
+383
+384
+385
+386
+387
+388
+389
+390
+391
+392
+393
+394
+395
+396
+397
+398
+399
+400
+401
+402
+403
+404
+405
+406
+407
+408
+409
+410
+411
+412
+413
+414
+415
+416
+417
+418
+419
+420
+421
+422
+423
+424
+425
+426
+427
+428
+429
+430
+431
+432
+433
+434
+435
+436
+437
+438
+439
+440
+441
+442
+443
+444
+445
+446
+447
+448
+449
+450
+451
+452
+453
+454
+455
+456
+457
+458
+459
+460
+461
+462
+463
+464
+465
+466
+467
+468
+469
+470
+471
+472
+473
+474
+475
+476
+477
+478
+479
+480
+481
+482
+483
+484
+485
+486
+487
+488
+489
+490
+491
+492
+493
+494
+495
+496
+497
+498
+499
+500
+501
+502
+503
+504
+505
+506
+507
+508
+509
+510
+511
+512
+513
+514
+515
+516
+517
+518
+519
+520
+521
+522
+523
+524
+525
+526
+527
+528
+529
+530
+531
+532
+533
+534
+535
+536
+537
+538
+539
class Zodipy:
+    """Interface for simulating zodiacal emission.
+
+    This class provides methods for simulating zodiacal emission given observer pointing
+    either in sky angles or through HEALPix pixels.
+
+    Args:
+        model (str): Name of the interplanetary dust model to use in the simulations.
+            Defaults to DIRBE.
+        gauss_quad_degree (int): Order of the Gaussian-Legendre quadrature used to evaluate
+            the line-of-sight integral in the simulations. Default is 50 points.
+        interp_kind (str): Interpolation kind used to interpolate relevant model parameters.
+            Defaults to 'linear'. For more information on available interpolation methods,
+            please visit the [Scipy documentation](
+            https://docs.scipy.org/doc/scipy/reference/generated/scipy.interpolate.interp1d.html).
+        extrapolate (bool): If `True` all spectral quantities in the selected model are
+            extrapolated to the requested frequencies or wavelengths. If `False`, an
+            exception is raised on requested frequencies/wavelengths outside of the
+            valid model range. Default is `False`.
+        ephemeris (str): Ephemeris used to compute the positions of the observer and the
+            Earth. Defaults to 'de432s', which requires downloading (and caching) a ~10MB
+            file. For more information on available ephemeridis, please visit the [Astropy
+            documentation](https://docs.astropy.org/en/stable/coordinates/solarsystem.html)
+        solar_cut (u.Quantity[u.deg]): Cutoff angle from the sun in degrees. The emission
+            for all the pointing with angular distance between the sun smaller than
+            `solar_cutoff` are masked. Defaults to `None`.
+        solar_cut_fill_value (float): Fill value for pixels masked with `solar_cut`.
+            Defaults to `np.nan`.
+        n_proc (int): Number of cores to use. If `n_proc` is greater than 1, the line-of-sight
+            integrals are parallelized using the `multiprocessing` module. Defaults to 1.
+
+    """
+
+    def __init__(
+        self,
+        model: str = "dirbe",
+        gauss_quad_degree: int = 50,
+        extrapolate: bool = False,
+        interp_kind: str = "linear",
+        ephemeris: str = "de432s",
+        solar_cut: u.Quantity[u.deg] | None = None,
+        solar_cut_fill_value: float = np.nan,
+        n_proc: int = 1,
+    ) -> None:
+        self.model = model
+        self.gauss_quad_degree = gauss_quad_degree
+        self.extrapolate = extrapolate
+        self.interp_kind = interp_kind
+        self.ephemeris = ephemeris
+        self.solar_cut = solar_cut.to(u.rad) if solar_cut is not None else solar_cut
+        self.solar_cut_fill_value = solar_cut_fill_value
+        self.n_proc = n_proc
+
+        self._interpolator = partial(
+            interp1d,
+            kind=self.interp_kind,
+            fill_value="extrapolate" if self.extrapolate else np.nan,
+        )
+        self._ipd_model = model_registry.get_model(model)
+        self._gauss_points_and_weights = np.polynomial.legendre.leggauss(gauss_quad_degree)
+
+    @property
+    def supported_observers(self) -> list[str]:
+        """Return a list of available observers given an ephemeris."""
+        return [*list(solar_system_ephemeris.bodies), "semb-l2"]
+
+    def get_parameters(self) -> ParameterDict:
+        """Return a dictionary containing the interplanetary dust model parameters."""
+        return self._ipd_model.to_dict()
+
+    def update_parameters(self, parameters: ParameterDict) -> None:
+        """Update the interplanetary dust model parameters.
+
+        Args:
+            parameters: Dictionary of parameters to update. The keys must be the names
+                of the parameters as defined in the model. To get the parameters dict
+                of an existing model, use `Zodipy("dirbe").get_parameters()`.
+
+        """
+        _dict = parameters.copy()
+        _dict["comps"] = {}
+        for key, value in parameters.items():
+            if key == "comps":
+                for comp_key, comp_value in value.items():
+                    _dict["comps"][ComponentLabel(comp_key)] = type(
+                        self._ipd_model.comps[ComponentLabel(comp_key)]
+                    )(**comp_value)
+            elif isinstance(value, dict):
+                _dict[key] = {ComponentLabel(k): v for k, v in value.items()}
+
+        self._ipd_model = self._ipd_model.__class__(**_dict)
+
+    def get_emission_ang(
+        self,
+        freq: FrequencyOrWavelength,
+        theta: SkyAngles,
+        phi: SkyAngles,
+        obs_time: Time,
+        obs: str = "earth",
+        obs_pos: u.Quantity[u.AU] | None = None,
+        weights: Sequence[float] | npt.NDArray[np.floating] | None = None,
+        lonlat: bool = False,
+        return_comps: bool = False,
+        coord_in: Literal["E", "G", "C"] = "E",
+    ) -> u.Quantity[u.MJy / u.sr]:
+        """Return the simulated zodiacal emission given angles on the sky.
+
+        The pointing, for which to compute the emission, is specified in form of angles on
+        the sky given by `theta` and `phi`.
+
+        Args:
+            freq: Delta frequency/wavelength or a sequence of frequencies corresponding to
+                a bandpass over which to evaluate the zodiacal emission. The frequencies
+                must be strictly increasing.
+            theta: Angular co-latitude coordinate of a point, or a sequence of points, on
+                the celestial sphere. Must be in the range [0, π] rad. Units must be either
+                radians or degrees.
+            phi: Angular longitude coordinate of a point, or a sequence of points, on the
+                celestial sphere. Must be in the range [0, 2π] rad. Units must be either
+                radians or degrees.
+            obs_time: Time of observation.
+            obs: Name of the Solar System observer. A list of all support observers (for a
+                given ephemeridis) is specified in `supported_observers` attribute of the
+                `Zodipy` instance. Defaults to 'earth'.
+            obs_pos: The heliocentric ecliptic cartesian position of the observer in AU.
+                Overrides the `obs` argument. Default is None.
+            weights: Bandpass weights corresponding the the frequencies in `freq`. The weights
+                are assumed to be given in spectral radiance units (Jy/sr).
+            lonlat: If True, input angles (`theta`, `phi`) are assumed to be longitude and
+                latitude, otherwise, they are co-latitude and longitude.
+            return_comps: If True, the emission is returned component-wise. Defaults to False.
+            coord_in: Coordinate frame of the input pointing. Assumes 'E' (ecliptic
+                coordinates) by default.
+
+        Returns:
+            emission: Simulated zodiacal emission in units of 'MJy/sr'.
+
+        """
+        theta, phi = get_validated_ang(theta=theta, phi=phi, lonlat=lonlat)
+
+        unique_angles, indicies = np.unique(np.asarray([theta, phi]), return_inverse=True, axis=1)
+        unit_vectors = get_unit_vectors_from_ang(
+            coord_in=coord_in,
+            theta=unique_angles[0],
+            phi=unique_angles[1],
+            lonlat=lonlat,
+        )
+
+        return self._compute_emission(
+            freq=freq,
+            weights=weights,
+            obs=obs,
+            obs_time=obs_time,
+            obs_pos=obs_pos,
+            unit_vectors=unit_vectors,
+            indicies=indicies,
+            return_comps=return_comps,
+        )
+
+    def get_emission_pix(
+        self,
+        freq: FrequencyOrWavelength,
+        pixels: Pixels,
+        nside: int,
+        obs_time: Time,
+        obs: str = "earth",
+        obs_pos: u.Quantity[u.AU] | None = None,
+        weights: Sequence[float] | npt.NDArray[np.floating] | None = None,
+        return_comps: bool = False,
+        coord_in: Literal["E", "G", "C"] = "E",
+    ) -> u.Quantity[u.MJy / u.sr]:
+        """Return the simulated zodiacal emission given pixel numbers.
+
+        The pixel numbers represent the pixel indicies on a HEALPix grid with resolution
+        given by `nside`.
+
+        Args:
+            freq: Delta frequency/wavelength or a sequence of frequencies corresponding to
+                a bandpass over which to evaluate the zodiacal emission. The frequencies
+                must be strictly increasing.
+            pixels: HEALPix pixel indicies representing points on the celestial sphere.
+            nside: HEALPix resolution parameter of the pixels and the binned map.
+            obs_time: Time of observation.
+            obs: Name of the Solar System observer. A list of all support observers (for a
+                given ephemeridis) is specified in `supported_observers` attribute of the
+                `Zodipy` instance. Defaults to 'earth'.
+            obs_pos: The heliocentric ecliptic cartesian position of the observer in AU.
+                Overrides the `obs` argument. Default is None.
+            weights: Bandpass weights corresponding the the frequencies in `freq`. The weights
+                are assumed to be given in spectral radiance units (Jy/sr).
+            return_comps: If True, the emission is returned component-wise. Defaults to False.
+            coord_in: Coordinate frame of the input pointing. Assumes 'E' (ecliptic
+                coordinates) by default.
+
+        Returns:
+            emission: Simulated zodiacal emission in units of 'MJy/sr'.
+
+        """
+        pixels = get_validated_pix(pixels=pixels, nside=nside)
+
+        unique_pixels, indicies = np.unique(pixels, return_inverse=True)
+        unit_vectors = get_unit_vectors_from_pixels(
+            coord_in=coord_in,
+            pixels=unique_pixels,
+            nside=nside,
+        )
+
+        return self._compute_emission(
+            freq=freq,
+            weights=weights,
+            obs=obs,
+            obs_time=obs_time,
+            obs_pos=obs_pos,
+            unit_vectors=unit_vectors,
+            indicies=indicies,
+            pixels=unique_pixels,
+            nside=nside,
+            return_comps=return_comps,
+        )
+
+    def get_binned_emission_ang(
+        self,
+        freq: FrequencyOrWavelength,
+        theta: SkyAngles,
+        phi: SkyAngles,
+        nside: int,
+        obs_time: Time,
+        obs: str = "earth",
+        obs_pos: u.Quantity[u.AU] | None = None,
+        weights: Sequence[float] | npt.NDArray[np.floating] | None = None,
+        lonlat: bool = False,
+        return_comps: bool = False,
+        coord_in: Literal["E", "G", "C"] = "E",
+    ) -> u.Quantity[u.MJy / u.sr]:
+        """Return the simulated binned zodiacal emission given angles on the sky.
+
+        The pointing, for which to compute the emission, is specified in form of angles on
+        the sky given by `theta` and `phi`. The emission is binned to a HEALPix map with
+        resolution given by `nside`.
+
+        Args:
+            freq: Delta frequency/wavelength or a sequence of frequencies corresponding to
+                a bandpass over which to evaluate the zodiacal emission. The frequencies
+                must be strictly increasing.
+            theta: Angular co-latitude coordinate of a point, or a sequence of points, on
+                the celestial sphere. Must be in the range [0, π] rad. Units must be either
+                radians or degrees.
+            phi: Angular longitude coordinate of a point, or a sequence of points, on the
+                celestial sphere. Must be in the range [0, 2π] rad. Units must be either
+                radians or degrees.
+            nside: HEALPix resolution parameter of the binned map.
+            obs_time: Time of observation.
+            obs: Name of the Solar System observer. A list of all support observers (for a
+                given ephemeridis) is specified in `supported_observers` attribute of the
+                `Zodipy` instance. Defaults to 'earth'.
+            obs_pos: The heliocentric ecliptic cartesian position of the observer in AU.
+                Overrides the `obs` argument. Default is None.
+            weights: Bandpass weights corresponding the the frequencies in `freq`. The weights
+                are assumed to be given in spectral radiance units (Jy/sr).
+            lonlat: If True, input angles `theta`, `phi` are assumed to be longitude and
+                latitude, otherwise, they are co-latitude and longitude.
+            return_comps: If True, the emission is returned component-wise. Defaults to False.
+            coord_in: Coordinate frame of the input pointing. Assumes 'E' (ecliptic
+                coordinates) by default.
+
+        Returns:
+            emission: Simulated zodiacal emission in units of 'MJy/sr'.
+
+        """
+        theta, phi = get_validated_ang(theta=theta, phi=phi, lonlat=lonlat)
+
+        unique_angles, counts = np.unique(np.asarray([theta, phi]), return_counts=True, axis=1)
+        unique_pixels = hp.ang2pix(nside, *unique_angles, lonlat=lonlat)
+        unit_vectors = get_unit_vectors_from_ang(
+            coord_in=coord_in,
+            theta=unique_angles[0],
+            phi=unique_angles[1],
+            lonlat=lonlat,
+        )
+
+        return self._compute_emission(
+            freq=freq,
+            weights=weights,
+            obs=obs,
+            obs_time=obs_time,
+            obs_pos=obs_pos,
+            unit_vectors=unit_vectors,
+            indicies=counts,
+            binned=True,
+            pixels=unique_pixels,
+            nside=nside,
+            return_comps=return_comps,
+        )
+
+    def get_binned_emission_pix(
+        self,
+        freq: FrequencyOrWavelength,
+        pixels: Pixels,
+        nside: int,
+        obs_time: Time,
+        obs: str = "earth",
+        obs_pos: u.Quantity[u.AU] | None = None,
+        weights: Sequence[float] | npt.NDArray[np.floating] | None = None,
+        return_comps: bool = False,
+        coord_in: Literal["E", "G", "C"] = "E",
+    ) -> u.Quantity[u.MJy / u.sr]:
+        """Return the simulated binned zodiacal Emission given pixel numbers.
+
+        The pixel numbers represent the pixel indicies on a HEALPix grid with resolution
+        given by `nside`. The emission is binned to a HEALPix map with resolution given by
+        `nside`.
+
+        Args:
+            freq: Delta frequency/wavelength or a sequence of frequencies corresponding to
+                a bandpass over which to evaluate the zodiacal emission. The frequencies
+                must be strictly increasing.
+            pixels: HEALPix pixel indicies representing points on the celestial sphere.
+            nside: HEALPix resolution parameter of the pixels and the binned map.
+            obs_time: Time of observation.
+            obs: Name of the Solar System observer. A list of all support observers (for a
+                given ephemeridis) is specified in `supported_observers` attribute of the
+                `Zodipy` instance. Defaults to 'earth'.
+            obs_pos: The heliocentric ecliptic cartesian position of the observer in AU.
+                Overrides the `obs` argument. Default is None.
+            weights: Bandpass weights corresponding the the frequencies in `freq`. The weights
+                are assumed to be given in spectral radiance units (Jy/sr).
+            return_comps: If True, the emission is returned component-wise. Defaults to False.
+            coord_in: Coordinate frame of the input pointing. Assumes 'E' (ecliptic
+                coordinates) by default.
+
+        Returns:
+            emission: Simulated zodiacal emission in units of 'MJy/sr'.
+
+        """
+        pixels = get_validated_pix(pixels=pixels, nside=nside)
+
+        unique_pixels, counts = np.unique(pixels, return_counts=True)
+        unit_vectors = get_unit_vectors_from_pixels(
+            coord_in=coord_in,
+            pixels=unique_pixels,
+            nside=nside,
+        )
+
+        return self._compute_emission(
+            freq=freq,
+            weights=weights,
+            obs=obs,
+            obs_time=obs_time,
+            obs_pos=obs_pos,
+            unit_vectors=unit_vectors,
+            indicies=counts,
+            binned=True,
+            pixels=unique_pixels,
+            nside=nside,
+            return_comps=return_comps,
+        )
+
+    def _compute_emission(
+        self,
+        freq: FrequencyOrWavelength,
+        weights: Sequence[float] | npt.NDArray[np.floating] | None,
+        obs: str,
+        obs_time: Time,
+        unit_vectors: npt.NDArray[np.float64],
+        indicies: npt.NDArray[np.int64],
+        binned: bool = False,
+        obs_pos: u.Quantity[u.AU] | None = None,
+        pixels: npt.NDArray[np.int64] | None = None,
+        nside: int | None = None,
+        return_comps: bool = False,
+    ) -> u.Quantity[u.MJy / u.sr]:
+        """Compute the component-wise zodiacal emission."""
+        bandpass = validate_and_get_bandpass(
+            freq=freq,
+            weights=weights,
+            model=self._ipd_model,
+            extrapolate=self.extrapolate,
+        )
+
+        # Get model parameters, some of which have been interpolated to the given
+        # frequency or bandpass.
+        source_parameters = SOURCE_PARAMS_MAPPING[type(self._ipd_model)](
+            bandpass, self._ipd_model, self._interpolator
+        )
+
+        observer_position, earth_position = get_obs_and_earth_positions(
+            obs=obs, obs_time=obs_time, obs_pos=obs_pos
+        )
+
+        # Get the integration limits for each zodiacal component (which may be
+        # different or the same depending on the model) along all line of sights.
+        start, stop = get_line_of_sight_start_and_stop_distances(
+            components=self._ipd_model.comps.keys(),
+            unit_vectors=unit_vectors,
+            obs_pos=observer_position,
+        )
+
+        density_partials = construct_density_partials_comps(
+            comps=self._ipd_model.comps,
+            dynamic_params={"X_earth": earth_position},
+        )
+
+        # Make table of pre-computed bandpass integrated blackbody emission.
+        bandpass_interpolatation_table = get_bandpass_interpolation_table(bandpass)
+
+        common_integrand = partial(
+            EMISSION_MAPPING[type(self._ipd_model)],
+            X_obs=observer_position,
+            bp_interpolation_table=bandpass_interpolatation_table,
+            **source_parameters["common"],
+        )
+
+        if self.n_proc > 1:
+            unit_vector_chunks = np.array_split(unit_vectors, self.n_proc, axis=-1)
+            integrated_comp_emission = np.zeros((len(self._ipd_model.comps), unit_vectors.shape[1]))
+            with multiprocessing.get_context(SYS_PROC_START_METHOD).Pool(
+                processes=self.n_proc
+            ) as pool:
+                for idx, comp_label in enumerate(self._ipd_model.comps.keys()):
+                    stop_chunks = np.array_split(stop[comp_label], self.n_proc, axis=-1)
+                    if start[comp_label].size == 1:
+                        start_chunks = [start[comp_label]] * self.n_proc
+                    else:
+                        start_chunks = np.array_split(start[comp_label], self.n_proc, axis=-1)
+                    comp_integrands = [
+                        partial(
+                            common_integrand,
+                            u_los=np.expand_dims(unit_vectors, axis=-1),
+                            start=np.expand_dims(start, axis=-1),
+                            stop=np.expand_dims(stop, axis=-1),
+                            get_density_function=density_partials[comp_label],
+                            **source_parameters[comp_label],
+                        )
+                        for unit_vectors, start, stop in zip(
+                            unit_vector_chunks, start_chunks, stop_chunks
+                        )
+                    ]
+
+                    proc_chunks = [
+                        pool.apply_async(
+                            _integrate_gauss_quad,
+                            args=(comp_integrand, *self._gauss_points_and_weights),
+                        )
+                        for comp_integrand in comp_integrands
+                    ]
+
+                    integrated_comp_emission[idx] += (
+                        np.concatenate([result.get() for result in proc_chunks])
+                        * 0.5
+                        * (stop[comp_label] - start[comp_label])
+                    )
+
+        else:
+            integrated_comp_emission = np.zeros((len(self._ipd_model.comps), unit_vectors.shape[1]))
+            unit_vectors_expanded = np.expand_dims(unit_vectors, axis=-1)
+
+            for idx, comp_label in enumerate(self._ipd_model.comps.keys()):
+                comp_integrand = partial(
+                    common_integrand,
+                    u_los=unit_vectors_expanded,
+                    start=np.expand_dims(start[comp_label], axis=-1),
+                    stop=np.expand_dims(stop[comp_label], axis=-1),
+                    get_density_function=density_partials[comp_label],
+                    **source_parameters[comp_label],
+                )
+
+                integrated_comp_emission[idx] = (
+                    _integrate_gauss_quad(comp_integrand, *self._gauss_points_and_weights)
+                    * 0.5
+                    * (stop[comp_label] - start[comp_label])
+                )
+
+        emission = np.zeros(
+            (
+                len(self._ipd_model.comps),
+                hp.nside2npix(nside) if binned else indicies.size,
+            )
+        )
+        if binned:
+            emission[:, pixels] = integrated_comp_emission
+        else:
+            emission = integrated_comp_emission[:, indicies]
+
+        if self.solar_cut is not None:
+            ang_dist = hp.rotator.angdist(-observer_position.flatten(), unit_vectors)
+            solar_mask = ang_dist < self.solar_cut.value
+            if binned and pixels is not None:
+                emission[:, pixels[solar_mask]] = self.solar_cut_fill_value
+            else:
+                emission[:, solar_mask[indicies]] = self.solar_cut_fill_value
+
+        emission = (emission << SPECIFIC_INTENSITY_UNITS).to(u.MJy / u.sr)
+
+        return emission if return_comps else emission.sum(axis=0)
+
+    def __repr__(self) -> str:
+        repr_str = f"{self.__class__.__name__}("
+        for attribute_name, attribute in self.__dict__.items():
+            if attribute_name.startswith("_"):
+                continue
+            repr_str += f"{attribute_name}={attribute!r}, "
+
+        return repr_str[:-2] + ")"
+
+
+ + + +
+ + + + + + + +
+ + + +

+ supported_observers: list[str] + + + property + + +

+ + +
+ +

Return a list of available observers given an ephemeris.

+
+ +
+ + + + +
+ + + +

+ get_binned_emission_ang(freq, theta, phi, nside, obs_time, obs='earth', obs_pos=None, weights=None, lonlat=False, return_comps=False, coord_in='E') + +

+ + +
+ +

Return the simulated binned zodiacal emission given angles on the sky.

+

The pointing, for which to compute the emission, is specified in form of angles on +the sky given by theta and phi. The emission is binned to a HEALPix map with +resolution given by nside.

+ + + +

Parameters:

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescriptionDefault
freq + FrequencyOrWavelength + +
+

Delta frequency/wavelength or a sequence of frequencies corresponding to +a bandpass over which to evaluate the zodiacal emission. The frequencies +must be strictly increasing.

+
+
+ required +
theta + SkyAngles + +
+

Angular co-latitude coordinate of a point, or a sequence of points, on +the celestial sphere. Must be in the range [0, π] rad. Units must be either +radians or degrees.

+
+
+ required +
phi + SkyAngles + +
+

Angular longitude coordinate of a point, or a sequence of points, on the +celestial sphere. Must be in the range [0, 2π] rad. Units must be either +radians or degrees.

+
+
+ required +
nside + int + +
+

HEALPix resolution parameter of the binned map.

+
+
+ required +
obs_time + Time + +
+

Time of observation.

+
+
+ required +
obs + str + +
+

Name of the Solar System observer. A list of all support observers (for a +given ephemeridis) is specified in supported_observers attribute of the +Zodipy instance. Defaults to 'earth'.

+
+
+ 'earth' +
obs_pos + Quantity[AU] | None + +
+

The heliocentric ecliptic cartesian position of the observer in AU. +Overrides the obs argument. Default is None.

+
+
+ None +
weights + Sequence[float] | NDArray[floating] | None + +
+

Bandpass weights corresponding the the frequencies in freq. The weights +are assumed to be given in spectral radiance units (Jy/sr).

+
+
+ None +
lonlat + bool + +
+

If True, input angles theta, phi are assumed to be longitude and +latitude, otherwise, they are co-latitude and longitude.

+
+
+ False +
return_comps + bool + +
+

If True, the emission is returned component-wise. Defaults to False.

+
+
+ False +
coord_in + Literal['E', 'G', 'C'] + +
+

Coordinate frame of the input pointing. Assumes 'E' (ecliptic +coordinates) by default.

+
+
+ 'E' +
+ + + +

Returns:

+ + + + + + + + + + + + + +
Name TypeDescription
emission + Quantity[MJy / sr] + +
+

Simulated zodiacal emission in units of 'MJy/sr'.

+
+
+ +
+ Source code in zodipy/zodipy.py +
257
+258
+259
+260
+261
+262
+263
+264
+265
+266
+267
+268
+269
+270
+271
+272
+273
+274
+275
+276
+277
+278
+279
+280
+281
+282
+283
+284
+285
+286
+287
+288
+289
+290
+291
+292
+293
+294
+295
+296
+297
+298
+299
+300
+301
+302
+303
+304
+305
+306
+307
+308
+309
+310
+311
+312
+313
+314
+315
+316
+317
+318
+319
+320
+321
+322
+323
+324
+325
+326
+327
+328
+329
def get_binned_emission_ang(
+    self,
+    freq: FrequencyOrWavelength,
+    theta: SkyAngles,
+    phi: SkyAngles,
+    nside: int,
+    obs_time: Time,
+    obs: str = "earth",
+    obs_pos: u.Quantity[u.AU] | None = None,
+    weights: Sequence[float] | npt.NDArray[np.floating] | None = None,
+    lonlat: bool = False,
+    return_comps: bool = False,
+    coord_in: Literal["E", "G", "C"] = "E",
+) -> u.Quantity[u.MJy / u.sr]:
+    """Return the simulated binned zodiacal emission given angles on the sky.
+
+    The pointing, for which to compute the emission, is specified in form of angles on
+    the sky given by `theta` and `phi`. The emission is binned to a HEALPix map with
+    resolution given by `nside`.
+
+    Args:
+        freq: Delta frequency/wavelength or a sequence of frequencies corresponding to
+            a bandpass over which to evaluate the zodiacal emission. The frequencies
+            must be strictly increasing.
+        theta: Angular co-latitude coordinate of a point, or a sequence of points, on
+            the celestial sphere. Must be in the range [0, π] rad. Units must be either
+            radians or degrees.
+        phi: Angular longitude coordinate of a point, or a sequence of points, on the
+            celestial sphere. Must be in the range [0, 2π] rad. Units must be either
+            radians or degrees.
+        nside: HEALPix resolution parameter of the binned map.
+        obs_time: Time of observation.
+        obs: Name of the Solar System observer. A list of all support observers (for a
+            given ephemeridis) is specified in `supported_observers` attribute of the
+            `Zodipy` instance. Defaults to 'earth'.
+        obs_pos: The heliocentric ecliptic cartesian position of the observer in AU.
+            Overrides the `obs` argument. Default is None.
+        weights: Bandpass weights corresponding the the frequencies in `freq`. The weights
+            are assumed to be given in spectral radiance units (Jy/sr).
+        lonlat: If True, input angles `theta`, `phi` are assumed to be longitude and
+            latitude, otherwise, they are co-latitude and longitude.
+        return_comps: If True, the emission is returned component-wise. Defaults to False.
+        coord_in: Coordinate frame of the input pointing. Assumes 'E' (ecliptic
+            coordinates) by default.
+
+    Returns:
+        emission: Simulated zodiacal emission in units of 'MJy/sr'.
+
+    """
+    theta, phi = get_validated_ang(theta=theta, phi=phi, lonlat=lonlat)
+
+    unique_angles, counts = np.unique(np.asarray([theta, phi]), return_counts=True, axis=1)
+    unique_pixels = hp.ang2pix(nside, *unique_angles, lonlat=lonlat)
+    unit_vectors = get_unit_vectors_from_ang(
+        coord_in=coord_in,
+        theta=unique_angles[0],
+        phi=unique_angles[1],
+        lonlat=lonlat,
+    )
+
+    return self._compute_emission(
+        freq=freq,
+        weights=weights,
+        obs=obs,
+        obs_time=obs_time,
+        obs_pos=obs_pos,
+        unit_vectors=unit_vectors,
+        indicies=counts,
+        binned=True,
+        pixels=unique_pixels,
+        nside=nside,
+        return_comps=return_comps,
+    )
+
+
+
+ +
+ + +
+ + + +

+ get_binned_emission_pix(freq, pixels, nside, obs_time, obs='earth', obs_pos=None, weights=None, return_comps=False, coord_in='E') + +

+ + +
+ +

Return the simulated binned zodiacal Emission given pixel numbers.

+

The pixel numbers represent the pixel indicies on a HEALPix grid with resolution +given by nside. The emission is binned to a HEALPix map with resolution given by +nside.

+ + + +

Parameters:

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescriptionDefault
freq + FrequencyOrWavelength + +
+

Delta frequency/wavelength or a sequence of frequencies corresponding to +a bandpass over which to evaluate the zodiacal emission. The frequencies +must be strictly increasing.

+
+
+ required +
pixels + Pixels + +
+

HEALPix pixel indicies representing points on the celestial sphere.

+
+
+ required +
nside + int + +
+

HEALPix resolution parameter of the pixels and the binned map.

+
+
+ required +
obs_time + Time + +
+

Time of observation.

+
+
+ required +
obs + str + +
+

Name of the Solar System observer. A list of all support observers (for a +given ephemeridis) is specified in supported_observers attribute of the +Zodipy instance. Defaults to 'earth'.

+
+
+ 'earth' +
obs_pos + Quantity[AU] | None + +
+

The heliocentric ecliptic cartesian position of the observer in AU. +Overrides the obs argument. Default is None.

+
+
+ None +
weights + Sequence[float] | NDArray[floating] | None + +
+

Bandpass weights corresponding the the frequencies in freq. The weights +are assumed to be given in spectral radiance units (Jy/sr).

+
+
+ None +
return_comps + bool + +
+

If True, the emission is returned component-wise. Defaults to False.

+
+
+ False +
coord_in + Literal['E', 'G', 'C'] + +
+

Coordinate frame of the input pointing. Assumes 'E' (ecliptic +coordinates) by default.

+
+
+ 'E' +
+ + + +

Returns:

+ + + + + + + + + + + + + +
Name TypeDescription
emission + Quantity[MJy / sr] + +
+

Simulated zodiacal emission in units of 'MJy/sr'.

+
+
+ +
+ Source code in zodipy/zodipy.py +
331
+332
+333
+334
+335
+336
+337
+338
+339
+340
+341
+342
+343
+344
+345
+346
+347
+348
+349
+350
+351
+352
+353
+354
+355
+356
+357
+358
+359
+360
+361
+362
+363
+364
+365
+366
+367
+368
+369
+370
+371
+372
+373
+374
+375
+376
+377
+378
+379
+380
+381
+382
+383
+384
+385
+386
+387
+388
+389
+390
+391
+392
def get_binned_emission_pix(
+    self,
+    freq: FrequencyOrWavelength,
+    pixels: Pixels,
+    nside: int,
+    obs_time: Time,
+    obs: str = "earth",
+    obs_pos: u.Quantity[u.AU] | None = None,
+    weights: Sequence[float] | npt.NDArray[np.floating] | None = None,
+    return_comps: bool = False,
+    coord_in: Literal["E", "G", "C"] = "E",
+) -> u.Quantity[u.MJy / u.sr]:
+    """Return the simulated binned zodiacal Emission given pixel numbers.
+
+    The pixel numbers represent the pixel indicies on a HEALPix grid with resolution
+    given by `nside`. The emission is binned to a HEALPix map with resolution given by
+    `nside`.
+
+    Args:
+        freq: Delta frequency/wavelength or a sequence of frequencies corresponding to
+            a bandpass over which to evaluate the zodiacal emission. The frequencies
+            must be strictly increasing.
+        pixels: HEALPix pixel indicies representing points on the celestial sphere.
+        nside: HEALPix resolution parameter of the pixels and the binned map.
+        obs_time: Time of observation.
+        obs: Name of the Solar System observer. A list of all support observers (for a
+            given ephemeridis) is specified in `supported_observers` attribute of the
+            `Zodipy` instance. Defaults to 'earth'.
+        obs_pos: The heliocentric ecliptic cartesian position of the observer in AU.
+            Overrides the `obs` argument. Default is None.
+        weights: Bandpass weights corresponding the the frequencies in `freq`. The weights
+            are assumed to be given in spectral radiance units (Jy/sr).
+        return_comps: If True, the emission is returned component-wise. Defaults to False.
+        coord_in: Coordinate frame of the input pointing. Assumes 'E' (ecliptic
+            coordinates) by default.
+
+    Returns:
+        emission: Simulated zodiacal emission in units of 'MJy/sr'.
+
+    """
+    pixels = get_validated_pix(pixels=pixels, nside=nside)
+
+    unique_pixels, counts = np.unique(pixels, return_counts=True)
+    unit_vectors = get_unit_vectors_from_pixels(
+        coord_in=coord_in,
+        pixels=unique_pixels,
+        nside=nside,
+    )
+
+    return self._compute_emission(
+        freq=freq,
+        weights=weights,
+        obs=obs,
+        obs_time=obs_time,
+        obs_pos=obs_pos,
+        unit_vectors=unit_vectors,
+        indicies=counts,
+        binned=True,
+        pixels=unique_pixels,
+        nside=nside,
+        return_comps=return_comps,
+    )
+
+
+
+ +
+ + +
+ + + +

+ get_emission_ang(freq, theta, phi, obs_time, obs='earth', obs_pos=None, weights=None, lonlat=False, return_comps=False, coord_in='E') + +

+ + +
+ +

Return the simulated zodiacal emission given angles on the sky.

+

The pointing, for which to compute the emission, is specified in form of angles on +the sky given by theta and phi.

+ + + +

Parameters:

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescriptionDefault
freq + FrequencyOrWavelength + +
+

Delta frequency/wavelength or a sequence of frequencies corresponding to +a bandpass over which to evaluate the zodiacal emission. The frequencies +must be strictly increasing.

+
+
+ required +
theta + SkyAngles + +
+

Angular co-latitude coordinate of a point, or a sequence of points, on +the celestial sphere. Must be in the range [0, π] rad. Units must be either +radians or degrees.

+
+
+ required +
phi + SkyAngles + +
+

Angular longitude coordinate of a point, or a sequence of points, on the +celestial sphere. Must be in the range [0, 2π] rad. Units must be either +radians or degrees.

+
+
+ required +
obs_time + Time + +
+

Time of observation.

+
+
+ required +
obs + str + +
+

Name of the Solar System observer. A list of all support observers (for a +given ephemeridis) is specified in supported_observers attribute of the +Zodipy instance. Defaults to 'earth'.

+
+
+ 'earth' +
obs_pos + Quantity[AU] | None + +
+

The heliocentric ecliptic cartesian position of the observer in AU. +Overrides the obs argument. Default is None.

+
+
+ None +
weights + Sequence[float] | NDArray[floating] | None + +
+

Bandpass weights corresponding the the frequencies in freq. The weights +are assumed to be given in spectral radiance units (Jy/sr).

+
+
+ None +
lonlat + bool + +
+

If True, input angles (theta, phi) are assumed to be longitude and +latitude, otherwise, they are co-latitude and longitude.

+
+
+ False +
return_comps + bool + +
+

If True, the emission is returned component-wise. Defaults to False.

+
+
+ False +
coord_in + Literal['E', 'G', 'C'] + +
+

Coordinate frame of the input pointing. Assumes 'E' (ecliptic +coordinates) by default.

+
+
+ 'E' +
+ + + +

Returns:

+ + + + + + + + + + + + + +
Name TypeDescription
emission + Quantity[MJy / sr] + +
+

Simulated zodiacal emission in units of 'MJy/sr'.

+
+
+ +
+ Source code in zodipy/zodipy.py +
129
+130
+131
+132
+133
+134
+135
+136
+137
+138
+139
+140
+141
+142
+143
+144
+145
+146
+147
+148
+149
+150
+151
+152
+153
+154
+155
+156
+157
+158
+159
+160
+161
+162
+163
+164
+165
+166
+167
+168
+169
+170
+171
+172
+173
+174
+175
+176
+177
+178
+179
+180
+181
+182
+183
+184
+185
+186
+187
+188
+189
+190
+191
+192
+193
+194
def get_emission_ang(
+    self,
+    freq: FrequencyOrWavelength,
+    theta: SkyAngles,
+    phi: SkyAngles,
+    obs_time: Time,
+    obs: str = "earth",
+    obs_pos: u.Quantity[u.AU] | None = None,
+    weights: Sequence[float] | npt.NDArray[np.floating] | None = None,
+    lonlat: bool = False,
+    return_comps: bool = False,
+    coord_in: Literal["E", "G", "C"] = "E",
+) -> u.Quantity[u.MJy / u.sr]:
+    """Return the simulated zodiacal emission given angles on the sky.
+
+    The pointing, for which to compute the emission, is specified in form of angles on
+    the sky given by `theta` and `phi`.
+
+    Args:
+        freq: Delta frequency/wavelength or a sequence of frequencies corresponding to
+            a bandpass over which to evaluate the zodiacal emission. The frequencies
+            must be strictly increasing.
+        theta: Angular co-latitude coordinate of a point, or a sequence of points, on
+            the celestial sphere. Must be in the range [0, π] rad. Units must be either
+            radians or degrees.
+        phi: Angular longitude coordinate of a point, or a sequence of points, on the
+            celestial sphere. Must be in the range [0, 2π] rad. Units must be either
+            radians or degrees.
+        obs_time: Time of observation.
+        obs: Name of the Solar System observer. A list of all support observers (for a
+            given ephemeridis) is specified in `supported_observers` attribute of the
+            `Zodipy` instance. Defaults to 'earth'.
+        obs_pos: The heliocentric ecliptic cartesian position of the observer in AU.
+            Overrides the `obs` argument. Default is None.
+        weights: Bandpass weights corresponding the the frequencies in `freq`. The weights
+            are assumed to be given in spectral radiance units (Jy/sr).
+        lonlat: If True, input angles (`theta`, `phi`) are assumed to be longitude and
+            latitude, otherwise, they are co-latitude and longitude.
+        return_comps: If True, the emission is returned component-wise. Defaults to False.
+        coord_in: Coordinate frame of the input pointing. Assumes 'E' (ecliptic
+            coordinates) by default.
+
+    Returns:
+        emission: Simulated zodiacal emission in units of 'MJy/sr'.
+
+    """
+    theta, phi = get_validated_ang(theta=theta, phi=phi, lonlat=lonlat)
+
+    unique_angles, indicies = np.unique(np.asarray([theta, phi]), return_inverse=True, axis=1)
+    unit_vectors = get_unit_vectors_from_ang(
+        coord_in=coord_in,
+        theta=unique_angles[0],
+        phi=unique_angles[1],
+        lonlat=lonlat,
+    )
+
+    return self._compute_emission(
+        freq=freq,
+        weights=weights,
+        obs=obs,
+        obs_time=obs_time,
+        obs_pos=obs_pos,
+        unit_vectors=unit_vectors,
+        indicies=indicies,
+        return_comps=return_comps,
+    )
+
+
+
+ +
+ + +
+ + + +

+ get_emission_pix(freq, pixels, nside, obs_time, obs='earth', obs_pos=None, weights=None, return_comps=False, coord_in='E') + +

+ + +
+ +

Return the simulated zodiacal emission given pixel numbers.

+

The pixel numbers represent the pixel indicies on a HEALPix grid with resolution +given by nside.

+ + + +

Parameters:

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescriptionDefault
freq + FrequencyOrWavelength + +
+

Delta frequency/wavelength or a sequence of frequencies corresponding to +a bandpass over which to evaluate the zodiacal emission. The frequencies +must be strictly increasing.

+
+
+ required +
pixels + Pixels + +
+

HEALPix pixel indicies representing points on the celestial sphere.

+
+
+ required +
nside + int + +
+

HEALPix resolution parameter of the pixels and the binned map.

+
+
+ required +
obs_time + Time + +
+

Time of observation.

+
+
+ required +
obs + str + +
+

Name of the Solar System observer. A list of all support observers (for a +given ephemeridis) is specified in supported_observers attribute of the +Zodipy instance. Defaults to 'earth'.

+
+
+ 'earth' +
obs_pos + Quantity[AU] | None + +
+

The heliocentric ecliptic cartesian position of the observer in AU. +Overrides the obs argument. Default is None.

+
+
+ None +
weights + Sequence[float] | NDArray[floating] | None + +
+

Bandpass weights corresponding the the frequencies in freq. The weights +are assumed to be given in spectral radiance units (Jy/sr).

+
+
+ None +
return_comps + bool + +
+

If True, the emission is returned component-wise. Defaults to False.

+
+
+ False +
coord_in + Literal['E', 'G', 'C'] + +
+

Coordinate frame of the input pointing. Assumes 'E' (ecliptic +coordinates) by default.

+
+
+ 'E' +
+ + + +

Returns:

+ + + + + + + + + + + + + +
Name TypeDescription
emission + Quantity[MJy / sr] + +
+

Simulated zodiacal emission in units of 'MJy/sr'.

+
+
+ +
+ Source code in zodipy/zodipy.py +
196
+197
+198
+199
+200
+201
+202
+203
+204
+205
+206
+207
+208
+209
+210
+211
+212
+213
+214
+215
+216
+217
+218
+219
+220
+221
+222
+223
+224
+225
+226
+227
+228
+229
+230
+231
+232
+233
+234
+235
+236
+237
+238
+239
+240
+241
+242
+243
+244
+245
+246
+247
+248
+249
+250
+251
+252
+253
+254
+255
def get_emission_pix(
+    self,
+    freq: FrequencyOrWavelength,
+    pixels: Pixels,
+    nside: int,
+    obs_time: Time,
+    obs: str = "earth",
+    obs_pos: u.Quantity[u.AU] | None = None,
+    weights: Sequence[float] | npt.NDArray[np.floating] | None = None,
+    return_comps: bool = False,
+    coord_in: Literal["E", "G", "C"] = "E",
+) -> u.Quantity[u.MJy / u.sr]:
+    """Return the simulated zodiacal emission given pixel numbers.
+
+    The pixel numbers represent the pixel indicies on a HEALPix grid with resolution
+    given by `nside`.
+
+    Args:
+        freq: Delta frequency/wavelength or a sequence of frequencies corresponding to
+            a bandpass over which to evaluate the zodiacal emission. The frequencies
+            must be strictly increasing.
+        pixels: HEALPix pixel indicies representing points on the celestial sphere.
+        nside: HEALPix resolution parameter of the pixels and the binned map.
+        obs_time: Time of observation.
+        obs: Name of the Solar System observer. A list of all support observers (for a
+            given ephemeridis) is specified in `supported_observers` attribute of the
+            `Zodipy` instance. Defaults to 'earth'.
+        obs_pos: The heliocentric ecliptic cartesian position of the observer in AU.
+            Overrides the `obs` argument. Default is None.
+        weights: Bandpass weights corresponding the the frequencies in `freq`. The weights
+            are assumed to be given in spectral radiance units (Jy/sr).
+        return_comps: If True, the emission is returned component-wise. Defaults to False.
+        coord_in: Coordinate frame of the input pointing. Assumes 'E' (ecliptic
+            coordinates) by default.
+
+    Returns:
+        emission: Simulated zodiacal emission in units of 'MJy/sr'.
+
+    """
+    pixels = get_validated_pix(pixels=pixels, nside=nside)
+
+    unique_pixels, indicies = np.unique(pixels, return_inverse=True)
+    unit_vectors = get_unit_vectors_from_pixels(
+        coord_in=coord_in,
+        pixels=unique_pixels,
+        nside=nside,
+    )
+
+    return self._compute_emission(
+        freq=freq,
+        weights=weights,
+        obs=obs,
+        obs_time=obs_time,
+        obs_pos=obs_pos,
+        unit_vectors=unit_vectors,
+        indicies=indicies,
+        pixels=unique_pixels,
+        nside=nside,
+        return_comps=return_comps,
+    )
+
+
+
+ +
+ + +
+ + + +

+ get_parameters() + +

+ + +
+ +

Return a dictionary containing the interplanetary dust model parameters.

+ +
+ Source code in zodipy/zodipy.py +
103
+104
+105
def get_parameters(self) -> ParameterDict:
+    """Return a dictionary containing the interplanetary dust model parameters."""
+    return self._ipd_model.to_dict()
+
+
+
+ +
+ + +
+ + + +

+ update_parameters(parameters) + +

+ + +
+ +

Update the interplanetary dust model parameters.

+ + + +

Parameters:

+ + + + + + + + + + + + + + + + + +
NameTypeDescriptionDefault
parameters + ParameterDict + +
+

Dictionary of parameters to update. The keys must be the names +of the parameters as defined in the model. To get the parameters dict +of an existing model, use Zodipy("dirbe").get_parameters().

+
+
+ required +
+ +
+ Source code in zodipy/zodipy.py +
107
+108
+109
+110
+111
+112
+113
+114
+115
+116
+117
+118
+119
+120
+121
+122
+123
+124
+125
+126
+127
def update_parameters(self, parameters: ParameterDict) -> None:
+    """Update the interplanetary dust model parameters.
+
+    Args:
+        parameters: Dictionary of parameters to update. The keys must be the names
+            of the parameters as defined in the model. To get the parameters dict
+            of an existing model, use `Zodipy("dirbe").get_parameters()`.
+
+    """
+    _dict = parameters.copy()
+    _dict["comps"] = {}
+    for key, value in parameters.items():
+        if key == "comps":
+            for comp_key, comp_value in value.items():
+                _dict["comps"][ComponentLabel(comp_key)] = type(
+                    self._ipd_model.comps[ComponentLabel(comp_key)]
+                )(**comp_value)
+        elif isinstance(value, dict):
+            _dict[key] = {ComponentLabel(k): v for k, v in value.items()}
+
+    self._ipd_model = self._ipd_model.__class__(**_dict)
+
+
+
+ +
+ + + +
+ +
+ + +
+ + + + +
+ +
+ +
+ + + + + + +
+
+ + +
+ +
+ + + +
+
+
+
+ + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/search/search_index.json b/search/search_index.json new file mode 100644 index 0000000..16495e6 --- /dev/null +++ b/search/search_index.json @@ -0,0 +1 @@ +{"config":{"lang":["en"],"separator":"[\\s\\-]+","pipeline":["stopWordFilter"]},"docs":[{"location":"","title":"Overview","text":"

ZodiPy is an Astropy affiliated package for simulating zodiacal light in intensity for arbitrary Solar system observers.

"},{"location":"#a-simple-example","title":"A simple example","text":"
import astropy.units as u\nfrom astropy.time import Time\n\nfrom zodipy import Zodipy\n\n\nmodel = Zodipy(\"dirbe\")\n\nemission = model.get_emission_ang(\n    25 * u.micron,\n    theta=[10, 10.1, 10.2] * u.deg,\n    phi=[90, 89, 88] * u.deg,\n    obs_time=Time(\"2022-01-01 12:00:00\"),\n    obs=\"earth\",\n    lonlat=True,\n)\n\nprint(emission)\n#> [15.53095493 15.52883577 15.53121942] MJy / sr\n

What's going on here:

  • We start by initializing the Zodipy class, which is our interface, where we specify that we want to use the DIRBE interplanetary dust model.
  • We use the get_emission_ang method which is a method to simulate emission from angular sky coordinates (see the reference for other available simulation methods).
  • The first argument to the get_emission_ang method, 25 * u.micron, specifies the wavelength of the simulated observation. Note that we use Astropy units for many of the input arguments.
  • theta and phi represent the pointing of the observation (co-latitude and longitude, following the healpy convention). In this example we observe three sky coordinates.
  • obs_time represents the time of observation, which we need to compute the position of the observer and all other required solar system bodies.
  • obs represents the observer, and must be an solar system observer supported by the Astropy ephemeris used internally. If we wish to be more specific about the observer position, we can use the obs_pos keyword instead of obs, which takes in a heliocentric cartesian position in units of AU.
  • Finally, lonlat is a boolean which converts the convention of theta and phi from co-latitude and longitude to longitude and latitude.

For more information on using ZodiPy, see the usage section.

"},{"location":"install/","title":"Install","text":"

Installing ZodiPy is as simple as:

pip install zodipy\n

Note

ZodiPy supports python versions >=3.9.

"},{"location":"install/#dependencies","title":"Dependencies","text":"

ZodiPy has the following dependencies (these are automatically downloaded alongside ZodiPy):

  • Astropy (>= 5.0.1)
  • NumPy
  • healpy
  • jplehem
  • SciPy
"},{"location":"introduction/","title":"Introduction","text":"

ZodiPy is an open source Python tool for simulating the zodiacal emission that a solar system observer is predicted to see given an interplanetary dust model. We attempts to make zodiacal emission simulations more accessible by providing the community with a simple interface to existing models. For other zodiacal emission tools, see Zodiacal Light Models on LAMBDA. All contributions are most welcome.

"},{"location":"introduction/#interplanetary-dust-models","title":"Interplanetary Dust Models","text":"

ZodiPy supports the following interplanetary dust models:

1.25-240 \\(\\boldsymbol{\\mu}\\)m

  • DIRBE (Kelsall et al. 1998)
  • RRM (experimental) (Rowan-Robinson and May 2013)

100-857 GHz

  • Planck 2013 (Planck Collaboration et al. 2014)
  • Planck 2015 (Planck Collaboration et al. 2016)
  • Planck 2018 (Planck Collaboration et al. 2020)
  • Odegard (Odegard et al. 2019)

Info

The Planck and Odegard models extend the DIRBE interplanetary dust model to CMB frequencies by fitting the blackbody emissivity of the dust in the respective DIRBE interplanetary dust components to Planck HFI data. The distribution of the interplanetary dust is exactly the same as in the DIRBE model.

If you see a missing model, please feel free to contact us by opening an issue on GitHub.

"},{"location":"introduction/#scientific-paper","title":"Scientific Paper","text":"

For an overview of the modeling approach used in ZodiPy and other information regarding zodiacal emission and interplanetary dust modeling we refer to the scientific paper on ZodiPy:

  • Cosmoglobe: Simulating zodiacal emission with ZodiPy
"},{"location":"reference/","title":"Reference","text":""},{"location":"reference/#zodipy.zodipy.Zodipy","title":"Zodipy","text":"

Interface for simulating zodiacal emission.

This class provides methods for simulating zodiacal emission given observer pointing either in sky angles or through HEALPix pixels.

Parameters:

Name Type Description Default model str

Name of the interplanetary dust model to use in the simulations. Defaults to DIRBE.

'dirbe' gauss_quad_degree int

Order of the Gaussian-Legendre quadrature used to evaluate the line-of-sight integral in the simulations. Default is 50 points.

50 interp_kind str

Interpolation kind used to interpolate relevant model parameters. Defaults to 'linear'. For more information on available interpolation methods, please visit the Scipy documentation.

'linear' extrapolate bool

If True all spectral quantities in the selected model are extrapolated to the requested frequencies or wavelengths. If False, an exception is raised on requested frequencies/wavelengths outside of the valid model range. Default is False.

False ephemeris str

Ephemeris used to compute the positions of the observer and the Earth. Defaults to 'de432s', which requires downloading (and caching) a ~10MB file. For more information on available ephemeridis, please visit the Astropy documentation

'de432s' solar_cut Quantity[deg]

Cutoff angle from the sun in degrees. The emission for all the pointing with angular distance between the sun smaller than solar_cutoff are masked. Defaults to None.

None solar_cut_fill_value float

Fill value for pixels masked with solar_cut. Defaults to np.nan.

nan n_proc int

Number of cores to use. If n_proc is greater than 1, the line-of-sight integrals are parallelized using the multiprocessing module. Defaults to 1.

1 Source code in zodipy/zodipy.py
class Zodipy:\n\"\"\"Interface for simulating zodiacal emission.\n\n    This class provides methods for simulating zodiacal emission given observer pointing\n    either in sky angles or through HEALPix pixels.\n\n    Args:\n        model (str): Name of the interplanetary dust model to use in the simulations.\n            Defaults to DIRBE.\n        gauss_quad_degree (int): Order of the Gaussian-Legendre quadrature used to evaluate\n            the line-of-sight integral in the simulations. Default is 50 points.\n        interp_kind (str): Interpolation kind used to interpolate relevant model parameters.\n            Defaults to 'linear'. For more information on available interpolation methods,\n            please visit the [Scipy documentation](\n            https://docs.scipy.org/doc/scipy/reference/generated/scipy.interpolate.interp1d.html).\n        extrapolate (bool): If `True` all spectral quantities in the selected model are\n            extrapolated to the requested frequencies or wavelengths. If `False`, an\n            exception is raised on requested frequencies/wavelengths outside of the\n            valid model range. Default is `False`.\n        ephemeris (str): Ephemeris used to compute the positions of the observer and the\n            Earth. Defaults to 'de432s', which requires downloading (and caching) a ~10MB\n            file. For more information on available ephemeridis, please visit the [Astropy\n            documentation](https://docs.astropy.org/en/stable/coordinates/solarsystem.html)\n        solar_cut (u.Quantity[u.deg]): Cutoff angle from the sun in degrees. The emission\n            for all the pointing with angular distance between the sun smaller than\n            `solar_cutoff` are masked. Defaults to `None`.\n        solar_cut_fill_value (float): Fill value for pixels masked with `solar_cut`.\n            Defaults to `np.nan`.\n        n_proc (int): Number of cores to use. If `n_proc` is greater than 1, the line-of-sight\n            integrals are parallelized using the `multiprocessing` module. Defaults to 1.\n\n    \"\"\"\n\n    def __init__(\n        self,\n        model: str = \"dirbe\",\n        gauss_quad_degree: int = 50,\n        extrapolate: bool = False,\n        interp_kind: str = \"linear\",\n        ephemeris: str = \"de432s\",\n        solar_cut: u.Quantity[u.deg] | None = None,\n        solar_cut_fill_value: float = np.nan,\n        n_proc: int = 1,\n    ) -> None:\n        self.model = model\n        self.gauss_quad_degree = gauss_quad_degree\n        self.extrapolate = extrapolate\n        self.interp_kind = interp_kind\n        self.ephemeris = ephemeris\n        self.solar_cut = solar_cut.to(u.rad) if solar_cut is not None else solar_cut\n        self.solar_cut_fill_value = solar_cut_fill_value\n        self.n_proc = n_proc\n\n        self._interpolator = partial(\n            interp1d,\n            kind=self.interp_kind,\n            fill_value=\"extrapolate\" if self.extrapolate else np.nan,\n        )\n        self._ipd_model = model_registry.get_model(model)\n        self._gauss_points_and_weights = np.polynomial.legendre.leggauss(gauss_quad_degree)\n\n    @property\n    def supported_observers(self) -> list[str]:\n\"\"\"Return a list of available observers given an ephemeris.\"\"\"\n        return [*list(solar_system_ephemeris.bodies), \"semb-l2\"]\n\n    def get_parameters(self) -> ParameterDict:\n\"\"\"Return a dictionary containing the interplanetary dust model parameters.\"\"\"\n        return self._ipd_model.to_dict()\n\n    def update_parameters(self, parameters: ParameterDict) -> None:\n\"\"\"Update the interplanetary dust model parameters.\n\n        Args:\n            parameters: Dictionary of parameters to update. The keys must be the names\n                of the parameters as defined in the model. To get the parameters dict\n                of an existing model, use `Zodipy(\"dirbe\").get_parameters()`.\n\n        \"\"\"\n        _dict = parameters.copy()\n        _dict[\"comps\"] = {}\n        for key, value in parameters.items():\n            if key == \"comps\":\n                for comp_key, comp_value in value.items():\n                    _dict[\"comps\"][ComponentLabel(comp_key)] = type(\n                        self._ipd_model.comps[ComponentLabel(comp_key)]\n                    )(**comp_value)\n            elif isinstance(value, dict):\n                _dict[key] = {ComponentLabel(k): v for k, v in value.items()}\n\n        self._ipd_model = self._ipd_model.__class__(**_dict)\n\n    def get_emission_ang(\n        self,\n        freq: FrequencyOrWavelength,\n        theta: SkyAngles,\n        phi: SkyAngles,\n        obs_time: Time,\n        obs: str = \"earth\",\n        obs_pos: u.Quantity[u.AU] | None = None,\n        weights: Sequence[float] | npt.NDArray[np.floating] | None = None,\n        lonlat: bool = False,\n        return_comps: bool = False,\n        coord_in: Literal[\"E\", \"G\", \"C\"] = \"E\",\n    ) -> u.Quantity[u.MJy / u.sr]:\n\"\"\"Return the simulated zodiacal emission given angles on the sky.\n\n        The pointing, for which to compute the emission, is specified in form of angles on\n        the sky given by `theta` and `phi`.\n\n        Args:\n            freq: Delta frequency/wavelength or a sequence of frequencies corresponding to\n                a bandpass over which to evaluate the zodiacal emission. The frequencies\n                must be strictly increasing.\n            theta: Angular co-latitude coordinate of a point, or a sequence of points, on\n                the celestial sphere. Must be in the range [0, \u03c0] rad. Units must be either\n                radians or degrees.\n            phi: Angular longitude coordinate of a point, or a sequence of points, on the\n                celestial sphere. Must be in the range [0, 2\u03c0] rad. Units must be either\n                radians or degrees.\n            obs_time: Time of observation.\n            obs: Name of the Solar System observer. A list of all support observers (for a\n                given ephemeridis) is specified in `supported_observers` attribute of the\n                `Zodipy` instance. Defaults to 'earth'.\n            obs_pos: The heliocentric ecliptic cartesian position of the observer in AU.\n                Overrides the `obs` argument. Default is None.\n            weights: Bandpass weights corresponding the the frequencies in `freq`. The weights\n                are assumed to be given in spectral radiance units (Jy/sr).\n            lonlat: If True, input angles (`theta`, `phi`) are assumed to be longitude and\n                latitude, otherwise, they are co-latitude and longitude.\n            return_comps: If True, the emission is returned component-wise. Defaults to False.\n            coord_in: Coordinate frame of the input pointing. Assumes 'E' (ecliptic\n                coordinates) by default.\n\n        Returns:\n            emission: Simulated zodiacal emission in units of 'MJy/sr'.\n\n        \"\"\"\n        theta, phi = get_validated_ang(theta=theta, phi=phi, lonlat=lonlat)\n\n        unique_angles, indicies = np.unique(np.asarray([theta, phi]), return_inverse=True, axis=1)\n        unit_vectors = get_unit_vectors_from_ang(\n            coord_in=coord_in,\n            theta=unique_angles[0],\n            phi=unique_angles[1],\n            lonlat=lonlat,\n        )\n\n        return self._compute_emission(\n            freq=freq,\n            weights=weights,\n            obs=obs,\n            obs_time=obs_time,\n            obs_pos=obs_pos,\n            unit_vectors=unit_vectors,\n            indicies=indicies,\n            return_comps=return_comps,\n        )\n\n    def get_emission_pix(\n        self,\n        freq: FrequencyOrWavelength,\n        pixels: Pixels,\n        nside: int,\n        obs_time: Time,\n        obs: str = \"earth\",\n        obs_pos: u.Quantity[u.AU] | None = None,\n        weights: Sequence[float] | npt.NDArray[np.floating] | None = None,\n        return_comps: bool = False,\n        coord_in: Literal[\"E\", \"G\", \"C\"] = \"E\",\n    ) -> u.Quantity[u.MJy / u.sr]:\n\"\"\"Return the simulated zodiacal emission given pixel numbers.\n\n        The pixel numbers represent the pixel indicies on a HEALPix grid with resolution\n        given by `nside`.\n\n        Args:\n            freq: Delta frequency/wavelength or a sequence of frequencies corresponding to\n                a bandpass over which to evaluate the zodiacal emission. The frequencies\n                must be strictly increasing.\n            pixels: HEALPix pixel indicies representing points on the celestial sphere.\n            nside: HEALPix resolution parameter of the pixels and the binned map.\n            obs_time: Time of observation.\n            obs: Name of the Solar System observer. A list of all support observers (for a\n                given ephemeridis) is specified in `supported_observers` attribute of the\n                `Zodipy` instance. Defaults to 'earth'.\n            obs_pos: The heliocentric ecliptic cartesian position of the observer in AU.\n                Overrides the `obs` argument. Default is None.\n            weights: Bandpass weights corresponding the the frequencies in `freq`. The weights\n                are assumed to be given in spectral radiance units (Jy/sr).\n            return_comps: If True, the emission is returned component-wise. Defaults to False.\n            coord_in: Coordinate frame of the input pointing. Assumes 'E' (ecliptic\n                coordinates) by default.\n\n        Returns:\n            emission: Simulated zodiacal emission in units of 'MJy/sr'.\n\n        \"\"\"\n        pixels = get_validated_pix(pixels=pixels, nside=nside)\n\n        unique_pixels, indicies = np.unique(pixels, return_inverse=True)\n        unit_vectors = get_unit_vectors_from_pixels(\n            coord_in=coord_in,\n            pixels=unique_pixels,\n            nside=nside,\n        )\n\n        return self._compute_emission(\n            freq=freq,\n            weights=weights,\n            obs=obs,\n            obs_time=obs_time,\n            obs_pos=obs_pos,\n            unit_vectors=unit_vectors,\n            indicies=indicies,\n            pixels=unique_pixels,\n            nside=nside,\n            return_comps=return_comps,\n        )\n\n    def get_binned_emission_ang(\n        self,\n        freq: FrequencyOrWavelength,\n        theta: SkyAngles,\n        phi: SkyAngles,\n        nside: int,\n        obs_time: Time,\n        obs: str = \"earth\",\n        obs_pos: u.Quantity[u.AU] | None = None,\n        weights: Sequence[float] | npt.NDArray[np.floating] | None = None,\n        lonlat: bool = False,\n        return_comps: bool = False,\n        coord_in: Literal[\"E\", \"G\", \"C\"] = \"E\",\n    ) -> u.Quantity[u.MJy / u.sr]:\n\"\"\"Return the simulated binned zodiacal emission given angles on the sky.\n\n        The pointing, for which to compute the emission, is specified in form of angles on\n        the sky given by `theta` and `phi`. The emission is binned to a HEALPix map with\n        resolution given by `nside`.\n\n        Args:\n            freq: Delta frequency/wavelength or a sequence of frequencies corresponding to\n                a bandpass over which to evaluate the zodiacal emission. The frequencies\n                must be strictly increasing.\n            theta: Angular co-latitude coordinate of a point, or a sequence of points, on\n                the celestial sphere. Must be in the range [0, \u03c0] rad. Units must be either\n                radians or degrees.\n            phi: Angular longitude coordinate of a point, or a sequence of points, on the\n                celestial sphere. Must be in the range [0, 2\u03c0] rad. Units must be either\n                radians or degrees.\n            nside: HEALPix resolution parameter of the binned map.\n            obs_time: Time of observation.\n            obs: Name of the Solar System observer. A list of all support observers (for a\n                given ephemeridis) is specified in `supported_observers` attribute of the\n                `Zodipy` instance. Defaults to 'earth'.\n            obs_pos: The heliocentric ecliptic cartesian position of the observer in AU.\n                Overrides the `obs` argument. Default is None.\n            weights: Bandpass weights corresponding the the frequencies in `freq`. The weights\n                are assumed to be given in spectral radiance units (Jy/sr).\n            lonlat: If True, input angles `theta`, `phi` are assumed to be longitude and\n                latitude, otherwise, they are co-latitude and longitude.\n            return_comps: If True, the emission is returned component-wise. Defaults to False.\n            coord_in: Coordinate frame of the input pointing. Assumes 'E' (ecliptic\n                coordinates) by default.\n\n        Returns:\n            emission: Simulated zodiacal emission in units of 'MJy/sr'.\n\n        \"\"\"\n        theta, phi = get_validated_ang(theta=theta, phi=phi, lonlat=lonlat)\n\n        unique_angles, counts = np.unique(np.asarray([theta, phi]), return_counts=True, axis=1)\n        unique_pixels = hp.ang2pix(nside, *unique_angles, lonlat=lonlat)\n        unit_vectors = get_unit_vectors_from_ang(\n            coord_in=coord_in,\n            theta=unique_angles[0],\n            phi=unique_angles[1],\n            lonlat=lonlat,\n        )\n\n        return self._compute_emission(\n            freq=freq,\n            weights=weights,\n            obs=obs,\n            obs_time=obs_time,\n            obs_pos=obs_pos,\n            unit_vectors=unit_vectors,\n            indicies=counts,\n            binned=True,\n            pixels=unique_pixels,\n            nside=nside,\n            return_comps=return_comps,\n        )\n\n    def get_binned_emission_pix(\n        self,\n        freq: FrequencyOrWavelength,\n        pixels: Pixels,\n        nside: int,\n        obs_time: Time,\n        obs: str = \"earth\",\n        obs_pos: u.Quantity[u.AU] | None = None,\n        weights: Sequence[float] | npt.NDArray[np.floating] | None = None,\n        return_comps: bool = False,\n        coord_in: Literal[\"E\", \"G\", \"C\"] = \"E\",\n    ) -> u.Quantity[u.MJy / u.sr]:\n\"\"\"Return the simulated binned zodiacal Emission given pixel numbers.\n\n        The pixel numbers represent the pixel indicies on a HEALPix grid with resolution\n        given by `nside`. The emission is binned to a HEALPix map with resolution given by\n        `nside`.\n\n        Args:\n            freq: Delta frequency/wavelength or a sequence of frequencies corresponding to\n                a bandpass over which to evaluate the zodiacal emission. The frequencies\n                must be strictly increasing.\n            pixels: HEALPix pixel indicies representing points on the celestial sphere.\n            nside: HEALPix resolution parameter of the pixels and the binned map.\n            obs_time: Time of observation.\n            obs: Name of the Solar System observer. A list of all support observers (for a\n                given ephemeridis) is specified in `supported_observers` attribute of the\n                `Zodipy` instance. Defaults to 'earth'.\n            obs_pos: The heliocentric ecliptic cartesian position of the observer in AU.\n                Overrides the `obs` argument. Default is None.\n            weights: Bandpass weights corresponding the the frequencies in `freq`. The weights\n                are assumed to be given in spectral radiance units (Jy/sr).\n            return_comps: If True, the emission is returned component-wise. Defaults to False.\n            coord_in: Coordinate frame of the input pointing. Assumes 'E' (ecliptic\n                coordinates) by default.\n\n        Returns:\n            emission: Simulated zodiacal emission in units of 'MJy/sr'.\n\n        \"\"\"\n        pixels = get_validated_pix(pixels=pixels, nside=nside)\n\n        unique_pixels, counts = np.unique(pixels, return_counts=True)\n        unit_vectors = get_unit_vectors_from_pixels(\n            coord_in=coord_in,\n            pixels=unique_pixels,\n            nside=nside,\n        )\n\n        return self._compute_emission(\n            freq=freq,\n            weights=weights,\n            obs=obs,\n            obs_time=obs_time,\n            obs_pos=obs_pos,\n            unit_vectors=unit_vectors,\n            indicies=counts,\n            binned=True,\n            pixels=unique_pixels,\n            nside=nside,\n            return_comps=return_comps,\n        )\n\n    def _compute_emission(\n        self,\n        freq: FrequencyOrWavelength,\n        weights: Sequence[float] | npt.NDArray[np.floating] | None,\n        obs: str,\n        obs_time: Time,\n        unit_vectors: npt.NDArray[np.float64],\n        indicies: npt.NDArray[np.int64],\n        binned: bool = False,\n        obs_pos: u.Quantity[u.AU] | None = None,\n        pixels: npt.NDArray[np.int64] | None = None,\n        nside: int | None = None,\n        return_comps: bool = False,\n    ) -> u.Quantity[u.MJy / u.sr]:\n\"\"\"Compute the component-wise zodiacal emission.\"\"\"\n        bandpass = validate_and_get_bandpass(\n            freq=freq,\n            weights=weights,\n            model=self._ipd_model,\n            extrapolate=self.extrapolate,\n        )\n\n        # Get model parameters, some of which have been interpolated to the given\n        # frequency or bandpass.\n        source_parameters = SOURCE_PARAMS_MAPPING[type(self._ipd_model)](\n            bandpass, self._ipd_model, self._interpolator\n        )\n\n        observer_position, earth_position = get_obs_and_earth_positions(\n            obs=obs, obs_time=obs_time, obs_pos=obs_pos\n        )\n\n        # Get the integration limits for each zodiacal component (which may be\n        # different or the same depending on the model) along all line of sights.\n        start, stop = get_line_of_sight_start_and_stop_distances(\n            components=self._ipd_model.comps.keys(),\n            unit_vectors=unit_vectors,\n            obs_pos=observer_position,\n        )\n\n        density_partials = construct_density_partials_comps(\n            comps=self._ipd_model.comps,\n            dynamic_params={\"X_earth\": earth_position},\n        )\n\n        # Make table of pre-computed bandpass integrated blackbody emission.\n        bandpass_interpolatation_table = get_bandpass_interpolation_table(bandpass)\n\n        common_integrand = partial(\n            EMISSION_MAPPING[type(self._ipd_model)],\n            X_obs=observer_position,\n            bp_interpolation_table=bandpass_interpolatation_table,\n            **source_parameters[\"common\"],\n        )\n\n        if self.n_proc > 1:\n            unit_vector_chunks = np.array_split(unit_vectors, self.n_proc, axis=-1)\n            integrated_comp_emission = np.zeros((len(self._ipd_model.comps), unit_vectors.shape[1]))\n            with multiprocessing.get_context(SYS_PROC_START_METHOD).Pool(\n                processes=self.n_proc\n            ) as pool:\n                for idx, comp_label in enumerate(self._ipd_model.comps.keys()):\n                    stop_chunks = np.array_split(stop[comp_label], self.n_proc, axis=-1)\n                    if start[comp_label].size == 1:\n                        start_chunks = [start[comp_label]] * self.n_proc\n                    else:\n                        start_chunks = np.array_split(start[comp_label], self.n_proc, axis=-1)\n                    comp_integrands = [\n                        partial(\n                            common_integrand,\n                            u_los=np.expand_dims(unit_vectors, axis=-1),\n                            start=np.expand_dims(start, axis=-1),\n                            stop=np.expand_dims(stop, axis=-1),\n                            get_density_function=density_partials[comp_label],\n                            **source_parameters[comp_label],\n                        )\n                        for unit_vectors, start, stop in zip(\n                            unit_vector_chunks, start_chunks, stop_chunks\n                        )\n                    ]\n\n                    proc_chunks = [\n                        pool.apply_async(\n                            _integrate_gauss_quad,\n                            args=(comp_integrand, *self._gauss_points_and_weights),\n                        )\n                        for comp_integrand in comp_integrands\n                    ]\n\n                    integrated_comp_emission[idx] += (\n                        np.concatenate([result.get() for result in proc_chunks])\n                        * 0.5\n                        * (stop[comp_label] - start[comp_label])\n                    )\n\n        else:\n            integrated_comp_emission = np.zeros((len(self._ipd_model.comps), unit_vectors.shape[1]))\n            unit_vectors_expanded = np.expand_dims(unit_vectors, axis=-1)\n\n            for idx, comp_label in enumerate(self._ipd_model.comps.keys()):\n                comp_integrand = partial(\n                    common_integrand,\n                    u_los=unit_vectors_expanded,\n                    start=np.expand_dims(start[comp_label], axis=-1),\n                    stop=np.expand_dims(stop[comp_label], axis=-1),\n                    get_density_function=density_partials[comp_label],\n                    **source_parameters[comp_label],\n                )\n\n                integrated_comp_emission[idx] = (\n                    _integrate_gauss_quad(comp_integrand, *self._gauss_points_and_weights)\n                    * 0.5\n                    * (stop[comp_label] - start[comp_label])\n                )\n\n        emission = np.zeros(\n            (\n                len(self._ipd_model.comps),\n                hp.nside2npix(nside) if binned else indicies.size,\n            )\n        )\n        if binned:\n            emission[:, pixels] = integrated_comp_emission\n        else:\n            emission = integrated_comp_emission[:, indicies]\n\n        if self.solar_cut is not None:\n            ang_dist = hp.rotator.angdist(-observer_position.flatten(), unit_vectors)\n            solar_mask = ang_dist < self.solar_cut.value\n            if binned and pixels is not None:\n                emission[:, pixels[solar_mask]] = self.solar_cut_fill_value\n            else:\n                emission[:, solar_mask[indicies]] = self.solar_cut_fill_value\n\n        emission = (emission << SPECIFIC_INTENSITY_UNITS).to(u.MJy / u.sr)\n\n        return emission if return_comps else emission.sum(axis=0)\n\n    def __repr__(self) -> str:\n        repr_str = f\"{self.__class__.__name__}(\"\n        for attribute_name, attribute in self.__dict__.items():\n            if attribute_name.startswith(\"_\"):\n                continue\n            repr_str += f\"{attribute_name}={attribute!r}, \"\n\n        return repr_str[:-2] + \")\"\n
"},{"location":"reference/#zodipy.zodipy.Zodipy.supported_observers","title":"supported_observers: list[str] property","text":"

Return a list of available observers given an ephemeris.

"},{"location":"reference/#zodipy.zodipy.Zodipy.get_binned_emission_ang","title":"get_binned_emission_ang(freq, theta, phi, nside, obs_time, obs='earth', obs_pos=None, weights=None, lonlat=False, return_comps=False, coord_in='E')","text":"

Return the simulated binned zodiacal emission given angles on the sky.

The pointing, for which to compute the emission, is specified in form of angles on the sky given by theta and phi. The emission is binned to a HEALPix map with resolution given by nside.

Parameters:

Name Type Description Default freq FrequencyOrWavelength

Delta frequency/wavelength or a sequence of frequencies corresponding to a bandpass over which to evaluate the zodiacal emission. The frequencies must be strictly increasing.

required theta SkyAngles

Angular co-latitude coordinate of a point, or a sequence of points, on the celestial sphere. Must be in the range [0, \u03c0] rad. Units must be either radians or degrees.

required phi SkyAngles

Angular longitude coordinate of a point, or a sequence of points, on the celestial sphere. Must be in the range [0, 2\u03c0] rad. Units must be either radians or degrees.

required nside int

HEALPix resolution parameter of the binned map.

required obs_time Time

Time of observation.

required obs str

Name of the Solar System observer. A list of all support observers (for a given ephemeridis) is specified in supported_observers attribute of the Zodipy instance. Defaults to 'earth'.

'earth' obs_pos Quantity[AU] | None

The heliocentric ecliptic cartesian position of the observer in AU. Overrides the obs argument. Default is None.

None weights Sequence[float] | NDArray[floating] | None

Bandpass weights corresponding the the frequencies in freq. The weights are assumed to be given in spectral radiance units (Jy/sr).

None lonlat bool

If True, input angles theta, phi are assumed to be longitude and latitude, otherwise, they are co-latitude and longitude.

False return_comps bool

If True, the emission is returned component-wise. Defaults to False.

False coord_in Literal['E', 'G', 'C']

Coordinate frame of the input pointing. Assumes 'E' (ecliptic coordinates) by default.

'E'

Returns:

Name Type Description emission Quantity[MJy / sr]

Simulated zodiacal emission in units of 'MJy/sr'.

Source code in zodipy/zodipy.py
def get_binned_emission_ang(\n    self,\n    freq: FrequencyOrWavelength,\n    theta: SkyAngles,\n    phi: SkyAngles,\n    nside: int,\n    obs_time: Time,\n    obs: str = \"earth\",\n    obs_pos: u.Quantity[u.AU] | None = None,\n    weights: Sequence[float] | npt.NDArray[np.floating] | None = None,\n    lonlat: bool = False,\n    return_comps: bool = False,\n    coord_in: Literal[\"E\", \"G\", \"C\"] = \"E\",\n) -> u.Quantity[u.MJy / u.sr]:\n\"\"\"Return the simulated binned zodiacal emission given angles on the sky.\n\n    The pointing, for which to compute the emission, is specified in form of angles on\n    the sky given by `theta` and `phi`. The emission is binned to a HEALPix map with\n    resolution given by `nside`.\n\n    Args:\n        freq: Delta frequency/wavelength or a sequence of frequencies corresponding to\n            a bandpass over which to evaluate the zodiacal emission. The frequencies\n            must be strictly increasing.\n        theta: Angular co-latitude coordinate of a point, or a sequence of points, on\n            the celestial sphere. Must be in the range [0, \u03c0] rad. Units must be either\n            radians or degrees.\n        phi: Angular longitude coordinate of a point, or a sequence of points, on the\n            celestial sphere. Must be in the range [0, 2\u03c0] rad. Units must be either\n            radians or degrees.\n        nside: HEALPix resolution parameter of the binned map.\n        obs_time: Time of observation.\n        obs: Name of the Solar System observer. A list of all support observers (for a\n            given ephemeridis) is specified in `supported_observers` attribute of the\n            `Zodipy` instance. Defaults to 'earth'.\n        obs_pos: The heliocentric ecliptic cartesian position of the observer in AU.\n            Overrides the `obs` argument. Default is None.\n        weights: Bandpass weights corresponding the the frequencies in `freq`. The weights\n            are assumed to be given in spectral radiance units (Jy/sr).\n        lonlat: If True, input angles `theta`, `phi` are assumed to be longitude and\n            latitude, otherwise, they are co-latitude and longitude.\n        return_comps: If True, the emission is returned component-wise. Defaults to False.\n        coord_in: Coordinate frame of the input pointing. Assumes 'E' (ecliptic\n            coordinates) by default.\n\n    Returns:\n        emission: Simulated zodiacal emission in units of 'MJy/sr'.\n\n    \"\"\"\n    theta, phi = get_validated_ang(theta=theta, phi=phi, lonlat=lonlat)\n\n    unique_angles, counts = np.unique(np.asarray([theta, phi]), return_counts=True, axis=1)\n    unique_pixels = hp.ang2pix(nside, *unique_angles, lonlat=lonlat)\n    unit_vectors = get_unit_vectors_from_ang(\n        coord_in=coord_in,\n        theta=unique_angles[0],\n        phi=unique_angles[1],\n        lonlat=lonlat,\n    )\n\n    return self._compute_emission(\n        freq=freq,\n        weights=weights,\n        obs=obs,\n        obs_time=obs_time,\n        obs_pos=obs_pos,\n        unit_vectors=unit_vectors,\n        indicies=counts,\n        binned=True,\n        pixels=unique_pixels,\n        nside=nside,\n        return_comps=return_comps,\n    )\n
"},{"location":"reference/#zodipy.zodipy.Zodipy.get_binned_emission_pix","title":"get_binned_emission_pix(freq, pixels, nside, obs_time, obs='earth', obs_pos=None, weights=None, return_comps=False, coord_in='E')","text":"

Return the simulated binned zodiacal Emission given pixel numbers.

The pixel numbers represent the pixel indicies on a HEALPix grid with resolution given by nside. The emission is binned to a HEALPix map with resolution given by nside.

Parameters:

Name Type Description Default freq FrequencyOrWavelength

Delta frequency/wavelength or a sequence of frequencies corresponding to a bandpass over which to evaluate the zodiacal emission. The frequencies must be strictly increasing.

required pixels Pixels

HEALPix pixel indicies representing points on the celestial sphere.

required nside int

HEALPix resolution parameter of the pixels and the binned map.

required obs_time Time

Time of observation.

required obs str

Name of the Solar System observer. A list of all support observers (for a given ephemeridis) is specified in supported_observers attribute of the Zodipy instance. Defaults to 'earth'.

'earth' obs_pos Quantity[AU] | None

The heliocentric ecliptic cartesian position of the observer in AU. Overrides the obs argument. Default is None.

None weights Sequence[float] | NDArray[floating] | None

Bandpass weights corresponding the the frequencies in freq. The weights are assumed to be given in spectral radiance units (Jy/sr).

None return_comps bool

If True, the emission is returned component-wise. Defaults to False.

False coord_in Literal['E', 'G', 'C']

Coordinate frame of the input pointing. Assumes 'E' (ecliptic coordinates) by default.

'E'

Returns:

Name Type Description emission Quantity[MJy / sr]

Simulated zodiacal emission in units of 'MJy/sr'.

Source code in zodipy/zodipy.py
def get_binned_emission_pix(\n    self,\n    freq: FrequencyOrWavelength,\n    pixels: Pixels,\n    nside: int,\n    obs_time: Time,\n    obs: str = \"earth\",\n    obs_pos: u.Quantity[u.AU] | None = None,\n    weights: Sequence[float] | npt.NDArray[np.floating] | None = None,\n    return_comps: bool = False,\n    coord_in: Literal[\"E\", \"G\", \"C\"] = \"E\",\n) -> u.Quantity[u.MJy / u.sr]:\n\"\"\"Return the simulated binned zodiacal Emission given pixel numbers.\n\n    The pixel numbers represent the pixel indicies on a HEALPix grid with resolution\n    given by `nside`. The emission is binned to a HEALPix map with resolution given by\n    `nside`.\n\n    Args:\n        freq: Delta frequency/wavelength or a sequence of frequencies corresponding to\n            a bandpass over which to evaluate the zodiacal emission. The frequencies\n            must be strictly increasing.\n        pixels: HEALPix pixel indicies representing points on the celestial sphere.\n        nside: HEALPix resolution parameter of the pixels and the binned map.\n        obs_time: Time of observation.\n        obs: Name of the Solar System observer. A list of all support observers (for a\n            given ephemeridis) is specified in `supported_observers` attribute of the\n            `Zodipy` instance. Defaults to 'earth'.\n        obs_pos: The heliocentric ecliptic cartesian position of the observer in AU.\n            Overrides the `obs` argument. Default is None.\n        weights: Bandpass weights corresponding the the frequencies in `freq`. The weights\n            are assumed to be given in spectral radiance units (Jy/sr).\n        return_comps: If True, the emission is returned component-wise. Defaults to False.\n        coord_in: Coordinate frame of the input pointing. Assumes 'E' (ecliptic\n            coordinates) by default.\n\n    Returns:\n        emission: Simulated zodiacal emission in units of 'MJy/sr'.\n\n    \"\"\"\n    pixels = get_validated_pix(pixels=pixels, nside=nside)\n\n    unique_pixels, counts = np.unique(pixels, return_counts=True)\n    unit_vectors = get_unit_vectors_from_pixels(\n        coord_in=coord_in,\n        pixels=unique_pixels,\n        nside=nside,\n    )\n\n    return self._compute_emission(\n        freq=freq,\n        weights=weights,\n        obs=obs,\n        obs_time=obs_time,\n        obs_pos=obs_pos,\n        unit_vectors=unit_vectors,\n        indicies=counts,\n        binned=True,\n        pixels=unique_pixels,\n        nside=nside,\n        return_comps=return_comps,\n    )\n
"},{"location":"reference/#zodipy.zodipy.Zodipy.get_emission_ang","title":"get_emission_ang(freq, theta, phi, obs_time, obs='earth', obs_pos=None, weights=None, lonlat=False, return_comps=False, coord_in='E')","text":"

Return the simulated zodiacal emission given angles on the sky.

The pointing, for which to compute the emission, is specified in form of angles on the sky given by theta and phi.

Parameters:

Name Type Description Default freq FrequencyOrWavelength

Delta frequency/wavelength or a sequence of frequencies corresponding to a bandpass over which to evaluate the zodiacal emission. The frequencies must be strictly increasing.

required theta SkyAngles

Angular co-latitude coordinate of a point, or a sequence of points, on the celestial sphere. Must be in the range [0, \u03c0] rad. Units must be either radians or degrees.

required phi SkyAngles

Angular longitude coordinate of a point, or a sequence of points, on the celestial sphere. Must be in the range [0, 2\u03c0] rad. Units must be either radians or degrees.

required obs_time Time

Time of observation.

required obs str

Name of the Solar System observer. A list of all support observers (for a given ephemeridis) is specified in supported_observers attribute of the Zodipy instance. Defaults to 'earth'.

'earth' obs_pos Quantity[AU] | None

The heliocentric ecliptic cartesian position of the observer in AU. Overrides the obs argument. Default is None.

None weights Sequence[float] | NDArray[floating] | None

Bandpass weights corresponding the the frequencies in freq. The weights are assumed to be given in spectral radiance units (Jy/sr).

None lonlat bool

If True, input angles (theta, phi) are assumed to be longitude and latitude, otherwise, they are co-latitude and longitude.

False return_comps bool

If True, the emission is returned component-wise. Defaults to False.

False coord_in Literal['E', 'G', 'C']

Coordinate frame of the input pointing. Assumes 'E' (ecliptic coordinates) by default.

'E'

Returns:

Name Type Description emission Quantity[MJy / sr]

Simulated zodiacal emission in units of 'MJy/sr'.

Source code in zodipy/zodipy.py
def get_emission_ang(\n    self,\n    freq: FrequencyOrWavelength,\n    theta: SkyAngles,\n    phi: SkyAngles,\n    obs_time: Time,\n    obs: str = \"earth\",\n    obs_pos: u.Quantity[u.AU] | None = None,\n    weights: Sequence[float] | npt.NDArray[np.floating] | None = None,\n    lonlat: bool = False,\n    return_comps: bool = False,\n    coord_in: Literal[\"E\", \"G\", \"C\"] = \"E\",\n) -> u.Quantity[u.MJy / u.sr]:\n\"\"\"Return the simulated zodiacal emission given angles on the sky.\n\n    The pointing, for which to compute the emission, is specified in form of angles on\n    the sky given by `theta` and `phi`.\n\n    Args:\n        freq: Delta frequency/wavelength or a sequence of frequencies corresponding to\n            a bandpass over which to evaluate the zodiacal emission. The frequencies\n            must be strictly increasing.\n        theta: Angular co-latitude coordinate of a point, or a sequence of points, on\n            the celestial sphere. Must be in the range [0, \u03c0] rad. Units must be either\n            radians or degrees.\n        phi: Angular longitude coordinate of a point, or a sequence of points, on the\n            celestial sphere. Must be in the range [0, 2\u03c0] rad. Units must be either\n            radians or degrees.\n        obs_time: Time of observation.\n        obs: Name of the Solar System observer. A list of all support observers (for a\n            given ephemeridis) is specified in `supported_observers` attribute of the\n            `Zodipy` instance. Defaults to 'earth'.\n        obs_pos: The heliocentric ecliptic cartesian position of the observer in AU.\n            Overrides the `obs` argument. Default is None.\n        weights: Bandpass weights corresponding the the frequencies in `freq`. The weights\n            are assumed to be given in spectral radiance units (Jy/sr).\n        lonlat: If True, input angles (`theta`, `phi`) are assumed to be longitude and\n            latitude, otherwise, they are co-latitude and longitude.\n        return_comps: If True, the emission is returned component-wise. Defaults to False.\n        coord_in: Coordinate frame of the input pointing. Assumes 'E' (ecliptic\n            coordinates) by default.\n\n    Returns:\n        emission: Simulated zodiacal emission in units of 'MJy/sr'.\n\n    \"\"\"\n    theta, phi = get_validated_ang(theta=theta, phi=phi, lonlat=lonlat)\n\n    unique_angles, indicies = np.unique(np.asarray([theta, phi]), return_inverse=True, axis=1)\n    unit_vectors = get_unit_vectors_from_ang(\n        coord_in=coord_in,\n        theta=unique_angles[0],\n        phi=unique_angles[1],\n        lonlat=lonlat,\n    )\n\n    return self._compute_emission(\n        freq=freq,\n        weights=weights,\n        obs=obs,\n        obs_time=obs_time,\n        obs_pos=obs_pos,\n        unit_vectors=unit_vectors,\n        indicies=indicies,\n        return_comps=return_comps,\n    )\n
"},{"location":"reference/#zodipy.zodipy.Zodipy.get_emission_pix","title":"get_emission_pix(freq, pixels, nside, obs_time, obs='earth', obs_pos=None, weights=None, return_comps=False, coord_in='E')","text":"

Return the simulated zodiacal emission given pixel numbers.

The pixel numbers represent the pixel indicies on a HEALPix grid with resolution given by nside.

Parameters:

Name Type Description Default freq FrequencyOrWavelength

Delta frequency/wavelength or a sequence of frequencies corresponding to a bandpass over which to evaluate the zodiacal emission. The frequencies must be strictly increasing.

required pixels Pixels

HEALPix pixel indicies representing points on the celestial sphere.

required nside int

HEALPix resolution parameter of the pixels and the binned map.

required obs_time Time

Time of observation.

required obs str

Name of the Solar System observer. A list of all support observers (for a given ephemeridis) is specified in supported_observers attribute of the Zodipy instance. Defaults to 'earth'.

'earth' obs_pos Quantity[AU] | None

The heliocentric ecliptic cartesian position of the observer in AU. Overrides the obs argument. Default is None.

None weights Sequence[float] | NDArray[floating] | None

Bandpass weights corresponding the the frequencies in freq. The weights are assumed to be given in spectral radiance units (Jy/sr).

None return_comps bool

If True, the emission is returned component-wise. Defaults to False.

False coord_in Literal['E', 'G', 'C']

Coordinate frame of the input pointing. Assumes 'E' (ecliptic coordinates) by default.

'E'

Returns:

Name Type Description emission Quantity[MJy / sr]

Simulated zodiacal emission in units of 'MJy/sr'.

Source code in zodipy/zodipy.py
def get_emission_pix(\n    self,\n    freq: FrequencyOrWavelength,\n    pixels: Pixels,\n    nside: int,\n    obs_time: Time,\n    obs: str = \"earth\",\n    obs_pos: u.Quantity[u.AU] | None = None,\n    weights: Sequence[float] | npt.NDArray[np.floating] | None = None,\n    return_comps: bool = False,\n    coord_in: Literal[\"E\", \"G\", \"C\"] = \"E\",\n) -> u.Quantity[u.MJy / u.sr]:\n\"\"\"Return the simulated zodiacal emission given pixel numbers.\n\n    The pixel numbers represent the pixel indicies on a HEALPix grid with resolution\n    given by `nside`.\n\n    Args:\n        freq: Delta frequency/wavelength or a sequence of frequencies corresponding to\n            a bandpass over which to evaluate the zodiacal emission. The frequencies\n            must be strictly increasing.\n        pixels: HEALPix pixel indicies representing points on the celestial sphere.\n        nside: HEALPix resolution parameter of the pixels and the binned map.\n        obs_time: Time of observation.\n        obs: Name of the Solar System observer. A list of all support observers (for a\n            given ephemeridis) is specified in `supported_observers` attribute of the\n            `Zodipy` instance. Defaults to 'earth'.\n        obs_pos: The heliocentric ecliptic cartesian position of the observer in AU.\n            Overrides the `obs` argument. Default is None.\n        weights: Bandpass weights corresponding the the frequencies in `freq`. The weights\n            are assumed to be given in spectral radiance units (Jy/sr).\n        return_comps: If True, the emission is returned component-wise. Defaults to False.\n        coord_in: Coordinate frame of the input pointing. Assumes 'E' (ecliptic\n            coordinates) by default.\n\n    Returns:\n        emission: Simulated zodiacal emission in units of 'MJy/sr'.\n\n    \"\"\"\n    pixels = get_validated_pix(pixels=pixels, nside=nside)\n\n    unique_pixels, indicies = np.unique(pixels, return_inverse=True)\n    unit_vectors = get_unit_vectors_from_pixels(\n        coord_in=coord_in,\n        pixels=unique_pixels,\n        nside=nside,\n    )\n\n    return self._compute_emission(\n        freq=freq,\n        weights=weights,\n        obs=obs,\n        obs_time=obs_time,\n        obs_pos=obs_pos,\n        unit_vectors=unit_vectors,\n        indicies=indicies,\n        pixels=unique_pixels,\n        nside=nside,\n        return_comps=return_comps,\n    )\n
"},{"location":"reference/#zodipy.zodipy.Zodipy.get_parameters","title":"get_parameters()","text":"

Return a dictionary containing the interplanetary dust model parameters.

Source code in zodipy/zodipy.py
def get_parameters(self) -> ParameterDict:\n\"\"\"Return a dictionary containing the interplanetary dust model parameters.\"\"\"\n    return self._ipd_model.to_dict()\n
"},{"location":"reference/#zodipy.zodipy.Zodipy.update_parameters","title":"update_parameters(parameters)","text":"

Update the interplanetary dust model parameters.

Parameters:

Name Type Description Default parameters ParameterDict

Dictionary of parameters to update. The keys must be the names of the parameters as defined in the model. To get the parameters dict of an existing model, use Zodipy(\"dirbe\").get_parameters().

required Source code in zodipy/zodipy.py
def update_parameters(self, parameters: ParameterDict) -> None:\n\"\"\"Update the interplanetary dust model parameters.\n\n    Args:\n        parameters: Dictionary of parameters to update. The keys must be the names\n            of the parameters as defined in the model. To get the parameters dict\n            of an existing model, use `Zodipy(\"dirbe\").get_parameters()`.\n\n    \"\"\"\n    _dict = parameters.copy()\n    _dict[\"comps\"] = {}\n    for key, value in parameters.items():\n        if key == \"comps\":\n            for comp_key, comp_value in value.items():\n                _dict[\"comps\"][ComponentLabel(comp_key)] = type(\n                    self._ipd_model.comps[ComponentLabel(comp_key)]\n                )(**comp_value)\n        elif isinstance(value, dict):\n            _dict[key] = {ComponentLabel(k): v for k, v in value.items()}\n\n    self._ipd_model = self._ipd_model.__class__(**_dict)\n
"},{"location":"usage/","title":"Usage","text":""},{"location":"usage/#timestreams","title":"Timestreams","text":"

Below we illustrate how ZodiPy can be used to create timestreams of the zodiacal emission. Note that since ZodiPy assumes a constant observer position over the input pointing sequence, the output will not be real timestreams, but for small enough time intervals the error is negligible.

"},{"location":"usage/#emission-along-a-meridian","title":"Emission along a meridian","text":"

In the following example we simulate what an observer on Earth is expected to see on 14 June, 2022 when looking along a meridian (line of constant longitude) at 30 microns, given the DIRBE interplanetary dust model.

import astropy.units as u\nimport matplotlib.pyplot as plt\nimport numpy as np\nfrom astropy.time import Time\n\nfrom zodipy import Zodipy\n\nmodel = Zodipy(\"dirbe\")\n\nlatitudes = np.linspace(-90, 90, 10000) * u.deg\nlongitudes = np.zeros_like(latitudes)\n\nemission = model.get_emission_ang(\n    30 * u.micron,\n    theta=longitudes,\n    phi=latitudes,\n    lonlat=True,\n    obs_time=Time(\"2022-06-14\"),\n    obs=\"earth\",\n)\n\n\nplt.plot(latitudes, emission)\nplt.xlabel(\"Latitude [deg]\")\nplt.ylabel(\"Emission [MJy/sr]\")\nplt.savefig(\"../img/timestream.png\", dpi=300)\nplt.show()\n

Note

ZodiPy assumes a constant observer position over an input pointing sequence. For an observer on Earth, the true zodiacal emission signal will move along the ecliptic on the sky by roughly one degree each day. To account for this effect, the full pointing sequence of an experiment should be chunked into small subsequences with timescales corresponding to at maximum a day.

"},{"location":"usage/#healpix-maps","title":"HEALPix maps","text":"

Below we illustrate how ZodiPy can be used to create simulated binned HEALPix maps of the zodiacal emission.

"},{"location":"usage/#instantaneous-map-in-ecliptic-coordinates","title":"Instantaneous map in ecliptic coordinates","text":"

In the following example we make an instantaneous map of of the zodiacal emission at 857 GHz as seen by an observer on earth on 14 June, 2022 given the Planck 2018 interplanetary dust model.

import astropy.units as u\nimport healpy as hp\nimport matplotlib.pyplot as plt\nimport numpy as np\nfrom astropy.time import Time\n\nfrom zodipy import Zodipy\n\nmodel = Zodipy(\"planck18\")\nnside = 256\n\nbinned_emission = model.get_binned_emission_pix(\n    857 * u.GHz,\n    pixels=np.arange(hp.nside2npix(nside)),\n    nside=nside,\n    obs_time=Time(\"2022-06-14\"),\n    obs=\"earth\",\n)\n\nhp.mollview(\n    binned_emission,\n    title=\"Binned zodiacal emission at 857 GHz\",\n    unit=\"MJy/sr\",\n    min=0,\n    max=1,\n    cmap=\"afmhot\",\n)\nplt.savefig(\"../img/binned.png\", dpi=300)\nplt.show()\n
Note that the color bar is logarithmic.

"},{"location":"usage/#bandpass-integrated-emission","title":"Bandpass integrated emission","text":"

Instruments do not typically observe at delta frequencies. Usually, we are more interested in finding out what the emission looks like over some instrument bandpass. ZodiPy will accept a sequence of frequencies to the freq argument in addition to the corresponding bandpass weights to the weights argument and perform bandpass integration. Note that the bandpass weights must be in spectral radiance units (Jy/sr), even though the weights them self are unitless. A top hat bandpass is assumed if a sequence of frequencies are used without providing weights.

import astropy.units as u\nimport healpy as hp\nimport matplotlib.pyplot as plt\nimport numpy as np\nfrom astropy.time import Time\n\nfrom zodipy import Zodipy\n\nnside = 128\n\ncenter_freq = 800 * u.GHz\nfreqs = np.linspace(750, 850, 11) * u.GHz\nweights = np.array([2, 3, 5, 9, 11, 11.5, 11, 9, 5, 3, 2])\nplt.plot(freqs, weights)\nplt.xlabel(\"Frequency [GHz]\")\nplt.ylabel(\"Weights\")\nplt.savefig(\"../img/bandpass.png\", dpi=300)\n\nmodel = Zodipy(model=\"planck18\")\n\nemission_central_freq = model.get_binned_emission_pix(\n    freq=center_freq,\n    pixels=np.arange(hp.nside2npix(nside)),\n    nside=nside,\n    obs_time=Time(\"2022-03-10\"),\n    obs=\"SEMB-L2\",\n)\n\nemission_bandpass_integrated = model.get_binned_emission_pix(\nfreq=freqs,\nweights=weights,\npixels=np.arange(hp.nside2npix(nside)),\n    nside=nside,\n    obs_time=Time(\"2022-03-10\"),\n    obs=\"SEMB-L2\",\n)\n\nhp.mollview(\n    emission_central_freq,\n    title=\"Center frequency\",\n    unit=\"MJy/sr\",\n    cmap=\"afmhot\",\n    norm=\"log\",\n)\nplt.savefig(\"../img/center_freq.png\", dpi=300)\n\nhp.mollview(\n    emission_bandpass_integrated,\n    title=\"Bandpass integrated\",\n    unit=\"MJy/sr\",\n    cmap=\"afmhot\",\n    norm=\"log\",\n)\nplt.savefig(\"../img/bandpass_integrated.png\", dpi=300)\nplt.show()\n

"},{"location":"usage/#solar-cutoff-angle","title":"Solar cutoff angle","text":"

Few experiments look directly in towards the Sun. We can initialize Zodipy with the solar_cut argument to mask all input pointing that looks in towards the sun with an angular distance smaller than the solar_cut value.

import astropy.units as u\nimport healpy as hp\nimport matplotlib.pyplot as plt\nimport numpy as np\nfrom astropy.time import Time\n\nfrom zodipy import Zodipy\n\nmodel = Zodipy(\"dirbe\", solar_cut=60 * u.deg)\nnside = 256\n\nbinned_emission = model.get_binned_emission_pix(\n    25 * u.micron,\n    pixels=np.arange(hp.nside2npix(nside)),\n    nside=nside,\n    obs_time=Time(\"2020-01-01\"),\n    obs=\"earth\",\n)\n\nhp.mollview(\n    binned_emission,\n    title=\"Solar cutoff at 60 degrees\",\n    unit=\"MJy/sr\",\n    max=80,\n    coord=\"E\",\n    cmap=\"afmhot\",\n)\nplt.savefig(\"../img/binned_solar_cutoff.png\", dpi=300)\nplt.show()\n

"},{"location":"usage/#non-ecliptic-coordinates","title":"Non-ecliptic coordinates","text":"

We can specify the coordinate system of the input pointing with the coord_in keyword

import astropy.units as u\nimport healpy as hp\nimport matplotlib.pyplot as plt\nimport numpy as np\nfrom astropy.time import Time\n\nfrom zodipy import Zodipy\n\nmodel = Zodipy(\"planck18\")\nnside = 256\n\nbinned_emission = model.get_binned_emission_pix(\n    857 * u.GHz,\n    pixels=np.arange(hp.nside2npix(nside)),\n    nside=nside,\n    obs_time=Time(\"2022-02-20\"),\n    obs=\"earth\",\ncoord_in=\"G\",  # Coordinates of the input pointing\n)\n\nhp.mollview(\n    binned_emission,\n    title=\"Binned zodiacal emission at 857 GHz\",\n    unit=\"MJy/sr\",\n    cmap=\"afmhot\",\n    min=0,\n    max=1,\n)\nplt.savefig(\"../img/binned_gal.png\", dpi=300)\nplt.show()\n

"},{"location":"usage/#component-wise-maps","title":"Component-wise maps","text":"

ZodiPy can also return the zodiacal emission component-wise. In the following example we use the DIRBE model since the later Planck models excluded the circumsolar-ring and Earth-trailing feature components. For more information on the interplanetary dust models, please read Cosmoglobe: Simulating Zodiacal Emission with ZodiPy.

import astropy.units as u\nimport healpy as hp\nimport matplotlib.pyplot as plt\nimport numpy as np\nfrom astropy.time import Time\n\nfrom zodipy import Zodipy\n\nmodel = Zodipy(\"dirbe\")\nnside = 256\n\nbinned_emission = model.get_binned_emission_pix(\n    25 * u.micron,\n    pixels=np.arange(hp.nside2npix(nside)),\n    nside=nside,\n    obs_time=Time(\"2022-01-01\"),\n    obs=\"earth\",\nreturn_comps=True,\n)\nfig = plt.figure(figsize=(8, 6.5), constrained_layout=True)\ncomps = [\"Cloud\", \"Band1\", \"Band2\", \"Band3\", \"Ring\", \"Feature\"]\nfor idx, binned_comp_emission in enumerate(binned_emission):\n    hp.mollview(\n        binned_comp_emission,\n        title=comps[idx],\n        norm=\"log\" if idx == 0 else None,\n        cmap=\"afmhot\",\n        cbar=False,\n        sub=(3, 2, idx + 1),\n        fig=fig,\n    )\n# plt.savefig(\"../img/binned_comp.png\", dpi=300)\nplt.show()\n
Note that the color for the Cloud component is logarithmic, while the others are linear.

"},{"location":"usage/#parallelization","title":"Parallelization","text":"

If you are not using ZodiPy in an already parallelized environment, you may specify the number of cores used by ZodiPy through the n_proc keyword. By default n_proc is set to 1. For values of n_proc > 1, the line-of-sight calculations are parallelized using the multiprocessing module.

import time\n\nimport astropy.units as u\nimport healpy as hp\nimport numpy as np\nfrom astropy.time import Time\n\nfrom zodipy import Zodipy\n\nnside = 256\npixels = np.arange(hp.nside2npix(nside))\nobs_time = Time(\"2020-01-01\")\nn_proc = 8\n\nmodel = Zodipy()\nmodel_parallel = Zodipy(n_proc=n_proc)\nstart = time.perf_counter()\nemission = model.get_binned_emission_pix(\n    40 * u.micron,\n    pixels=pixels,\n    nside=nside,\n    obs_time=obs_time,\n)\nprint(\"Time spent on a single CPU:\", round(time.perf_counter() - start, 2), \"seconds\")\n# > Time spent on a single CPU: 35.23 seconds\n\nstart = time.perf_counter()\nemission_parallel = model_parallel.get_binned_emission_pix(\n    40 * u.micron,\n    pixels=pixels,\n    nside=nside,\n    obs_time=obs_time,\n)\nprint(\n    f\"Time spent on {n_proc} CPUs:\",\n    round(time.perf_counter() - start, 2),\n    \"seconds\",\n)\n# > Time spent on 8 CPUs: 12.85 seconds\n\nassert np.allclose(emission, emission_parallel)\n

Windows users

Windows users must make sure to wrap the get_*_emission_* function calls in a if __name__ == \"__main__\" guard to avoid spawning infinite processes:

...\nif __name__ == \"__main__\":\n    emission = model.get_emission_pix(\n        ...\n    )\n

Using ZodiPy in parallelized environments

If ZodiPy is used in a parallelized environment one may have to specifically set the environment variable OMP_NUM_THREADS=1 to avoid oversubscription. This is due automatic parallelization in third party libraries such as healpy where for instance the hp.Rotator object automatically parallelizes rotation of unit vectors. This means that when using ZodiPy with pointing in a coordinate system other than ecliptic, even if Zodipy is initialized with n_proc=1, healpy will under the hood automatically distribute the pointing to available CPU's.

"},{"location":"usage/#visualizing-the-interplanetary-dust-distribution-of-a-model","title":"Visualizing the interplanetary dust distribution of a model","text":"

It is possible to visualize the three-dimensional interplanetary dust distribution of the models used in ZodiPy by using the tabulate_density function which takes in a interplanetary dust model and a custom grid.

In the following example we tabulate the density distribution of the DIRBE interplanetary dust model and plot the cross section of the diffuse cloud components density in the yz-plane.

import matplotlib.pyplot as plt\nimport numpy as np\nfrom matplotlib.colors import LogNorm\n\nfrom zodipy import tabulate_density\n\nN = 200\n\nx = np.linspace(-5, 5, N)  # x-plane\ny = np.linspace(-5, 5, N)  # y-plane\nz = np.linspace(-2, 2, N)  # z-plane\n\ngrid = np.asarray(np.meshgrid(x, y, z))\ndensity_grid = tabulate_density(grid, model=\"dirbe\")\ndensity_grid = density_grid.sum(axis=0)  # Sum over all components\n\nplt.pcolormesh(\n    x,\n    y,\n    density_grid[N // 2].T,  # cross section in the yz-plane\n    cmap=\"afmhot\",\n    norm=LogNorm(vmin=density_grid.min(), vmax=density_grid.max()),\n    shading=\"gouraud\",\n    rasterized=True,\n)\nplt.title(\"Cross section of the interplanetary dust density (yz-plane)\")\nplt.xlabel(\"x [AU]\")\nplt.ylabel(\"z [AU]\")\n# plt.savefig(\"../img/density_grid.png\", dpi=300)\nplt.show()\n

"}]} \ No newline at end of file diff --git a/sitemap.xml b/sitemap.xml new file mode 100644 index 0000000..0f8724e --- /dev/null +++ b/sitemap.xml @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/sitemap.xml.gz b/sitemap.xml.gz new file mode 100644 index 0000000..374dcde Binary files /dev/null and b/sitemap.xml.gz differ diff --git a/usage/index.html b/usage/index.html new file mode 100644 index 0000000..735df7e --- /dev/null +++ b/usage/index.html @@ -0,0 +1,964 @@ + + + + + + + + + + + + + + + + + + + + + + + + Usage - ZodiPy + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + +
+
+
+ + + + + + + +
+
+ + + + + + + +

Usage

+ +

Timestreams

+

Below we illustrate how ZodiPy can be used to create timestreams of the zodiacal emission. +Note that since ZodiPy assumes a constant observer position over the input pointing sequence, the output +will not be real timestreams, but for small enough time intervals the error is negligible.

+

Emission along a meridian

+

In the following example we simulate what an observer on Earth is expected to see on 14 June, +2022 when looking along a meridian (line of constant longitude) at 30 microns, given the +DIRBE interplanetary dust model.

+
import astropy.units as u
+import matplotlib.pyplot as plt
+import numpy as np
+from astropy.time import Time
+
+from zodipy import Zodipy
+
+model = Zodipy("dirbe")
+
+latitudes = np.linspace(-90, 90, 10000) * u.deg
+longitudes = np.zeros_like(latitudes)
+
+emission = model.get_emission_ang(
+    30 * u.micron,
+    theta=longitudes,
+    phi=latitudes,
+    lonlat=True,
+    obs_time=Time("2022-06-14"),
+    obs="earth",
+)
+
+
+plt.plot(latitudes, emission)
+plt.xlabel("Latitude [deg]")
+plt.ylabel("Emission [MJy/sr]")
+plt.savefig("../img/timestream.png", dpi=300)
+plt.show()
+
+

Zodiacal emission timestream

+
+

Note

+

ZodiPy assumes a constant observer position over an input pointing sequence. For an observer on Earth, +the true zodiacal emission signal will move along the ecliptic on the sky by roughly one degree each day. +To account for this effect, the full pointing sequence of an experiment should be chunked into small +subsequences with timescales corresponding to at maximum a day.

+
+

HEALPix maps

+

Below we illustrate how ZodiPy can be used to create simulated binned HEALPix maps of the zodiacal emission.

+

Instantaneous map in ecliptic coordinates

+

In the following example we make an instantaneous map of of the zodiacal emission at 857 GHz +as seen by an observer on earth on 14 June, 2022 given the Planck 2018 interplanetary dust model.

+

import astropy.units as u
+import healpy as hp
+import matplotlib.pyplot as plt
+import numpy as np
+from astropy.time import Time
+
+from zodipy import Zodipy
+
+model = Zodipy("planck18")
+nside = 256
+
+binned_emission = model.get_binned_emission_pix(
+    857 * u.GHz,
+    pixels=np.arange(hp.nside2npix(nside)),
+    nside=nside,
+    obs_time=Time("2022-06-14"),
+    obs="earth",
+)
+
+hp.mollview(
+    binned_emission,
+    title="Binned zodiacal emission at 857 GHz",
+    unit="MJy/sr",
+    min=0,
+    max=1,
+    cmap="afmhot",
+)
+plt.savefig("../img/binned.png", dpi=300)
+plt.show()
+
+Zodiacal emission map +Note that the color bar is logarithmic.

+

Bandpass integrated emission

+

Instruments do not typically observe at delta frequencies. Usually, we are more interested in finding out +what the emission looks like over some instrument bandpass. ZodiPy will accept a sequence of frequencies to the freq +argument in addition to the corresponding bandpass weights to the weights argument and perform bandpass integration. +Note that the bandpass weights must be in spectral radiance units (Jy/sr), even though the weights them self are unitless. A top hat bandpass is assumed if a sequence of frequencies are used without providing weights. +

import astropy.units as u
+import healpy as hp
+import matplotlib.pyplot as plt
+import numpy as np
+from astropy.time import Time
+
+from zodipy import Zodipy
+
+nside = 128
+
+center_freq = 800 * u.GHz
+freqs = np.linspace(750, 850, 11) * u.GHz
+weights = np.array([2, 3, 5, 9, 11, 11.5, 11, 9, 5, 3, 2])
+
+plt.plot(freqs, weights)
+plt.xlabel("Frequency [GHz]")
+plt.ylabel("Weights")
+plt.savefig("../img/bandpass.png", dpi=300)
+
+model = Zodipy(model="planck18")
+
+emission_central_freq = model.get_binned_emission_pix(
+    freq=center_freq,
+    pixels=np.arange(hp.nside2npix(nside)),
+    nside=nside,
+    obs_time=Time("2022-03-10"),
+    obs="SEMB-L2",
+)
+
+emission_bandpass_integrated = model.get_binned_emission_pix(
+    freq=freqs,
+    weights=weights,
+    pixels=np.arange(hp.nside2npix(nside)),
+    nside=nside,
+    obs_time=Time("2022-03-10"),
+    obs="SEMB-L2",
+)
+
+hp.mollview(
+    emission_central_freq,
+    title="Center frequency",
+    unit="MJy/sr",
+    cmap="afmhot",
+    norm="log",
+)
+plt.savefig("../img/center_freq.png", dpi=300)
+
+hp.mollview(
+    emission_bandpass_integrated,
+    title="Bandpass integrated",
+    unit="MJy/sr",
+    cmap="afmhot",
+    norm="log",
+)
+plt.savefig("../img/bandpass_integrated.png", dpi=300)
+plt.show()
+
+Generated Bandpass +Center frequency emission +Bandpass integrated emission

+

Solar cutoff angle

+

Few experiments look directly in towards the Sun. We can initialize Zodipy with the solar_cut +argument to mask all input pointing that looks in towards the sun with an angular distance smaller +than the solar_cut value.

+

import astropy.units as u
+import healpy as hp
+import matplotlib.pyplot as plt
+import numpy as np
+from astropy.time import Time
+
+from zodipy import Zodipy
+
+model = Zodipy("dirbe", solar_cut=60 * u.deg)
+nside = 256
+
+binned_emission = model.get_binned_emission_pix(
+    25 * u.micron,
+    pixels=np.arange(hp.nside2npix(nside)),
+    nside=nside,
+    obs_time=Time("2020-01-01"),
+    obs="earth",
+)
+
+hp.mollview(
+    binned_emission,
+    title="Solar cutoff at 60 degrees",
+    unit="MJy/sr",
+    max=80,
+    coord="E",
+    cmap="afmhot",
+)
+plt.savefig("../img/binned_solar_cutoff.png", dpi=300)
+plt.show()
+
+Zodiacal emission map

+

Non-ecliptic coordinates

+

We can specify the coordinate system of the input pointing with the coord_in keyword

+

import astropy.units as u
+import healpy as hp
+import matplotlib.pyplot as plt
+import numpy as np
+from astropy.time import Time
+
+from zodipy import Zodipy
+
+model = Zodipy("planck18")
+nside = 256
+
+binned_emission = model.get_binned_emission_pix(
+    857 * u.GHz,
+    pixels=np.arange(hp.nside2npix(nside)),
+    nside=nside,
+    obs_time=Time("2022-02-20"),
+    obs="earth",
+    coord_in="G",  # Coordinates of the input pointing
+)
+
+hp.mollview(
+    binned_emission,
+    title="Binned zodiacal emission at 857 GHz",
+    unit="MJy/sr",
+    cmap="afmhot",
+    min=0,
+    max=1,
+)
+plt.savefig("../img/binned_gal.png", dpi=300)
+plt.show()
+
+Zodiacal emission map galactic

+

Component-wise maps

+

ZodiPy can also return the zodiacal emission component-wise. In the following example we use +the DIRBE model since the later Planck models excluded the circumsolar-ring and Earth-trailing +feature components. For more information on the interplanetary dust models, please +read Cosmoglobe: Simulating Zodiacal Emission with ZodiPy.

+

import astropy.units as u
+import healpy as hp
+import matplotlib.pyplot as plt
+import numpy as np
+from astropy.time import Time
+
+from zodipy import Zodipy
+
+model = Zodipy("dirbe")
+nside = 256
+
+binned_emission = model.get_binned_emission_pix(
+    25 * u.micron,
+    pixels=np.arange(hp.nside2npix(nside)),
+    nside=nside,
+    obs_time=Time("2022-01-01"),
+    obs="earth",
+    return_comps=True,
+)
+fig = plt.figure(figsize=(8, 6.5), constrained_layout=True)
+comps = ["Cloud", "Band1", "Band2", "Band3", "Ring", "Feature"]
+for idx, binned_comp_emission in enumerate(binned_emission):
+    hp.mollview(
+        binned_comp_emission,
+        title=comps[idx],
+        norm="log" if idx == 0 else None,
+        cmap="afmhot",
+        cbar=False,
+        sub=(3, 2, idx + 1),
+        fig=fig,
+    )
+# plt.savefig("../img/binned_comp.png", dpi=300)
+plt.show()
+
+Component-wise emission maps +Note that the color for the Cloud component is logarithmic, while the others are linear.

+

Parallelization

+

If you are not using ZodiPy in an already parallelized environment, you may specify the number of cores used by ZodiPy through the n_proc keyword. By default n_proc is set to 1. For values of n_proc > 1, the line-of-sight calculations are parallelized using the multiprocessing module.

+
import time
+
+import astropy.units as u
+import healpy as hp
+import numpy as np
+from astropy.time import Time
+
+from zodipy import Zodipy
+
+nside = 256
+pixels = np.arange(hp.nside2npix(nside))
+obs_time = Time("2020-01-01")
+n_proc = 8
+
+model = Zodipy()
+model_parallel = Zodipy(n_proc=n_proc)
+
+start = time.perf_counter()
+emission = model.get_binned_emission_pix(
+    40 * u.micron,
+    pixels=pixels,
+    nside=nside,
+    obs_time=obs_time,
+)
+print("Time spent on a single CPU:", round(time.perf_counter() - start, 2), "seconds")
+# > Time spent on a single CPU: 35.23 seconds
+
+start = time.perf_counter()
+emission_parallel = model_parallel.get_binned_emission_pix(
+    40 * u.micron,
+    pixels=pixels,
+    nside=nside,
+    obs_time=obs_time,
+)
+print(
+    f"Time spent on {n_proc} CPUs:",
+    round(time.perf_counter() - start, 2),
+    "seconds",
+)
+# > Time spent on 8 CPUs: 12.85 seconds
+
+assert np.allclose(emission, emission_parallel)
+
+
+

Windows users

+

Windows users must make sure to wrap the get_*_emission_* function calls in a if __name__ == "__main__" guard to avoid spawning infinite processes: +

...
+if __name__ == "__main__":
+    emission = model.get_emission_pix(
+        ...
+    )
+

+
+
+

Using ZodiPy in parallelized environments

+

If ZodiPy is used in a parallelized environment one may have to specifically set the environment variable +OMP_NUM_THREADS=1 to avoid oversubscription. This is due automatic parallelization in third party libraries such as healpy where for instance the hp.Rotator object automatically parallelizes rotation of unit vectors. +This means that when using ZodiPy with pointing in a coordinate system other than ecliptic, even if Zodipy is initialized with n_proc=1, healpy will under the hood automatically distribute the pointing to available CPU's.

+
+

Visualizing the interplanetary dust distribution of a model

+

It is possible to visualize the three-dimensional interplanetary dust distribution of the models used in +ZodiPy by using the tabulate_density function which takes in a interplanetary dust model and a custom grid.

+

In the following example we tabulate the density distribution of the DIRBE interplanetary dust model +and plot the cross section of the diffuse cloud components density in the yz-plane.

+

import matplotlib.pyplot as plt
+import numpy as np
+from matplotlib.colors import LogNorm
+
+from zodipy import tabulate_density
+
+N = 200
+
+x = np.linspace(-5, 5, N)  # x-plane
+y = np.linspace(-5, 5, N)  # y-plane
+z = np.linspace(-2, 2, N)  # z-plane
+
+grid = np.asarray(np.meshgrid(x, y, z))
+density_grid = tabulate_density(grid, model="dirbe")
+density_grid = density_grid.sum(axis=0)  # Sum over all components
+
+plt.pcolormesh(
+    x,
+    y,
+    density_grid[N // 2].T,  # cross section in the yz-plane
+    cmap="afmhot",
+    norm=LogNorm(vmin=density_grid.min(), vmax=density_grid.max()),
+    shading="gouraud",
+    rasterized=True,
+)
+plt.title("Cross section of the interplanetary dust density (yz-plane)")
+plt.xlabel("x [AU]")
+plt.ylabel("z [AU]")
+# plt.savefig("../img/density_grid.png", dpi=300)
+plt.show()
+
+Interplanetary dust distribution

+ + + + + + +
+
+ + +
+ +
+ + + +
+
+
+
+ + + + + + + + + + + + + + + + + + + + + \ No newline at end of file