<!-- 
RSS generated by JIRA (8.3.4#803005-sha1:1f96e09b3c60279a408a2ae47be3c745f571388b) at Sat Feb 10 15:59:12 JST 2024

It is possible to restrict the fields that are returned in this document by specifying the 'field' parameter in your request.
For example, to request only the issue key and summary append 'field=key&field=summary' to the URL of your request.
-->
<rss version="0.92" >
<channel>
    <title>PFS-JIRA</title>
    <link>https://pfspipe.ipmu.jp/jira</link>
    <description>This file is an XML representation of an issue</description>
    <language>en-us</language>    <build-info>
        <version>8.3.4</version>
        <build-number>803005</build-number>
        <build-date>13-09-2019</build-date>
    </build-info>


<item>
            <title>[PIPE2D-872] Expose function resampleKernelImage to python</title>
                <link>https://pfspipe.ipmu.jp/jira/browse/PIPE2D-872</link>
                <project id="10002" key="PIPE2D">DRP 2-D Pipeline</project>
                    <description>&lt;p&gt;It would be useful to expose the&#160;resampleKernelImage function from &lt;a href=&quot;https://github.com/Subaru-PFS/drp_stella/blob/master/src/SpectralPsf.cc.&quot; class=&quot;external-link&quot; rel=&quot;nofollow&quot;&gt;https://github.com/Subaru-PFS/drp_stella/blob/master/src/SpectralPsf.cc.&lt;/a&gt;&#160;This would enable me to use it in my testing and analysis, and to ensure that we are not introducing errors when moving from between analysis of the spots and final implementation in the pipeline.&lt;/p&gt;

&lt;p&gt;Additionally, it would be good to better understand the difference between&#160;resampleKernelImage function and&#160;bin_image function from base LSST code.&lt;/p&gt;</description>
                <environment></environment>
        <key id="16943">PIPE2D-872</key>
            <summary>Expose function resampleKernelImage to python</summary>
                <type id="3" iconUrl="https://pfspipe.ipmu.jp/jira/secure/viewavatar?size=xsmall&amp;avatarId=10518&amp;avatarType=issuetype">Task</type>
                                            <priority id="10000" iconUrl="https://pfspipe.ipmu.jp/jira/images/icons/priorities/medium.svg">Normal</priority>
                        <status id="10002" iconUrl="https://pfspipe.ipmu.jp/jira/images/icons/statuses/generic.png" description="The issue is resolved, reviewed, and merged">Done</status>
                    <statusCategory id="3" key="done" colorName="green"/>
                                    <resolution id="10000">Done</resolution>
                                        <assignee username="price">price</assignee>
                                    <reporter username="ncaplar">ncaplar</reporter>
                        <labels>
                    </labels>
                <created>Mon, 19 Jul 2021 20:07:25 +0000</created>
                <updated>Tue, 3 Aug 2021 20:22:06 +0000</updated>
                            <resolved>Wed, 28 Jul 2021 14:40:22 +0000</resolved>
                                                                        <due></due>
                            <votes>0</votes>
                                    <watches>3</watches>
                                                                <comments>
                            <comment id="21705" author="price" created="Tue, 20 Jul 2021 16:20:41 +0000"  >&lt;p&gt;&lt;tt&gt;lsst.afw.math.binImage&lt;/tt&gt; puts the corner of the input image in the corner of the output image.  &lt;tt&gt;pfs.drp.stella.resampleKernelImage&lt;/tt&gt; puts the center of the input image in the center of the output image. Consider the following example:&lt;/p&gt;
&lt;div class=&quot;code panel&quot; style=&quot;border-width: 1px;&quot;&gt;&lt;div class=&quot;codeContent panelContent&quot;&gt;
&lt;pre class=&quot;code-java&quot;&gt;
&amp;gt;&amp;gt;&amp;gt; &lt;span class=&quot;code-keyword&quot;&gt;import&lt;/span&gt; numpy as np
&amp;gt;&amp;gt;&amp;gt; from lsst.afw.image &lt;span class=&quot;code-keyword&quot;&gt;import&lt;/span&gt; ImageD
&amp;gt;&amp;gt;&amp;gt; from lsst.afw.math &lt;span class=&quot;code-keyword&quot;&gt;import&lt;/span&gt; binImage
&amp;gt;&amp;gt;&amp;gt; from lsst.geom &lt;span class=&quot;code-keyword&quot;&gt;import&lt;/span&gt; Box2I, Point2I, Point2D
&amp;gt;&amp;gt;&amp;gt; from pfs.drp.stella.images &lt;span class=&quot;code-keyword&quot;&gt;import&lt;/span&gt; getIndices, calculateCentroid
&amp;gt;&amp;gt;&amp;gt; from pfs.drp.stella &lt;span class=&quot;code-keyword&quot;&gt;import&lt;/span&gt; resampleKernelImage
&amp;gt;&amp;gt;&amp;gt; binning = 5
&amp;gt;&amp;gt;&amp;gt; box = Box2I(Point2I(-50, -50), Point2I(50, 50))
&amp;gt;&amp;gt;&amp;gt; image = ImageD(box)
&amp;gt;&amp;gt;&amp;gt; xx, yy = getIndices(image.getBBox())
&amp;gt;&amp;gt;&amp;gt; image.array[:] = np.exp(-0.5*(xx**2 + yy**2)/5.43**2)
&amp;gt;&amp;gt;&amp;gt; lsst = binImage(image, binning)
&amp;gt;&amp;gt;&amp;gt; pfs = resampleKernelImage(image, binning, Box2I(Point2I(-10, -10), Point2I(10, 10)))
&amp;gt;&amp;gt;&amp;gt; calculateCentroid(image)
namespace(x=-2.5493701622806684e-18, y=-1.1988050118056573e-17)
&amp;gt;&amp;gt;&amp;gt; calculateCentroid(lsst)
namespace(x=-40.39999999998449, y=-40.39999999998449)
&amp;gt;&amp;gt;&amp;gt; calculateCentroid(pfs)
namespace(x=-9.642385750780955e-18, y=-9.642172334948585e-18)
&lt;/pre&gt;
&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;We created a PSF directly in the center of the input kernel, but &lt;tt&gt;lsst.afw.math.binImage&lt;/tt&gt; moved the center so that it&apos;s not even centered on a pixel. However, &lt;tt&gt;pfs.drp.stella.resampleKernelImage&lt;/tt&gt; puts the center exactly where it should be. In the figure below, the original oversampled &lt;tt&gt;image&lt;/tt&gt; is on the left, the &lt;tt&gt;lsst&lt;/tt&gt; image is in the middle, and the &lt;tt&gt;pfs&lt;/tt&gt; image is on the right.&lt;/p&gt;

&lt;p&gt;&lt;span class=&quot;image-wrap&quot; style=&quot;&quot;&gt;&lt;img src=&quot;https://pfspipe.ipmu.jp/jira/secure/attachment/13947/13947_centering.jpg&quot; style=&quot;border: 0px solid black&quot; /&gt;&lt;/span&gt;&lt;/p&gt;</comment>
                            <comment id="21716" author="ncaplar" created="Thu, 22 Jul 2021 20:22:46 +0000"  >&lt;p&gt;&#160;Could you perhaps comment on the results of the followign example&lt;/p&gt;
&lt;div class=&quot;code panel&quot; style=&quot;border-width: 1px;&quot;&gt;&lt;div class=&quot;codeContent panelContent&quot;&gt;
&lt;pre class=&quot;code-java&quot;&gt;
from lsst.afw.image &lt;span class=&quot;code-keyword&quot;&gt;import&lt;/span&gt; ImageD
from lsst.afw.math &lt;span class=&quot;code-keyword&quot;&gt;import&lt;/span&gt; binImage
from lsst.geom &lt;span class=&quot;code-keyword&quot;&gt;import&lt;/span&gt; Box2I, Point2I, Point2D
from pfs.drp.stella.images &lt;span class=&quot;code-keyword&quot;&gt;import&lt;/span&gt; getIndices, calculateCentroid
from pfs.drp.stella &lt;span class=&quot;code-keyword&quot;&gt;import&lt;/span&gt; resampleKernelImagebinning = 10
box = Box2I(Point2I(-20, -20), Point2I(19, 19))
image = ImageD(box)xx, yy = getIndices(image.getBBox())
image.array[:] =np.ones((40,40))print(&lt;span class=&quot;code-quote&quot;&gt;&apos;calculateCentroid(starting image): &apos;&lt;/span&gt;+str(calculateCentroid(image)))lsst = binImage(image, binning)
pfs = resampleKernelImage(image, binning, Box2I(Point2I(-2, -2), Point2I(1, 1)))
print(&lt;span class=&quot;code-quote&quot;&gt;&apos;calculateCentroid(after binImage + getBBox() minimum ): &apos;&lt;/span&gt;+str(np.array([calculateCentroid(lsst).x,calculateCentroid(lsst).x])+20))
print(&lt;span class=&quot;code-quote&quot;&gt;&apos;calculateCentroid(resampleKernelImage): &apos;&lt;/span&gt;+str(calculateCentroid(pfs)))
plt.figure(figsize=(24,6))plt.subplot(131)
plt.title(&lt;span class=&quot;code-quote&quot;&gt;&apos;via binImage&apos;&lt;/span&gt;)
plt.imshow(lsst.array,origin=&lt;span class=&quot;code-quote&quot;&gt;&apos;lower&apos;&lt;/span&gt;)
plt.axhline(1.5,color=&lt;span class=&quot;code-quote&quot;&gt;&apos;black&apos;&lt;/span&gt;)
plt.axvline(1.5,color=&lt;span class=&quot;code-quote&quot;&gt;&apos;black&apos;&lt;/span&gt;)
cbar=plt.colorbar(fraction=0.046, pad=0.04)plt.subplot(132)
plt.title(&lt;span class=&quot;code-quote&quot;&gt;&apos;via resampleKernelImage&apos;&lt;/span&gt;)
plt.imshow(pfs.array,origin=&lt;span class=&quot;code-quote&quot;&gt;&apos;lower&apos;&lt;/span&gt;)
cbar=plt.colorbar(fraction=0.046, pad=0.04)
plt.axhline(1.6666666666666667,color=&lt;span class=&quot;code-quote&quot;&gt;&apos;black&apos;&lt;/span&gt;)
plt.axvline(1.6666666666666667,color=&lt;span class=&quot;code-quote&quot;&gt;&apos;black&apos;&lt;/span&gt;)&lt;/pre&gt;
&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;which creates the figure `example_constant_array.png` and output of&#160;&lt;/p&gt;
&lt;div class=&quot;code panel&quot; style=&quot;border-width: 1px;&quot;&gt;&lt;div class=&quot;codeContent panelContent&quot;&gt;
&lt;pre class=&quot;code-java&quot;&gt;
calculateCentroid(starting image): namespace(x=-0.5, y=-0.5) 
calculateCentroid(after binImage + getBBox() minimum ): [1.5 1.5] 
calculateCentroid(resampleKernelImage): namespace(x=-0.33333333333333337, y=-0.33333333333333337)&lt;/pre&gt;
&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;In this example I create a constant array, 40x40 which I resample into 4x4, assuming oversampling of 10. This is somewhat more similar to my case in which I always dowsample by integer value (in the previous example 101x101 gets downsampled by factor of 5 into 21x21). I am quite confused by the result from the pfs algorithm, whilst understanding lsst output - I just get constant image again.&lt;br/&gt;
 &#160;&lt;/p&gt;</comment>
                            <comment id="21717" author="ncaplar" created="Thu, 22 Jul 2021 20:55:46 +0000"  >&lt;p&gt;The more I look at the algorithm I think that there is a 0.5 pixel difference between the two which is creating all this confusion, i.e., standard what is the index of pixel question.&lt;/p&gt;</comment>
                            <comment id="21719" author="price" created="Fri, 23 Jul 2021 00:50:39 +0000"  >&lt;p&gt;Because the image is constant, how the output image looks all comes down to how the output pixels overlap the input pixels. For the &lt;tt&gt;lsst&lt;/tt&gt; image, all the output pixels overlap a full 10x10 pixels (the corner maps to the corner, and there&apos;s an exact multiple of the binning in the input image), and so the output image is constant. For the &lt;tt&gt;pfs&lt;/tt&gt; image, not all output pixels are fully populated (the center maps to the center, which means 20,20 physical/&lt;tt&gt;LOCAL&lt;/tt&gt; coordinate in the input maps to 2,2 physical/&lt;tt&gt;LOCAL&lt;/tt&gt; in the output; therefore the column=2 physical/&lt;tt&gt;LOCAL&lt;/tt&gt; output contains contributions from physical input columns 16 to 25 inclusive, so column=1 has 6 to 15, and column=0 has -4 to 5, but it is assumed there is no flux outside the physical bounds of the input image, which means -4 to -1 inclusive are zero, and only 0 through 5 inclusive are populated, hence it only gets 6/10 of the flux), and so the edges have 0.6 of the flux that the main image has, and the bottom-left corner has 0.6^2 = 0.36.&lt;/p&gt;
&lt;div class=&quot;code panel&quot; style=&quot;border-width: 1px;&quot;&gt;&lt;div class=&quot;codeContent panelContent&quot;&gt;
&lt;pre class=&quot;code-java&quot;&gt;
&amp;gt;&amp;gt;&amp;gt; (pfs.array[1,1]/pfs.array[1,0])**-1
0.6
&amp;gt;&amp;gt;&amp;gt; (pfs.array[1,1]/pfs.array[0,0])**-1
0.36
&lt;/pre&gt;
&lt;/div&gt;&lt;/div&gt;</comment>
                            <comment id="21734" author="price" created="Fri, 23 Jul 2021 05:13:10 +0000"  >&lt;p&gt;It occurred to me that your confusion might be due to being unaware of the pixel indexing conventions in use.&lt;/p&gt;

&lt;p&gt;We find it useful to associate images with two related indexing conventions. The first is the &lt;tt&gt;LOCAL&lt;/tt&gt; convention, which you can think of as physical coordinates (not strictly accurate, but good enough for now), where the bottom-left pixel is &lt;tt&gt;0,0&lt;/tt&gt;. For an image of size &lt;tt&gt;4,5&lt;/tt&gt;, the &lt;tt&gt;LOCAL&lt;/tt&gt; coordinates run from &lt;tt&gt;0,0&lt;/tt&gt; to &lt;tt&gt;3,4&lt;/tt&gt; (inclusive). The second is the &lt;tt&gt;PARENT&lt;/tt&gt; convention, or logical coordinates, where the bottom-left pixel is &lt;tt&gt;x0,y0&lt;/tt&gt; (often abbreviated as &lt;tt&gt;xy0&lt;/tt&gt;). For an image of size &lt;tt&gt;4,5&lt;/tt&gt; with an &lt;tt&gt;xy0&lt;/tt&gt; of &lt;tt&gt;2,3&lt;/tt&gt;, the &lt;tt&gt;PARENT&lt;/tt&gt; coordinates run from &lt;tt&gt;2,3&lt;/tt&gt; to &lt;tt&gt;5,7&lt;/tt&gt; (inclusive).&lt;/p&gt;

&lt;p&gt;The &lt;tt&gt;PARENT&lt;/tt&gt; convention is so-named because it&apos;s what we use when we want to refer to the coordinate system of the full image from which we&apos;ve taken a sub-image. We can have an image of size &lt;tt&gt;100,100&lt;/tt&gt;, and from it extract a sub-image, say of size &lt;tt&gt;4,5&lt;/tt&gt; and with an &lt;tt&gt;xy0&lt;/tt&gt; of &lt;tt&gt;2,3&lt;/tt&gt;. When we operate on that sub-image (e.g., &lt;tt&gt;subImage.array&lt;span class=&quot;error&quot;&gt;&amp;#91;y,x&amp;#93;&lt;/span&gt;&lt;/tt&gt;), we use &lt;tt&gt;LOCAL&lt;/tt&gt; coordinates. When we want to talk about where something is in relation to the full image, we use the &lt;tt&gt;PARENT&lt;/tt&gt; coordinates.&lt;/p&gt;

&lt;p&gt;You can use &lt;tt&gt;image.getXY0()&lt;/tt&gt; to get the &lt;tt&gt;xy0&lt;/tt&gt; of the image, and &lt;tt&gt;image.getBBox()&lt;/tt&gt; to get the &lt;tt&gt;PARENT&lt;/tt&gt; bounding box, and &lt;tt&gt;image.getBBox(lsst.afw.image.LOCAL)&lt;/tt&gt; to get the &lt;tt&gt;LOCAL&lt;/tt&gt; bounding box.&lt;/p&gt;

&lt;p&gt;When we have a kernel image (as in a convolution kernel), where the concept of the center is important (because it corresponds to zero shift, or the center of a PSF), we set &lt;tt&gt;xy0&lt;/tt&gt; negative, so that &lt;tt&gt;0,0&lt;/tt&gt; in the &lt;tt&gt;PARENT&lt;/tt&gt; coordinate system is somewhere in the middle of our image (in the &lt;tt&gt;LOCAL&lt;/tt&gt; coordinate system). So an image of size &lt;tt&gt;4,5&lt;/tt&gt; with an &lt;tt&gt;xy0&lt;/tt&gt; of &lt;tt&gt;-2,-3&lt;/tt&gt; has &lt;tt&gt;PARENT&lt;/tt&gt; coordinates that run from &lt;tt&gt;-2,-3&lt;/tt&gt; to &lt;tt&gt;1,1&lt;/tt&gt; (inclusive), and the &quot;center&quot; (the &lt;tt&gt;0,0&lt;/tt&gt; pixel in the &lt;tt&gt;PARENT&lt;/tt&gt; frame) is at &lt;tt&gt;2,3&lt;/tt&gt; in the &lt;tt&gt;LOCAL&lt;/tt&gt; frame.&lt;/p&gt;

&lt;p&gt;So when I say that &quot;the center maps to the center&quot;, it means that the (center of the) &lt;tt&gt;0,0&lt;/tt&gt; pixel in the &lt;tt&gt;PARENT&lt;/tt&gt; frame of the input image maps to the (center of the) &lt;tt&gt;0,0&lt;/tt&gt; pixel in the &lt;tt&gt;PARENT&lt;/tt&gt; frame of the output image, and the borders of the output pixels on the input image follow from that. And &quot;the corner maps to the corner&quot; means that the (corner of the) &lt;tt&gt;0,0&lt;/tt&gt; pixel in the &lt;tt&gt;LOCAL&lt;/tt&gt; frame of the input image maps to the (corner of the) &lt;tt&gt;0,0&lt;/tt&gt; pixel in the &lt;tt&gt;LOCAL&lt;/tt&gt; frame of the output image, and the borders of the output pixels on the input image follow from that.&lt;/p&gt;

&lt;p&gt;One subtlety is that when we&apos;re binning by an even factor, we can&apos;t put the center of the input image directly on the center of the output image without sub-pixel sampling, which we don&apos;t want to do in the rebinning operation. Instead for even binning factors, when we recenter ((&lt;tt&gt;recenterOversampledKernelImage&lt;/tt&gt;) we move the center of the PSF to &lt;tt&gt;-0.5,-0.5&lt;/tt&gt; instead of &lt;tt&gt;0,0&lt;/tt&gt; to account for this.&lt;/p&gt;</comment>
                            <comment id="21746" author="hassan" created="Wed, 28 Jul 2021 11:51:18 +0000"  >&lt;p&gt;Code changes look fine. Minor comment made.&lt;/p&gt;</comment>
                            <comment id="21747" author="ncaplar" created="Wed, 28 Jul 2021 12:49:41 +0000"  >&lt;p&gt;I apologize for not commenting here earlier. The changes are exactly as needed and described. Comment made by Paul was very helpful.&lt;/p&gt;</comment>
                            <comment id="21750" author="price" created="Wed, 28 Jul 2021 14:40:22 +0000"  >&lt;p&gt;Merged.&lt;/p&gt;</comment>
                    </comments>
                <issuelinks>
                            <issuelinktype id="10003">
                    <name>Relates</name>
                                            <outwardlinks description="relates to">
                                        <issuelink>
            <issuekey id="16972">PIPE2D-874</issuekey>
        </issuelink>
                            </outwardlinks>
                                                        </issuelinktype>
                    </issuelinks>
                <attachments>
                            <attachment id="13947" name="centering.jpg" size="31687" author="price" created="Tue, 20 Jul 2021 16:19:01 +0000"/>
                            <attachment id="13948" name="example_constant_array.png" size="18504" author="ncaplar" created="Thu, 22 Jul 2021 20:16:10 +0000"/>
                    </attachments>
                <subtasks>
                    </subtasks>
                <customfields>
                                                <customfield id="customfield_10500" key="com.atlassian.jira.plugins.jira-development-integration-plugin:devsummary">
                        <customfieldname>Development</customfieldname>
                        <customfieldvalues>
                            
                        </customfieldvalues>
                    </customfield>
                                                                                                                                                                                                            <customfield id="customfield_10010" key="com.pyxis.greenhopper.jira:gh-lexo-rank">
                        <customfieldname>Rank</customfieldname>
                        <customfieldvalues>
                            <customfieldvalue>0|zzs8a0:</customfieldvalue>

                        </customfieldvalues>
                    </customfield>
                                                                                            <customfield id="customfield_10100" key="com.atlassian.jira.plugin.system.customfieldtypes:userpicker">
                        <customfieldname>Reviewers</customfieldname>
                        <customfieldvalues>
                            <customfieldvalue>hassan</customfieldvalue>

                        </customfieldvalues>
                    </customfield>
                                                                <customfield id="customfield_10005" key="com.pyxis.greenhopper.jira:gh-sprint">
                        <customfieldname>Sprint</customfieldname>
                        <customfieldvalues>
                                <customfieldvalue id="115">2DDRP-2021 A 7</customfieldvalue>

                        </customfieldvalues>
                    </customfield>
                                                                <customfield id="customfield_10002" key="com.atlassian.jira.plugin.system.customfieldtypes:float">
                        <customfieldname>Story Points</customfieldname>
                        <customfieldvalues>
                            <customfieldvalue>1.0</customfieldvalue>
                        </customfieldvalues>
                    </customfield>
                                                                                                                        </customfields>
    </item>
</channel>
</rss>