New field-of-view observer - #337

Open
vsnever wants to merge 1 commit into
raysect:developmentfrom
vsnever:feature/FovCamera
Open

New field-of-view observer#337
vsnever wants to merge 1 commit into
raysect:developmentfrom
vsnever:feature/FovCamera

Conversation

@vsnever

Copy link
Copy Markdown
Contributor

This adds a new 2D observer called FovCamera that launches rays from the observer's origin point over a specified field of view in spherical coordinates. Each pixel of the final image represents a solid angle of collection inside an azimuth-altitude rectangle.
When developing a new diagnostic, before selecting lines of sight, setting the optics, etc. it may be useful to obtain an image in the field of view of that diagnostic as a function of azimuthal and altitudinal angles. VectorCamera can be used for that purpose, however I think that having a dedicated, simpler class is better.
I propose it for Raysect, but if you find it more suitable for Cherab, then I'm not against moving it to Cherab.

mattngc
mattngc previously approved these changes Dec 30, 2019

@mattngcmattngc left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Thanks Vlad for this contrib. Looks good to me. I've done some testing to and works nicely in my use cases. I'd say its ready to merge as is. I'll just leave it up another 2 days in case one of the others wants to comment.

@mattngcmattngc self-assigned this Dec 30, 2019
@mattngcmattngc added this to the Release v0.7 milestone Dec 30, 2019
@CnlPepper

CnlPepper commented Dec 30, 2019

Copy link
Copy Markdown
Member

I was going to add a camera called LightProbe that performs even sampling over a sphere, with optional range restriction and with configurable mapping to a rectangle. Equi-angle sampling would be one of the possible mapping options, as would equi-area. The functionality of the FOVCamera would end up being a subset of the LightProbe. As such I'd prefer we don't merge this unless it is generalised further... i.e. implementing a full light probe.

The mapping would be a plug-able mapping class. The angle restriction would be centred around the +ve Z-axis as per other cameras.

@CnlPepper

Copy link
Copy Markdown
Member

@vsnever could I make a request that new features are discussed via the issue tracker before implementation and merge request. You a producing some great code, however receiving merge requests out of the blue containing new features puts us in a difficult position when those requests clash with planned functionality. To ensure neither your, nor our time is wasted and that there are no hard feelings, we would prefer it if an issue is raised proposing a feature before any merge requests are sent. We can then decide on the approach before generating code.

cdef:
np.ndarray solid_angle1d

solid_angle1d = (pi / 180.) * self.azimuth_delta * (np.sin((pi / 180.) * (self._altitude + 0.5 * self.altitude_delta)) -

@CnlPepperCnlPepperDec 30, 2019

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

This doesn't look right to me. d(SA) = sin(theta) d(theta) d(phi). The shouldn't the surface integral over an element spanning [theta0, theta1] and [phi0, phi1] include a cos term....

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

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

Here, the altitude angle is measured from the equatorial plane, not from the pole (Z-axis is also lies in the equatorial plane, it easier when dealing with a field of view), so d(SA) = cos(theta) d(theta) d(phi).

@CnlPepperCnlPepperDec 30, 2019

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Not sure I followed the description. The raysect standard is for the camera to look along the +ve z-axis, with the "up" direction being +ve y-axis. The altitude here should be the equivalent of the pitch in math.transform.rotate(), while the azimuth should be the yaw. (0, 0) degrees being aligned with the z-axis. Is this what you mean?

@CnlPepperCnlPepperDec 30, 2019

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

If it is then it should be cos(theta) d(theta) d(phi) as you say. As the circumference decreases as the altitude angle increases.

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

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

The camera looks along +ve z-axis and the "up" direction is +ve y-axis just like in all other Raysect cameras. However, altitude and azimuth angles are calculated like in horizontal coordinate system, so the direction of z-axis is not the azimuth point but the north point (see the scheme). For the FoV with angles of view (phi, theta), the azimuth angle goes from -phi/2 to phi/2 and the altitude angle goes from -theta/2 to theta/2. The total solid angle observed is 2 * phi * sin(theta/2).

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Ah we are describing the same thing, great.

return rays

cpdef double _pixel_sensitivity(self, int x, int y):
return self._sensitivity

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

There is a finite solid angle, that varies per pixel. The solid angle should be included in this calculation. the sensitivity then becomes an effective area.... if a power pipeline is used (which isn't a great idea), everything should then be correctly normalised.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Though we do ignore this for the pinhole camera, so best to follow the same pattern. i.e assume the sampling is being done through an infinitesimal pinhole.

@vsnever

Copy link
Copy Markdown
ContributorAuthor

@vsnever could I make a request that new features are discussed via the issue tracker before implementation and merge request.

Yes, I agree, I should have to open a discussion in the issue tracker before adding any new code. I’m sorry I didn’t do that. The only reason I started a pull request without opening a discussion first is because for me it wasn’t really a new code, I created it back in the summer as a part of ITER synthetic diagnostics as well as some other code I proposed earlier for Cherab.

@vsnever

Copy link
Copy Markdown
ContributorAuthor

I was going to add a camera called LightProbe that performs even sampling over a sphere, with optional range restriction and with configurable mapping to a rectangle.

I’ll try to implement a LightProbe camera class and a couple of mapping classes for simple cases (e.g. equirectangular projection and cylindrical equal-area projection).

@CnlPepper

Copy link
Copy Markdown
Member

Excellent, thanks. Those are the exactly the projections I meant.

@mattngcmattngc assigned CnlPepper and unassigned mattngcJan 1, 2020
@mattngc

Copy link
Copy Markdown
Member

Like where this is going. Alex has a clearer vision for this feature so handing over reviewer-ship.

@CnlPepperCnlPepper removed this from the Release v0.7 milestone Nov 7, 2020
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants

@vsnever@CnlPepper@mattngc
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Add copy buttons to all
 blocks\n(function() {\n function addCopyButtons() {\n document.querySelectorAll('pre code').forEach(function(codeBlock) {\n if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;\n codeBlock.parentElement.setAttribute('data-copy-added', 'true');\n \n var btn = document.createElement('button');\n btn.textContent = 'Copy';\n btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';\n btn.onmouseover = function() { this.style.opacity = '1'; };\n btn.onmouseout = function() { this.style.opacity = '0.7'; };\n btn.onclick = function() {\n navigator.clipboard.writeText(codeBlock.textContent).then(function() {\n btn.textContent = 'Copied!';\n setTimeout(function() { btn.textContent = 'Copy'; }, 1500);\n });\n };\n codeBlock.parentElement.style.position = 'relative';\n codeBlock.parentElement.appendChild(btn);\n });\n }\n \n addCopyButtons();\n \n // Re-run on dynamic content\n var observer = new MutationObserver(addCopyButtons);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Add Copy Buttons to Code Blocks");
}
} catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
})();
(function(){
try {
var __m = "github.com";
var __re = new RegExp('^' + "github\\.com" + '
Skip to content

New field-of-view observer - #337

Open
vsnever wants to merge 1 commit into
raysect:developmentfrom
vsnever:feature/FovCamera
Open

New field-of-view observer#337
vsnever wants to merge 1 commit into
raysect:developmentfrom
vsnever:feature/FovCamera

Conversation

@vsnever

Copy link
Copy Markdown
Contributor

This adds a new 2D observer called FovCamera that launches rays from the observer's origin point over a specified field of view in spherical coordinates. Each pixel of the final image represents a solid angle of collection inside an azimuth-altitude rectangle.
When developing a new diagnostic, before selecting lines of sight, setting the optics, etc. it may be useful to obtain an image in the field of view of that diagnostic as a function of azimuthal and altitudinal angles. VectorCamera can be used for that purpose, however I think that having a dedicated, simpler class is better.
I propose it for Raysect, but if you find it more suitable for Cherab, then I'm not against moving it to Cherab.

mattngc
mattngc previously approved these changes Dec 30, 2019

@mattngcmattngc left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Thanks Vlad for this contrib. Looks good to me. I've done some testing to and works nicely in my use cases. I'd say its ready to merge as is. I'll just leave it up another 2 days in case one of the others wants to comment.

@mattngcmattngc self-assigned this Dec 30, 2019
@mattngcmattngc added this to the Release v0.7 milestone Dec 30, 2019
@CnlPepper

CnlPepper commented Dec 30, 2019

Copy link
Copy Markdown
Member

I was going to add a camera called LightProbe that performs even sampling over a sphere, with optional range restriction and with configurable mapping to a rectangle. Equi-angle sampling would be one of the possible mapping options, as would equi-area. The functionality of the FOVCamera would end up being a subset of the LightProbe. As such I'd prefer we don't merge this unless it is generalised further... i.e. implementing a full light probe.

The mapping would be a plug-able mapping class. The angle restriction would be centred around the +ve Z-axis as per other cameras.

@CnlPepper

Copy link
Copy Markdown
Member

@vsnever could I make a request that new features are discussed via the issue tracker before implementation and merge request. You a producing some great code, however receiving merge requests out of the blue containing new features puts us in a difficult position when those requests clash with planned functionality. To ensure neither your, nor our time is wasted and that there are no hard feelings, we would prefer it if an issue is raised proposing a feature before any merge requests are sent. We can then decide on the approach before generating code.

cdef:
np.ndarray solid_angle1d

solid_angle1d = (pi / 180.) * self.azimuth_delta * (np.sin((pi / 180.) * (self._altitude + 0.5 * self.altitude_delta)) -

@CnlPepperCnlPepperDec 30, 2019

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

This doesn't look right to me. d(SA) = sin(theta) d(theta) d(phi). The shouldn't the surface integral over an element spanning [theta0, theta1] and [phi0, phi1] include a cos term....

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

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

Here, the altitude angle is measured from the equatorial plane, not from the pole (Z-axis is also lies in the equatorial plane, it easier when dealing with a field of view), so d(SA) = cos(theta) d(theta) d(phi).

@CnlPepperCnlPepperDec 30, 2019

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Not sure I followed the description. The raysect standard is for the camera to look along the +ve z-axis, with the "up" direction being +ve y-axis. The altitude here should be the equivalent of the pitch in math.transform.rotate(), while the azimuth should be the yaw. (0, 0) degrees being aligned with the z-axis. Is this what you mean?

@CnlPepperCnlPepperDec 30, 2019

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

If it is then it should be cos(theta) d(theta) d(phi) as you say. As the circumference decreases as the altitude angle increases.

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

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

The camera looks along +ve z-axis and the "up" direction is +ve y-axis just like in all other Raysect cameras. However, altitude and azimuth angles are calculated like in horizontal coordinate system, so the direction of z-axis is not the azimuth point but the north point (see the scheme). For the FoV with angles of view (phi, theta), the azimuth angle goes from -phi/2 to phi/2 and the altitude angle goes from -theta/2 to theta/2. The total solid angle observed is 2 * phi * sin(theta/2).

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Ah we are describing the same thing, great.

return rays

cpdef double _pixel_sensitivity(self, int x, int y):
return self._sensitivity

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

There is a finite solid angle, that varies per pixel. The solid angle should be included in this calculation. the sensitivity then becomes an effective area.... if a power pipeline is used (which isn't a great idea), everything should then be correctly normalised.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Though we do ignore this for the pinhole camera, so best to follow the same pattern. i.e assume the sampling is being done through an infinitesimal pinhole.

@vsnever

Copy link
Copy Markdown
ContributorAuthor

@vsnever could I make a request that new features are discussed via the issue tracker before implementation and merge request.

Yes, I agree, I should have to open a discussion in the issue tracker before adding any new code. I’m sorry I didn’t do that. The only reason I started a pull request without opening a discussion first is because for me it wasn’t really a new code, I created it back in the summer as a part of ITER synthetic diagnostics as well as some other code I proposed earlier for Cherab.

@vsnever

Copy link
Copy Markdown
ContributorAuthor

I was going to add a camera called LightProbe that performs even sampling over a sphere, with optional range restriction and with configurable mapping to a rectangle.

I’ll try to implement a LightProbe camera class and a couple of mapping classes for simple cases (e.g. equirectangular projection and cylindrical equal-area projection).

@CnlPepper

Copy link
Copy Markdown
Member

Excellent, thanks. Those are the exactly the projections I meant.

@mattngcmattngc assigned CnlPepper and unassigned mattngcJan 1, 2020
@mattngc

Copy link
Copy Markdown
Member

Like where this is going. Alex has a clearer vision for this feature so handing over reviewer-ship.

@CnlPepperCnlPepper removed this from the Release v0.7 milestone Nov 7, 2020
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants

@vsnever@CnlPepper@mattngc
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Force GitHub README to respect dark mode\n(function() {\n var style = document.createElement('style');\n style.textContent = '\n .markdown-body {\n color-scheme: dark light;\n }\n .markdown-body pre { background: #161b22 !important; }\n .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; }\n .markdown-body table th, .markdown-body table td { border-color: #30363d !important; }\n .markdown-body img { background: #0d1117; }\n .markdown-body blockquote { border-left-color: #8b949e; }\n .markdown-body hr { border-color: #30363d; }\n ';\n document.head.appendChild(style);\n})();", "GitHub Dark Mode README Fix"); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

New field-of-view observer - #337

Open
vsnever wants to merge 1 commit into
raysect:developmentfrom
vsnever:feature/FovCamera
Open

New field-of-view observer#337
vsnever wants to merge 1 commit into
raysect:developmentfrom
vsnever:feature/FovCamera

Conversation

@vsnever

Copy link
Copy Markdown
Contributor

This adds a new 2D observer called FovCamera that launches rays from the observer's origin point over a specified field of view in spherical coordinates. Each pixel of the final image represents a solid angle of collection inside an azimuth-altitude rectangle.
When developing a new diagnostic, before selecting lines of sight, setting the optics, etc. it may be useful to obtain an image in the field of view of that diagnostic as a function of azimuthal and altitudinal angles. VectorCamera can be used for that purpose, however I think that having a dedicated, simpler class is better.
I propose it for Raysect, but if you find it more suitable for Cherab, then I'm not against moving it to Cherab.

mattngc
mattngc previously approved these changes Dec 30, 2019

@mattngcmattngc left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Thanks Vlad for this contrib. Looks good to me. I've done some testing to and works nicely in my use cases. I'd say its ready to merge as is. I'll just leave it up another 2 days in case one of the others wants to comment.

@mattngcmattngc self-assigned this Dec 30, 2019
@mattngcmattngc added this to the Release v0.7 milestone Dec 30, 2019
@CnlPepper

CnlPepper commented Dec 30, 2019

Copy link
Copy Markdown
Member

I was going to add a camera called LightProbe that performs even sampling over a sphere, with optional range restriction and with configurable mapping to a rectangle. Equi-angle sampling would be one of the possible mapping options, as would equi-area. The functionality of the FOVCamera would end up being a subset of the LightProbe. As such I'd prefer we don't merge this unless it is generalised further... i.e. implementing a full light probe.

The mapping would be a plug-able mapping class. The angle restriction would be centred around the +ve Z-axis as per other cameras.

@CnlPepper

Copy link
Copy Markdown
Member

@vsnever could I make a request that new features are discussed via the issue tracker before implementation and merge request. You a producing some great code, however receiving merge requests out of the blue containing new features puts us in a difficult position when those requests clash with planned functionality. To ensure neither your, nor our time is wasted and that there are no hard feelings, we would prefer it if an issue is raised proposing a feature before any merge requests are sent. We can then decide on the approach before generating code.

cdef:
np.ndarray solid_angle1d

solid_angle1d = (pi / 180.) * self.azimuth_delta * (np.sin((pi / 180.) * (self._altitude + 0.5 * self.altitude_delta)) -

@CnlPepperCnlPepperDec 30, 2019

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

This doesn't look right to me. d(SA) = sin(theta) d(theta) d(phi). The shouldn't the surface integral over an element spanning [theta0, theta1] and [phi0, phi1] include a cos term....

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

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

Here, the altitude angle is measured from the equatorial plane, not from the pole (Z-axis is also lies in the equatorial plane, it easier when dealing with a field of view), so d(SA) = cos(theta) d(theta) d(phi).

@CnlPepperCnlPepperDec 30, 2019

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Not sure I followed the description. The raysect standard is for the camera to look along the +ve z-axis, with the "up" direction being +ve y-axis. The altitude here should be the equivalent of the pitch in math.transform.rotate(), while the azimuth should be the yaw. (0, 0) degrees being aligned with the z-axis. Is this what you mean?

@CnlPepperCnlPepperDec 30, 2019

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

If it is then it should be cos(theta) d(theta) d(phi) as you say. As the circumference decreases as the altitude angle increases.

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

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

The camera looks along +ve z-axis and the "up" direction is +ve y-axis just like in all other Raysect cameras. However, altitude and azimuth angles are calculated like in horizontal coordinate system, so the direction of z-axis is not the azimuth point but the north point (see the scheme). For the FoV with angles of view (phi, theta), the azimuth angle goes from -phi/2 to phi/2 and the altitude angle goes from -theta/2 to theta/2. The total solid angle observed is 2 * phi * sin(theta/2).

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Ah we are describing the same thing, great.

return rays

cpdef double _pixel_sensitivity(self, int x, int y):
return self._sensitivity

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

There is a finite solid angle, that varies per pixel. The solid angle should be included in this calculation. the sensitivity then becomes an effective area.... if a power pipeline is used (which isn't a great idea), everything should then be correctly normalised.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Though we do ignore this for the pinhole camera, so best to follow the same pattern. i.e assume the sampling is being done through an infinitesimal pinhole.

@vsnever

Copy link
Copy Markdown
ContributorAuthor

@vsnever could I make a request that new features are discussed via the issue tracker before implementation and merge request.

Yes, I agree, I should have to open a discussion in the issue tracker before adding any new code. I’m sorry I didn’t do that. The only reason I started a pull request without opening a discussion first is because for me it wasn’t really a new code, I created it back in the summer as a part of ITER synthetic diagnostics as well as some other code I proposed earlier for Cherab.

@vsnever

Copy link
Copy Markdown
ContributorAuthor

I was going to add a camera called LightProbe that performs even sampling over a sphere, with optional range restriction and with configurable mapping to a rectangle.

I’ll try to implement a LightProbe camera class and a couple of mapping classes for simple cases (e.g. equirectangular projection and cylindrical equal-area projection).

@CnlPepper

Copy link
Copy Markdown
Member

Excellent, thanks. Those are the exactly the projections I meant.

@mattngcmattngc assigned CnlPepper and unassigned mattngcJan 1, 2020
@mattngc

Copy link
Copy Markdown
Member

Like where this is going. Alex has a clearer vision for this feature so handing over reviewer-ship.

@CnlPepperCnlPepper removed this from the Release v0.7 milestone Nov 7, 2020
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants

@vsnever@CnlPepper@mattngc
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Highlight search terms from Google/DuckDuckGo/Bing referrer\n(function() {\n var ref = document.referrer;\n var terms = [];\n \n if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) {\n var url = new URL(ref);\n var q = url.searchParams.get('q') || url.searchParams.get('p');\n if (q) {\n terms = q.split(/\\s+/).filter(function(t) { return t.length > 2; });\n }\n }\n \n if (terms.length === 0) return;\n \n var style = document.createElement('style');\n style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }';\n document.head.appendChild(style);\n \n function highlight(node) {\n if (node.nodeType === 3) { // text node\n var text = node.textContent;\n var found = false;\n terms.forEach(function(term) {\n var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\') + ')', 'gi');\n if (regex.test(text)) {\n found = true;\n var frag = document.createDocumentFragment();\n var parts = text.split(regex);\n parts.forEach(function(part, i) {\n if (i % 2 === 0) {\n frag.appendChild(document.createTextNode(part));\n } else {\n var span = document.createElement('span');\n span.className = 'userscript-highlight';\n span.textContent = part;\n frag.appendChild(span);\n }\n });\n node.parentNode.replaceChild(frag, node);\n }\n });\n } else if (node.nodeType === 1 && node.childNodes) { // element\n var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT'];\n if (!skipTags.includes(node.tagName)) {\n Array.from(node.childNodes).forEach(highlight);\n }\n }\n }\n \n highlight(document.body);\n \n // Re-highlight on dynamic content\n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1 || node.nodeType === 3) highlight(node);\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Highlight Search Terms"); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

New field-of-view observer - #337

Open
vsnever wants to merge 1 commit into
raysect:developmentfrom
vsnever:feature/FovCamera
Open

New field-of-view observer#337
vsnever wants to merge 1 commit into
raysect:developmentfrom
vsnever:feature/FovCamera

Conversation

@vsnever

Copy link
Copy Markdown
Contributor

This adds a new 2D observer called FovCamera that launches rays from the observer's origin point over a specified field of view in spherical coordinates. Each pixel of the final image represents a solid angle of collection inside an azimuth-altitude rectangle.
When developing a new diagnostic, before selecting lines of sight, setting the optics, etc. it may be useful to obtain an image in the field of view of that diagnostic as a function of azimuthal and altitudinal angles. VectorCamera can be used for that purpose, however I think that having a dedicated, simpler class is better.
I propose it for Raysect, but if you find it more suitable for Cherab, then I'm not against moving it to Cherab.

mattngc
mattngc previously approved these changes Dec 30, 2019

@mattngcmattngc left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Thanks Vlad for this contrib. Looks good to me. I've done some testing to and works nicely in my use cases. I'd say its ready to merge as is. I'll just leave it up another 2 days in case one of the others wants to comment.

@mattngcmattngc self-assigned this Dec 30, 2019
@mattngcmattngc added this to the Release v0.7 milestone Dec 30, 2019
@CnlPepper

CnlPepper commented Dec 30, 2019

Copy link
Copy Markdown
Member

I was going to add a camera called LightProbe that performs even sampling over a sphere, with optional range restriction and with configurable mapping to a rectangle. Equi-angle sampling would be one of the possible mapping options, as would equi-area. The functionality of the FOVCamera would end up being a subset of the LightProbe. As such I'd prefer we don't merge this unless it is generalised further... i.e. implementing a full light probe.

The mapping would be a plug-able mapping class. The angle restriction would be centred around the +ve Z-axis as per other cameras.

@CnlPepper

Copy link
Copy Markdown
Member

@vsnever could I make a request that new features are discussed via the issue tracker before implementation and merge request. You a producing some great code, however receiving merge requests out of the blue containing new features puts us in a difficult position when those requests clash with planned functionality. To ensure neither your, nor our time is wasted and that there are no hard feelings, we would prefer it if an issue is raised proposing a feature before any merge requests are sent. We can then decide on the approach before generating code.

cdef:
np.ndarray solid_angle1d

solid_angle1d = (pi / 180.) * self.azimuth_delta * (np.sin((pi / 180.) * (self._altitude + 0.5 * self.altitude_delta)) -

@CnlPepperCnlPepperDec 30, 2019

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

This doesn't look right to me. d(SA) = sin(theta) d(theta) d(phi). The shouldn't the surface integral over an element spanning [theta0, theta1] and [phi0, phi1] include a cos term....

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

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

Here, the altitude angle is measured from the equatorial plane, not from the pole (Z-axis is also lies in the equatorial plane, it easier when dealing with a field of view), so d(SA) = cos(theta) d(theta) d(phi).

@CnlPepperCnlPepperDec 30, 2019

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Not sure I followed the description. The raysect standard is for the camera to look along the +ve z-axis, with the "up" direction being +ve y-axis. The altitude here should be the equivalent of the pitch in math.transform.rotate(), while the azimuth should be the yaw. (0, 0) degrees being aligned with the z-axis. Is this what you mean?

@CnlPepperCnlPepperDec 30, 2019

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

If it is then it should be cos(theta) d(theta) d(phi) as you say. As the circumference decreases as the altitude angle increases.

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

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

The camera looks along +ve z-axis and the "up" direction is +ve y-axis just like in all other Raysect cameras. However, altitude and azimuth angles are calculated like in horizontal coordinate system, so the direction of z-axis is not the azimuth point but the north point (see the scheme). For the FoV with angles of view (phi, theta), the azimuth angle goes from -phi/2 to phi/2 and the altitude angle goes from -theta/2 to theta/2. The total solid angle observed is 2 * phi * sin(theta/2).

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Ah we are describing the same thing, great.

return rays

cpdef double _pixel_sensitivity(self, int x, int y):
return self._sensitivity

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

There is a finite solid angle, that varies per pixel. The solid angle should be included in this calculation. the sensitivity then becomes an effective area.... if a power pipeline is used (which isn't a great idea), everything should then be correctly normalised.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Though we do ignore this for the pinhole camera, so best to follow the same pattern. i.e assume the sampling is being done through an infinitesimal pinhole.

@vsnever

Copy link
Copy Markdown
ContributorAuthor

@vsnever could I make a request that new features are discussed via the issue tracker before implementation and merge request.

Yes, I agree, I should have to open a discussion in the issue tracker before adding any new code. I’m sorry I didn’t do that. The only reason I started a pull request without opening a discussion first is because for me it wasn’t really a new code, I created it back in the summer as a part of ITER synthetic diagnostics as well as some other code I proposed earlier for Cherab.

@vsnever

Copy link
Copy Markdown
ContributorAuthor

I was going to add a camera called LightProbe that performs even sampling over a sphere, with optional range restriction and with configurable mapping to a rectangle.

I’ll try to implement a LightProbe camera class and a couple of mapping classes for simple cases (e.g. equirectangular projection and cylindrical equal-area projection).

@CnlPepper

Copy link
Copy Markdown
Member

Excellent, thanks. Those are the exactly the projections I meant.

@mattngcmattngc assigned CnlPepper and unassigned mattngcJan 1, 2020
@mattngc

Copy link
Copy Markdown
Member

Like where this is going. Alex has a clearer vision for this feature so handing over reviewer-ship.

@CnlPepperCnlPepper removed this from the Release v0.7 milestone Nov 7, 2020
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants

@vsnever@CnlPepper@mattngc
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Strip utm_, fbclid, gclid, etc. from all links on page\n(function() {\n var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content',\n 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid',\n 'ref', 'ref_src', 'source', 'medium', 'campaign'];\n \n function cleanUrl(url) {\n try {\n var u = new URL(url, window.location.origin);\n var changed = false;\n trackingParams.forEach(function(p) {\n if (u.searchParams.has(p)) {\n u.searchParams.delete(p);\n changed = true;\n }\n });\n return changed ? u.toString() : url;\n } catch (e) {\n return url;\n }\n }\n \n function cleanLinks() {\n document.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n \n cleanLinks();\n \n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1) {\n if (node.tagName === 'A') cleanLinks();\n node.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Remove Tracking Parameters from Links"); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + '
Skip to content

New field-of-view observer - #337

Open
vsnever wants to merge 1 commit into
raysect:developmentfrom
vsnever:feature/FovCamera
Open

New field-of-view observer#337
vsnever wants to merge 1 commit into
raysect:developmentfrom
vsnever:feature/FovCamera

Conversation

@vsnever

Copy link
Copy Markdown
Contributor

This adds a new 2D observer called FovCamera that launches rays from the observer's origin point over a specified field of view in spherical coordinates. Each pixel of the final image represents a solid angle of collection inside an azimuth-altitude rectangle.
When developing a new diagnostic, before selecting lines of sight, setting the optics, etc. it may be useful to obtain an image in the field of view of that diagnostic as a function of azimuthal and altitudinal angles. VectorCamera can be used for that purpose, however I think that having a dedicated, simpler class is better.
I propose it for Raysect, but if you find it more suitable for Cherab, then I'm not against moving it to Cherab.

mattngc
mattngc previously approved these changes Dec 30, 2019

@mattngcmattngc left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Thanks Vlad for this contrib. Looks good to me. I've done some testing to and works nicely in my use cases. I'd say its ready to merge as is. I'll just leave it up another 2 days in case one of the others wants to comment.

@mattngcmattngc self-assigned this Dec 30, 2019
@mattngcmattngc added this to the Release v0.7 milestone Dec 30, 2019
@CnlPepper

CnlPepper commented Dec 30, 2019

Copy link
Copy Markdown
Member

I was going to add a camera called LightProbe that performs even sampling over a sphere, with optional range restriction and with configurable mapping to a rectangle. Equi-angle sampling would be one of the possible mapping options, as would equi-area. The functionality of the FOVCamera would end up being a subset of the LightProbe. As such I'd prefer we don't merge this unless it is generalised further... i.e. implementing a full light probe.

The mapping would be a plug-able mapping class. The angle restriction would be centred around the +ve Z-axis as per other cameras.

@CnlPepper

Copy link
Copy Markdown
Member

@vsnever could I make a request that new features are discussed via the issue tracker before implementation and merge request. You a producing some great code, however receiving merge requests out of the blue containing new features puts us in a difficult position when those requests clash with planned functionality. To ensure neither your, nor our time is wasted and that there are no hard feelings, we would prefer it if an issue is raised proposing a feature before any merge requests are sent. We can then decide on the approach before generating code.

cdef:
np.ndarray solid_angle1d

solid_angle1d = (pi / 180.) * self.azimuth_delta * (np.sin((pi / 180.) * (self._altitude + 0.5 * self.altitude_delta)) -

@CnlPepperCnlPepperDec 30, 2019

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

This doesn't look right to me. d(SA) = sin(theta) d(theta) d(phi). The shouldn't the surface integral over an element spanning [theta0, theta1] and [phi0, phi1] include a cos term....

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

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

Here, the altitude angle is measured from the equatorial plane, not from the pole (Z-axis is also lies in the equatorial plane, it easier when dealing with a field of view), so d(SA) = cos(theta) d(theta) d(phi).

@CnlPepperCnlPepperDec 30, 2019

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Not sure I followed the description. The raysect standard is for the camera to look along the +ve z-axis, with the "up" direction being +ve y-axis. The altitude here should be the equivalent of the pitch in math.transform.rotate(), while the azimuth should be the yaw. (0, 0) degrees being aligned with the z-axis. Is this what you mean?

@CnlPepperCnlPepperDec 30, 2019

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

If it is then it should be cos(theta) d(theta) d(phi) as you say. As the circumference decreases as the altitude angle increases.

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

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

The camera looks along +ve z-axis and the "up" direction is +ve y-axis just like in all other Raysect cameras. However, altitude and azimuth angles are calculated like in horizontal coordinate system, so the direction of z-axis is not the azimuth point but the north point (see the scheme). For the FoV with angles of view (phi, theta), the azimuth angle goes from -phi/2 to phi/2 and the altitude angle goes from -theta/2 to theta/2. The total solid angle observed is 2 * phi * sin(theta/2).

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Ah we are describing the same thing, great.

return rays

cpdef double _pixel_sensitivity(self, int x, int y):
return self._sensitivity

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

There is a finite solid angle, that varies per pixel. The solid angle should be included in this calculation. the sensitivity then becomes an effective area.... if a power pipeline is used (which isn't a great idea), everything should then be correctly normalised.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Though we do ignore this for the pinhole camera, so best to follow the same pattern. i.e assume the sampling is being done through an infinitesimal pinhole.

@vsnever

Copy link
Copy Markdown
ContributorAuthor

@vsnever could I make a request that new features are discussed via the issue tracker before implementation and merge request.

Yes, I agree, I should have to open a discussion in the issue tracker before adding any new code. I’m sorry I didn’t do that. The only reason I started a pull request without opening a discussion first is because for me it wasn’t really a new code, I created it back in the summer as a part of ITER synthetic diagnostics as well as some other code I proposed earlier for Cherab.

@vsnever

Copy link
Copy Markdown
ContributorAuthor

I was going to add a camera called LightProbe that performs even sampling over a sphere, with optional range restriction and with configurable mapping to a rectangle.

I’ll try to implement a LightProbe camera class and a couple of mapping classes for simple cases (e.g. equirectangular projection and cylindrical equal-area projection).

@CnlPepper

Copy link
Copy Markdown
Member

Excellent, thanks. Those are the exactly the projections I meant.

@mattngcmattngc assigned CnlPepper and unassigned mattngcJan 1, 2020
@mattngc

Copy link
Copy Markdown
Member

Like where this is going. Alex has a clearer vision for this feature so handing over reviewer-ship.

@CnlPepperCnlPepper removed this from the Release v0.7 milestone Nov 7, 2020
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants

@vsnever@CnlPepper@mattngc
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Auto-enable theater mode on YouTube\n(function() {\n function tryTheater() {\n var btn = document.querySelector('button[aria-label=\"Theater mode\"], ytd-player #player button[title=\"Theater mode\"]');\n if (btn && !btn.classList.contains('activated')) {\n btn.click();\n }\n }\n \n // Try immediately\n tryTheater();\n \n // Try after navigation (SPA)\n var lastUrl = location.href;\n setInterval(function() {\n if (location.href !== lastUrl) {\n lastUrl = location.href;\n setTimeout(tryTheater, 500);\n }\n }, 1000);\n \n // Also try on player load\n var observer = new MutationObserver(tryTheater);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "YouTube Theater Mode Default"); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

New field-of-view observer - #337

Open
vsnever wants to merge 1 commit into
raysect:developmentfrom
vsnever:feature/FovCamera
Open

New field-of-view observer#337
vsnever wants to merge 1 commit into
raysect:developmentfrom
vsnever:feature/FovCamera

Conversation

@vsnever

Copy link
Copy Markdown
Contributor

This adds a new 2D observer called FovCamera that launches rays from the observer's origin point over a specified field of view in spherical coordinates. Each pixel of the final image represents a solid angle of collection inside an azimuth-altitude rectangle.
When developing a new diagnostic, before selecting lines of sight, setting the optics, etc. it may be useful to obtain an image in the field of view of that diagnostic as a function of azimuthal and altitudinal angles. VectorCamera can be used for that purpose, however I think that having a dedicated, simpler class is better.
I propose it for Raysect, but if you find it more suitable for Cherab, then I'm not against moving it to Cherab.

mattngc
mattngc previously approved these changes Dec 30, 2019

@mattngcmattngc left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Thanks Vlad for this contrib. Looks good to me. I've done some testing to and works nicely in my use cases. I'd say its ready to merge as is. I'll just leave it up another 2 days in case one of the others wants to comment.

@mattngcmattngc self-assigned this Dec 30, 2019
@mattngcmattngc added this to the Release v0.7 milestone Dec 30, 2019
@CnlPepper

CnlPepper commented Dec 30, 2019

Copy link
Copy Markdown
Member

I was going to add a camera called LightProbe that performs even sampling over a sphere, with optional range restriction and with configurable mapping to a rectangle. Equi-angle sampling would be one of the possible mapping options, as would equi-area. The functionality of the FOVCamera would end up being a subset of the LightProbe. As such I'd prefer we don't merge this unless it is generalised further... i.e. implementing a full light probe.

The mapping would be a plug-able mapping class. The angle restriction would be centred around the +ve Z-axis as per other cameras.

@CnlPepper

Copy link
Copy Markdown
Member

@vsnever could I make a request that new features are discussed via the issue tracker before implementation and merge request. You a producing some great code, however receiving merge requests out of the blue containing new features puts us in a difficult position when those requests clash with planned functionality. To ensure neither your, nor our time is wasted and that there are no hard feelings, we would prefer it if an issue is raised proposing a feature before any merge requests are sent. We can then decide on the approach before generating code.

cdef:
np.ndarray solid_angle1d

solid_angle1d = (pi / 180.) * self.azimuth_delta * (np.sin((pi / 180.) * (self._altitude + 0.5 * self.altitude_delta)) -

@CnlPepperCnlPepperDec 30, 2019

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

This doesn't look right to me. d(SA) = sin(theta) d(theta) d(phi). The shouldn't the surface integral over an element spanning [theta0, theta1] and [phi0, phi1] include a cos term....

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

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

Here, the altitude angle is measured from the equatorial plane, not from the pole (Z-axis is also lies in the equatorial plane, it easier when dealing with a field of view), so d(SA) = cos(theta) d(theta) d(phi).

@CnlPepperCnlPepperDec 30, 2019

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Not sure I followed the description. The raysect standard is for the camera to look along the +ve z-axis, with the "up" direction being +ve y-axis. The altitude here should be the equivalent of the pitch in math.transform.rotate(), while the azimuth should be the yaw. (0, 0) degrees being aligned with the z-axis. Is this what you mean?

@CnlPepperCnlPepperDec 30, 2019

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

If it is then it should be cos(theta) d(theta) d(phi) as you say. As the circumference decreases as the altitude angle increases.

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

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

The camera looks along +ve z-axis and the "up" direction is +ve y-axis just like in all other Raysect cameras. However, altitude and azimuth angles are calculated like in horizontal coordinate system, so the direction of z-axis is not the azimuth point but the north point (see the scheme). For the FoV with angles of view (phi, theta), the azimuth angle goes from -phi/2 to phi/2 and the altitude angle goes from -theta/2 to theta/2. The total solid angle observed is 2 * phi * sin(theta/2).

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Ah we are describing the same thing, great.

return rays

cpdef double _pixel_sensitivity(self, int x, int y):
return self._sensitivity

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

There is a finite solid angle, that varies per pixel. The solid angle should be included in this calculation. the sensitivity then becomes an effective area.... if a power pipeline is used (which isn't a great idea), everything should then be correctly normalised.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Though we do ignore this for the pinhole camera, so best to follow the same pattern. i.e assume the sampling is being done through an infinitesimal pinhole.

@vsnever

Copy link
Copy Markdown
ContributorAuthor

@vsnever could I make a request that new features are discussed via the issue tracker before implementation and merge request.

Yes, I agree, I should have to open a discussion in the issue tracker before adding any new code. I’m sorry I didn’t do that. The only reason I started a pull request without opening a discussion first is because for me it wasn’t really a new code, I created it back in the summer as a part of ITER synthetic diagnostics as well as some other code I proposed earlier for Cherab.

@vsnever

Copy link
Copy Markdown
ContributorAuthor

I was going to add a camera called LightProbe that performs even sampling over a sphere, with optional range restriction and with configurable mapping to a rectangle.

I’ll try to implement a LightProbe camera class and a couple of mapping classes for simple cases (e.g. equirectangular projection and cylindrical equal-area projection).

@CnlPepper

Copy link
Copy Markdown
Member

Excellent, thanks. Those are the exactly the projections I meant.

@mattngcmattngc assigned CnlPepper and unassigned mattngcJan 1, 2020
@mattngc

Copy link
Copy Markdown
Member

Like where this is going. Alex has a clearer vision for this feature so handing over reviewer-ship.

@CnlPepperCnlPepper removed this from the Release v0.7 milestone Nov 7, 2020
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants

@vsnever@CnlPepper@mattngc
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Remove or un-stick sticky/fixed headers that block content\n(function() {\n function unstick() {\n document.querySelectorAll('header, nav, [role=\"banner\"], .header, .navbar, .sticky, .fixed-top, [style*=\"position: fixed\"], [style*=\"position:sticky\"]').forEach(function(el) {\n if (el.style.position === 'fixed' || el.style.position === 'sticky' || \n getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') {\n el.style.position = 'static';\n el.style.top = 'auto';\n el.style.zIndex = 'auto';\n }\n });\n }\n \n unstick();\n \n var observer = new MutationObserver(unstick);\n observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] });\n})();", "Kill Sticky Headers"); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

New field-of-view observer - #337

Open
vsnever wants to merge 1 commit into
raysect:developmentfrom
vsnever:feature/FovCamera
Open

New field-of-view observer#337
vsnever wants to merge 1 commit into
raysect:developmentfrom
vsnever:feature/FovCamera

Conversation

@vsnever

Copy link
Copy Markdown
Contributor

This adds a new 2D observer called FovCamera that launches rays from the observer's origin point over a specified field of view in spherical coordinates. Each pixel of the final image represents a solid angle of collection inside an azimuth-altitude rectangle.
When developing a new diagnostic, before selecting lines of sight, setting the optics, etc. it may be useful to obtain an image in the field of view of that diagnostic as a function of azimuthal and altitudinal angles. VectorCamera can be used for that purpose, however I think that having a dedicated, simpler class is better.
I propose it for Raysect, but if you find it more suitable for Cherab, then I'm not against moving it to Cherab.

mattngc
mattngc previously approved these changes Dec 30, 2019

@mattngcmattngc left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Thanks Vlad for this contrib. Looks good to me. I've done some testing to and works nicely in my use cases. I'd say its ready to merge as is. I'll just leave it up another 2 days in case one of the others wants to comment.

@mattngcmattngc self-assigned this Dec 30, 2019
@mattngcmattngc added this to the Release v0.7 milestone Dec 30, 2019
@CnlPepper

CnlPepper commented Dec 30, 2019

Copy link
Copy Markdown
Member

I was going to add a camera called LightProbe that performs even sampling over a sphere, with optional range restriction and with configurable mapping to a rectangle. Equi-angle sampling would be one of the possible mapping options, as would equi-area. The functionality of the FOVCamera would end up being a subset of the LightProbe. As such I'd prefer we don't merge this unless it is generalised further... i.e. implementing a full light probe.

The mapping would be a plug-able mapping class. The angle restriction would be centred around the +ve Z-axis as per other cameras.

@CnlPepper

Copy link
Copy Markdown
Member

@vsnever could I make a request that new features are discussed via the issue tracker before implementation and merge request. You a producing some great code, however receiving merge requests out of the blue containing new features puts us in a difficult position when those requests clash with planned functionality. To ensure neither your, nor our time is wasted and that there are no hard feelings, we would prefer it if an issue is raised proposing a feature before any merge requests are sent. We can then decide on the approach before generating code.

cdef:
np.ndarray solid_angle1d

solid_angle1d = (pi / 180.) * self.azimuth_delta * (np.sin((pi / 180.) * (self._altitude + 0.5 * self.altitude_delta)) -

@CnlPepperCnlPepperDec 30, 2019

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

This doesn't look right to me. d(SA) = sin(theta) d(theta) d(phi). The shouldn't the surface integral over an element spanning [theta0, theta1] and [phi0, phi1] include a cos term....

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

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

Here, the altitude angle is measured from the equatorial plane, not from the pole (Z-axis is also lies in the equatorial plane, it easier when dealing with a field of view), so d(SA) = cos(theta) d(theta) d(phi).

@CnlPepperCnlPepperDec 30, 2019

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Not sure I followed the description. The raysect standard is for the camera to look along the +ve z-axis, with the "up" direction being +ve y-axis. The altitude here should be the equivalent of the pitch in math.transform.rotate(), while the azimuth should be the yaw. (0, 0) degrees being aligned with the z-axis. Is this what you mean?

@CnlPepperCnlPepperDec 30, 2019

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

If it is then it should be cos(theta) d(theta) d(phi) as you say. As the circumference decreases as the altitude angle increases.

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

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

The camera looks along +ve z-axis and the "up" direction is +ve y-axis just like in all other Raysect cameras. However, altitude and azimuth angles are calculated like in horizontal coordinate system, so the direction of z-axis is not the azimuth point but the north point (see the scheme). For the FoV with angles of view (phi, theta), the azimuth angle goes from -phi/2 to phi/2 and the altitude angle goes from -theta/2 to theta/2. The total solid angle observed is 2 * phi * sin(theta/2).

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Ah we are describing the same thing, great.

return rays

cpdef double _pixel_sensitivity(self, int x, int y):
return self._sensitivity

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

There is a finite solid angle, that varies per pixel. The solid angle should be included in this calculation. the sensitivity then becomes an effective area.... if a power pipeline is used (which isn't a great idea), everything should then be correctly normalised.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Though we do ignore this for the pinhole camera, so best to follow the same pattern. i.e assume the sampling is being done through an infinitesimal pinhole.

@vsnever

Copy link
Copy Markdown
ContributorAuthor

@vsnever could I make a request that new features are discussed via the issue tracker before implementation and merge request.

Yes, I agree, I should have to open a discussion in the issue tracker before adding any new code. I’m sorry I didn’t do that. The only reason I started a pull request without opening a discussion first is because for me it wasn’t really a new code, I created it back in the summer as a part of ITER synthetic diagnostics as well as some other code I proposed earlier for Cherab.

@vsnever

Copy link
Copy Markdown
ContributorAuthor

I was going to add a camera called LightProbe that performs even sampling over a sphere, with optional range restriction and with configurable mapping to a rectangle.

I’ll try to implement a LightProbe camera class and a couple of mapping classes for simple cases (e.g. equirectangular projection and cylindrical equal-area projection).

@CnlPepper

Copy link
Copy Markdown
Member

Excellent, thanks. Those are the exactly the projections I meant.

@mattngcmattngc assigned CnlPepper and unassigned mattngcJan 1, 2020
@mattngc

Copy link
Copy Markdown
Member

Like where this is going. Alex has a clearer vision for this feature so handing over reviewer-ship.

@CnlPepperCnlPepper removed this from the Release v0.7 milestone Nov 7, 2020
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants

@vsnever@CnlPepper@mattngc
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Universal Dark Mode - works on any site\n(function() {\n var enabled = true;\n \n function applyDarkMode() {\n if (!enabled) return;\n \n // Create style element if it doesn't exist\n var style = document.getElementById('universal-dark-mode-style');\n if (!style) {\n style = document.createElement('style');\n style.id = 'universal-dark-mode-style';\n document.head.appendChild(style);\n }\n \n // Dark mode CSS - inverts colors but preserves images/video\n style.textContent = '\n /* Invert everything except media */\n html {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #1a1a2e !important;\n }\n \n /* Restore images, videos, iframes, canvas */\n img, video, iframe, canvas, svg, picture, [style*=\"background-image\"] {\n filter: invert(1) hue-rotate(180deg) !important;\n }\n \n /* Preserve specific elements that should not be inverted */\n .no-dark-mode, .no-dark-mode *,\n [data-theme=\"light\"], [data-theme=\"light\"],\n .ace_editor, .ace_editor *,\n .CodeMirror, .CodeMirror *,\n .monaco-editor, .monaco-editor *,\n .markdown-body pre, .markdown-body pre *,\n .highlight, .highlight *,\n pre code, pre code * {\n filter: none !important;\n }\n \n /* Fix common UI elements */\n .modal, .popup, .dropdown-menu, .tooltip, .popover {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #2d2d44 !important;\n border-color: #444 !important;\n }\n \n /* Scrollbars */\n ::-webkit-scrollbar { background: #1a1a2e !important; }\n ::-webkit-scrollbar-thumb { background: #444 !important; }\n ::-webkit-scrollbar-thumb:hover { background: #555 !important; }\n \n /* Selection */\n ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ';\n }\n \n function removeDarkMode() {\n var style = document.getElementById('universal-dark-mode-style');\n if (style) style.remove();\n }\n \n // Toggle with Alt+Shift+D\n document.addEventListener('keydown', function(e) {\n if (e.altKey && e.shiftKey && e.key === 'D') {\n e.preventDefault();\n enabled = !enabled;\n if (enabled) {\n applyDarkMode();\n console.log('[Universal Dark Mode] Enabled');\n } else {\n removeDarkMode();\n console.log('[Universal Dark Mode] Disabled');\n }\n }\n });\n \n // Apply on load\n applyDarkMode();\n \n // Re-apply on dynamic content\n var observer = new MutationObserver(function(mutations) {\n if (enabled && !document.getElementById('universal-dark-mode-style')) {\n applyDarkMode();\n }\n });\n observer.observe(document.head, { childList: true });\n \n console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle');\n})();", "Universal Dark Mode"); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })();
Skip to content

New field-of-view observer - #337

Open
vsnever wants to merge 1 commit into
raysect:developmentfrom
vsnever:feature/FovCamera
Open

New field-of-view observer#337
vsnever wants to merge 1 commit into
raysect:developmentfrom
vsnever:feature/FovCamera

Conversation

@vsnever

Copy link
Copy Markdown
Contributor

This adds a new 2D observer called FovCamera that launches rays from the observer's origin point over a specified field of view in spherical coordinates. Each pixel of the final image represents a solid angle of collection inside an azimuth-altitude rectangle.
When developing a new diagnostic, before selecting lines of sight, setting the optics, etc. it may be useful to obtain an image in the field of view of that diagnostic as a function of azimuthal and altitudinal angles. VectorCamera can be used for that purpose, however I think that having a dedicated, simpler class is better.
I propose it for Raysect, but if you find it more suitable for Cherab, then I'm not against moving it to Cherab.

mattngc
mattngc previously approved these changes Dec 30, 2019

@mattngcmattngc left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Thanks Vlad for this contrib. Looks good to me. I've done some testing to and works nicely in my use cases. I'd say its ready to merge as is. I'll just leave it up another 2 days in case one of the others wants to comment.

@mattngcmattngc self-assigned this Dec 30, 2019
@mattngcmattngc added this to the Release v0.7 milestone Dec 30, 2019
@CnlPepper

CnlPepper commented Dec 30, 2019

Copy link
Copy Markdown
Member

I was going to add a camera called LightProbe that performs even sampling over a sphere, with optional range restriction and with configurable mapping to a rectangle. Equi-angle sampling would be one of the possible mapping options, as would equi-area. The functionality of the FOVCamera would end up being a subset of the LightProbe. As such I'd prefer we don't merge this unless it is generalised further... i.e. implementing a full light probe.

The mapping would be a plug-able mapping class. The angle restriction would be centred around the +ve Z-axis as per other cameras.

@CnlPepper

Copy link
Copy Markdown
Member

@vsnever could I make a request that new features are discussed via the issue tracker before implementation and merge request. You a producing some great code, however receiving merge requests out of the blue containing new features puts us in a difficult position when those requests clash with planned functionality. To ensure neither your, nor our time is wasted and that there are no hard feelings, we would prefer it if an issue is raised proposing a feature before any merge requests are sent. We can then decide on the approach before generating code.

cdef:
np.ndarray solid_angle1d

solid_angle1d = (pi / 180.) * self.azimuth_delta * (np.sin((pi / 180.) * (self._altitude + 0.5 * self.altitude_delta)) -

@CnlPepperCnlPepperDec 30, 2019

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

This doesn't look right to me. d(SA) = sin(theta) d(theta) d(phi). The shouldn't the surface integral over an element spanning [theta0, theta1] and [phi0, phi1] include a cos term....

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

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

Here, the altitude angle is measured from the equatorial plane, not from the pole (Z-axis is also lies in the equatorial plane, it easier when dealing with a field of view), so d(SA) = cos(theta) d(theta) d(phi).

@CnlPepperCnlPepperDec 30, 2019

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Not sure I followed the description. The raysect standard is for the camera to look along the +ve z-axis, with the "up" direction being +ve y-axis. The altitude here should be the equivalent of the pitch in math.transform.rotate(), while the azimuth should be the yaw. (0, 0) degrees being aligned with the z-axis. Is this what you mean?

@CnlPepperCnlPepperDec 30, 2019

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

If it is then it should be cos(theta) d(theta) d(phi) as you say. As the circumference decreases as the altitude angle increases.

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

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

The camera looks along +ve z-axis and the "up" direction is +ve y-axis just like in all other Raysect cameras. However, altitude and azimuth angles are calculated like in horizontal coordinate system, so the direction of z-axis is not the azimuth point but the north point (see the scheme). For the FoV with angles of view (phi, theta), the azimuth angle goes from -phi/2 to phi/2 and the altitude angle goes from -theta/2 to theta/2. The total solid angle observed is 2 * phi * sin(theta/2).

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Ah we are describing the same thing, great.

return rays

cpdef double _pixel_sensitivity(self, int x, int y):
return self._sensitivity

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

There is a finite solid angle, that varies per pixel. The solid angle should be included in this calculation. the sensitivity then becomes an effective area.... if a power pipeline is used (which isn't a great idea), everything should then be correctly normalised.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Though we do ignore this for the pinhole camera, so best to follow the same pattern. i.e assume the sampling is being done through an infinitesimal pinhole.

@vsnever

Copy link
Copy Markdown
ContributorAuthor

@vsnever could I make a request that new features are discussed via the issue tracker before implementation and merge request.

Yes, I agree, I should have to open a discussion in the issue tracker before adding any new code. I’m sorry I didn’t do that. The only reason I started a pull request without opening a discussion first is because for me it wasn’t really a new code, I created it back in the summer as a part of ITER synthetic diagnostics as well as some other code I proposed earlier for Cherab.

@vsnever

Copy link
Copy Markdown
ContributorAuthor

I was going to add a camera called LightProbe that performs even sampling over a sphere, with optional range restriction and with configurable mapping to a rectangle.

I’ll try to implement a LightProbe camera class and a couple of mapping classes for simple cases (e.g. equirectangular projection and cylindrical equal-area projection).

@CnlPepper

Copy link
Copy Markdown
Member

Excellent, thanks. Those are the exactly the projections I meant.

@mattngcmattngc assigned CnlPepper and unassigned mattngcJan 1, 2020
@mattngc

Copy link
Copy Markdown
Member

Like where this is going. Alex has a clearer vision for this feature so handing over reviewer-ship.

@CnlPepperCnlPepper removed this from the Release v0.7 milestone Nov 7, 2020
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants

@vsnever@CnlPepper@mattngc