René's URL Explorer Experiment


Title: `ImageItem` not properly scaling along Y-axis with logarithmic scale · Issue #36 · PlotPyStack/PlotPy · GitHub

Open Graph Title: `ImageItem` not properly scaling along Y-axis with logarithmic scale · Issue #36 · PlotPyStack/PlotPy

X Title: `ImageItem` not properly scaling along Y-axis with logarithmic scale · Issue #36 · PlotPyStack/PlotPy

Description: Problem Description I'm experiencing an issue where ImageItem properly stretches across the entire X-axis range but fails to occupy the full Y-axis range when using a logarithmic scale. This behavior is inconsistent between the X and Y a...

Open Graph Description: Problem Description I'm experiencing an issue where ImageItem properly stretches across the entire X-axis range but fails to occupy the full Y-axis range when using a logarithmic scale. This behavi...

X Description: Problem Description I'm experiencing an issue where ImageItem properly stretches across the entire X-axis range but fails to occupy the full Y-axis range when using a logarithmic scale. This be...

Opengraph URL: https://github.com/PlotPyStack/PlotPy/issues/36

X: @github

direct link

Domain: github.com


Hey, it has json ld scripts:
{"@context":"https://schema.org","@type":"DiscussionForumPosting","headline":"`ImageItem` not properly scaling along Y-axis with logarithmic scale","articleBody":"_**Problem Description**_\n\nI'm experiencing an issue where ImageItem properly stretches across the entire X-axis range but fails to occupy the full Y-axis range when using a logarithmic scale. This behavior is inconsistent between the X and Y axes.\n\n_**Reproduction Steps**_\n\nI've created a simple test case with a multi-histogram plot that can be rotated to switch the axes:\n- When the logarithmic scale is on the Y-axis (normal orientation), the `ImageItem` doesn't stretch properly from `LOG_MIN` (1) to `LOG_MAX` (10^8).\n- When the same logarithmic scale is on the X-axis (rotated orientation), the `ImageItem` stretches correctly across the full range.\n\n_**Questions**_\n1) Is there something going on with ImageItem's axis handling? Does ImageItem interpret X and Y axes differently when applying scaling?\n2) Does the `QwtScaleEngine` and `QwtTransform` interpret X and Y axes differently? Is there a fundamental difference in how scale engines are applied to different axes?\n\n_**Code Example**_\nI've created a minimal reproducible example that demonstrates the issue. The key components are:\n- Custom `Log10ScaleEngine` and `Log10Transform` for logarithmic scaling.\n- `ImageItem` with properly set bounds in `image_param`.\n- Ability to rotate the plot to switch which axis uses the logarithmic scale. See the `rotate` parameter of the `MultiHistogramPlot` class.\n\n```\nimport sys, numpy as np\nfrom PySide6.QtWidgets import QApplication, QMainWindow, QWidget, QVBoxLayout, QSizePolicy\nfrom PySide6.QtGui import QFont\nfrom PySide6.QtCore import Qt\nfrom plotpy.plot import BasePlot\nfrom plotpy.items import ImageItem\nfrom plotpy.styles import ImageParam\nfrom qwt import QwtScaleDiv, QwtScaleDraw, QwtText\nfrom qwt.scale_engine import QwtScaleEngine\nfrom qwt.transform import QwtTransform\n\nWAVELENGTHS = [\"371nm\", \"382nm\", \"393nm\", \"404nm\", \"415nm\"]\nLOG_MIN, LOG_MAX = 1, 10**8\n\nclass WavelengthTransform(QwtTransform):\n    def transform(self, value): return value\n    def invTransform(self, value): return value\n    def copy(self): return WavelengthTransform()\n\nclass WavelengthScaleDraw(QwtScaleDraw):\n    def __init__(self, wavelengths):\n        super().__init__()\n        self.wavelengths = wavelengths\n        self.setLabelRotation(45)\n        self.setLabelAlignment(Qt.AlignBottom)\n        self.setSpacing(10)\n        self.setPenWidth(1.5)\n    \n    def label(self, value):\n        idx = int(round(value))\n        if 0 \u003c= idx \u003c len(self.wavelengths):\n            text = QwtText(self.wavelengths[idx])\n            text.setFont(QFont(\"Arial\", 9))\n            return text\n        return QwtText(\"\")\n\nclass WavelengthScaleEngine(QwtScaleEngine):\n    def __init__(self, wavelengths):\n        super().__init__()\n        self.wavelengths = wavelengths\n        self.setAttribute(QwtScaleEngine.Floating, False)\n        self.setAttribute(QwtScaleEngine.Symmetric, False)\n        self.setAttribute(QwtScaleEngine.IncludeReference, True)\n    \n    def transformation(self): return WavelengthTransform()\n    def autoScale(self, maxNumSteps, x1, x2, stepSize): return -1, len(self.wavelengths) + 1, 1.0\n    \n    def divideScale(self, x1, x2, maxMajor, maxMinor, stepSize=0):\n        x1, x2 = -1, len(self.wavelengths) + 1\n        major_ticks = list(range(len(self.wavelengths)))\n        return QwtScaleDiv(x1, x2, [], [], major_ticks)\n\nclass Log10Transform(QwtTransform):\n    def __init__(self):\n        super().__init__()\n        self.LogMin, self.LogMax = LOG_MIN, LOG_MAX\n\n    def bounded(self, value): return np.clip(value, self.LogMin, self.LogMax)\n    def copy(self): return Log10Transform()\n    def invTransform(self, value): return 10**self.bounded(value)\n    def transform(self, value): return np.log10(self.bounded(value))\n\nclass Log10ScaleEngine(QwtScaleEngine):\n    def transformation(self): return Log10Transform()\n    def autoScale(self, maxNumSteps, x1, x2, stepSize): return LOG_MIN, LOG_MAX, 1\n    \n    def divideScale(self, x1, x2, maxMajor, maxMinor, stepSize=0):\n        x1, x2 = LOG_MIN, LOG_MAX\n        major_ticks = [10**i for i in range(9)]\n        minor_ticks = [base * j for i in range(8) for base in [10**i] for j in range(2, 10)]\n        return QwtScaleDiv(x1, x2, minor_ticks, [], major_ticks)\n\nclass MultiHistogramPlot(QMainWindow):\n    def __init__(self, rotate=False):\n        super().__init__()\n        main_widget = QWidget()\n        self.setCentralWidget(main_widget)\n        layout = QVBoxLayout(main_widget)\n        self.rotate = rotate\n        self.plot = BasePlot()\n        layout.addWidget(self.plot)\n        self.setup_plot()\n\n    def setup_plot(self):\n        self.setup_axes()\n        self.num_bins = 1024\n        \n        # Initialize data array based on orientation\n        self.initialH = np.zeros((self.num_bins, len(WAVELENGTHS)) if not self.rotate else (len(WAVELENGTHS), self.num_bins))\n\n        # Configure image parameters\n        self.image_param = ImageParam()\n        self.image_param.lock_position = True\n        \n        # Set axis limits based on orientation\n        if not self.rotate:\n            self.image_param.xmin, self.image_param.xmax = -0.5, len(WAVELENGTHS)-0.5\n            self.image_param.ymin, self.image_param.ymax = LOG_MIN, LOG_MAX\n        else:\n            self.image_param.xmin, self.image_param.xmax = LOG_MIN, LOG_MAX\n            self.image_param.ymin, self.image_param.ymax = -0.5, len(WAVELENGTHS)-0.5\n        \n        self.image_param.colormap = \"jet\"\n        \n        print(f\"Before adding image item: \")\n        print(f\"self.image_param.xmin: {self.image_param.xmin}, \\\n              self.image_param.xmax: {self.image_param.xmax}, \\\n              self.image_param.ymin: {self.image_param.ymin}, \\\n              self.image_param.ymax: {self.image_param.ymax}\")\n        \n        # Create and add image item\n        self.hist = ImageItem(self.initialH, self.image_param)\n        self.plot.set_aspect_ratio(ratio=None, lock=False)  # Prevent overflow errors\n        self.plot.add_item(self.hist)\n\n        print(f\"After adding image item: \") \n        print(f\"self.image_param.xmin: {self.image_param.xmin}, \\\n              self.image_param.xmax: {self.image_param.xmax}, \\\n              self.image_param.ymin: {self.image_param.ymin}, \\\n              self.image_param.ymax: {self.image_param.ymax}\")\n\n    \n    def setup_axes(self):\n        if not self.rotate:\n            # Normal orientation\n            self.plot.setAxisTitle(BasePlot.X_BOTTOM, \"Wavelength\")\n            self.plot.setAxisTitle(BasePlot.Y_LEFT, \"Intensity\")\n            self.plot.setAxisScaleEngine(BasePlot.X_BOTTOM, WavelengthScaleEngine(WAVELENGTHS))\n            self.plot.setAxisScaleDraw(BasePlot.X_BOTTOM, WavelengthScaleDraw(WAVELENGTHS))\n            self.plot.setAxisScaleEngine(BasePlot.Y_LEFT, Log10ScaleEngine())\n        else:\n            # Rotated orientation\n            self.plot.setAxisTitle(BasePlot.X_BOTTOM, \"Intensity\")\n            self.plot.setAxisTitle(BasePlot.Y_LEFT, \"Wavelength\")\n            self.plot.setAxisScaleEngine(BasePlot.X_BOTTOM, Log10ScaleEngine())\n            self.plot.setAxisScaleEngine(BasePlot.Y_LEFT, WavelengthScaleEngine(WAVELENGTHS))\n            self.plot.setAxisScaleDraw(BasePlot.Y_LEFT, WavelengthScaleDraw(WAVELENGTHS))\n\nif __name__ == '__main__':\n    app = QApplication(sys.argv)\n    window = MultiHistogramPlot(rotate=False)\n    \n    # Create logarithmic bins and generate sample data\n    log_bins = np.logspace(np.log10(LOG_MIN), np.log10(LOG_MAX), window.num_bins)\n    sample_data = np.zeros((len(WAVELENGTHS), window.num_bins-1) if window.rotate else (window.num_bins-1, len(WAVELENGTHS)))\n    \n    # Generate histogram data for each wavelength\n    for i in range(len(WAVELENGTHS)):\n        # Generate raw data with multiple peaks\n        num_samples = 100000\n        mean1, std1 = 10**(2 + i*0.7), 10**(2 + i*0.7) * 0.3\n        mean2, std2 = 10**(4 + i*0.5), 10**(4 + i*0.5) * 0.2\n        \n        # Create and combine samples\n        raw_data = np.abs(np.concatenate([\n            np.random.normal(mean1, std1, num_samples // 2),\n            np.random.normal(mean2, std2, num_samples // 2)\n        ]))\n        \n        # Create histogram with logarithmic bins\n        hist_values, _ = np.histogram(raw_data, bins=log_bins)\n        \n        # Store histogram values in appropriate orientation\n        if window.rotate:\n            sample_data[i, :] = hist_values\n        else:\n            sample_data[:, i] = hist_values\n    \n    # Update the plot with the histogram data\n    window.hist.set_data(sample_data)\n\n    print(f\"After setting data: \")\n    print(f\"self.image_param.xmin: {window.image_param.xmin}, \\\n          self.image_param.xmax: {window.image_param.xmax}, \\\n          self.image_param.ymin: {window.image_param.ymin}, \\\n          self.image_param.ymax: {window.image_param.ymax}\")\n    \n    window.show()\n    sys.exit(app.exec())\n```\n\n\nI've verified that these parameters are maintained after adding the item and setting data, but the visual result shows the Y-axis scaling is not being applied correctly.\n\n**_Expected Behavior_**\n\nThe `ImageItem` should stretch to fill the entire plot area defined by the axis limits, regardless of which axis uses the logarithmic scale.\n\n_**Actual Behavior**_\n\nThe `ImageItem` only stretches properly when the logarithmic scale is on the X-axis, but not when it's on the Y-axis.","author":{"url":"https://github.com/imad-miftek","@type":"Person","name":"imad-miftek"},"datePublished":"2025-03-08T20:11:55.000Z","interactionStatistic":{"@type":"InteractionCounter","interactionType":"https://schema.org/CommentAction","userInteractionCount":4},"url":"https://github.com/36/PlotPy/issues/36"}

route-pattern/_view_fragments/issues/show/:user_id/:repository/:id/issue_layout(.:format)
route-controllervoltron_issues_fragments
route-actionissue_layout
fetch-noncev2:e61616a8-d75a-3588-7d03-5852c6899eb2
current-catalog-service-hash81bb79d38c15960b92d99bca9288a9108c7a47b18f2423d0f6438c5b7bcd2114
request-idB494:209CC7:2CAD4CB:3D6DCC8:6972B4D3
html-safe-nonce7c724d60436e6a2600b0da96280cadc1ebd6cbe9b0ecf903c8e031d1bc71a4ce
visitor-payloadeyJyZWZlcnJlciI6IiIsInJlcXVlc3RfaWQiOiJCNDk0OjIwOUNDNzoyQ0FENENCOjNENkRDQzg6Njk3MkI0RDMiLCJ2aXNpdG9yX2lkIjoiMzc1MjExNTUyNzg0NTMyODA4MyIsInJlZ2lvbl9lZGdlIjoiaWFkIiwicmVnaW9uX3JlbmRlciI6ImlhZCJ9
visitor-hmac596fdb301724a49b42f5f28ac4d88274f7b3747a8c4831182eefd630aeeb4f2a
hovercard-subject-tagissue:2904996605
github-keyboard-shortcutsrepository,issues,copilot
google-site-verificationApib7-x98H0j5cPqHWwSMm6dNU4GmODRoqxLiDzdx9I
octolytics-urlhttps://collector.github.com/github/collect
analytics-location///voltron/issues_fragments/issue_layout
fb:app_id1401488693436528
apple-itunes-appapp-id=1477376905, app-argument=https://github.com/_view_fragments/issues/show/PlotPyStack/PlotPy/36/issue_layout
twitter:imagehttps://opengraph.githubassets.com/e7a1872b8828f1699ef64b80291f1beb1ce9c15258526332e087f656da014371/PlotPyStack/PlotPy/issues/36
twitter:cardsummary_large_image
og:imagehttps://opengraph.githubassets.com/e7a1872b8828f1699ef64b80291f1beb1ce9c15258526332e087f656da014371/PlotPyStack/PlotPy/issues/36
og:image:altProblem Description I'm experiencing an issue where ImageItem properly stretches across the entire X-axis range but fails to occupy the full Y-axis range when using a logarithmic scale. This behavi...
og:image:width1200
og:image:height600
og:site_nameGitHub
og:typeobject
og:author:usernameimad-miftek
hostnamegithub.com
expected-hostnamegithub.com
None51c0d0848f5569c6fa2198e9d69bd5f8f94a83c9fa3659e40728e7732afab130
turbo-cache-controlno-preview
go-importgithub.com/PlotPyStack/PlotPy git https://github.com/PlotPyStack/PlotPy.git
octolytics-dimension-user_id145201262
octolytics-dimension-user_loginPlotPyStack
octolytics-dimension-repository_id671159499
octolytics-dimension-repository_nwoPlotPyStack/PlotPy
octolytics-dimension-repository_publictrue
octolytics-dimension-repository_is_forkfalse
octolytics-dimension-repository_network_root_id671159499
octolytics-dimension-repository_network_root_nwoPlotPyStack/PlotPy
turbo-body-classeslogged-out env-production page-responsive
disable-turbofalse
browser-stats-urlhttps://api.github.com/_private/browser/stats
browser-errors-urlhttps://api.github.com/_private/browser/errors
release10c5e2f2307495b2750073db87e9a5d3356a924f
ui-targetfull
theme-color#1e2327
color-schemelight dark

Links:

Skip to contenthttps://github.com/PlotPyStack/PlotPy/issues/36#start-of-content
https://github.com/
Sign in https://github.com/login?return_to=https%3A%2F%2Fgithub.com%2FPlotPyStack%2FPlotPy%2Fissues%2F36
GitHub CopilotWrite better code with AIhttps://github.com/features/copilot
GitHub SparkBuild and deploy intelligent appshttps://github.com/features/spark
GitHub ModelsManage and compare promptshttps://github.com/features/models
MCP RegistryNewIntegrate external toolshttps://github.com/mcp
ActionsAutomate any workflowhttps://github.com/features/actions
CodespacesInstant dev environmentshttps://github.com/features/codespaces
IssuesPlan and track workhttps://github.com/features/issues
Code ReviewManage code changeshttps://github.com/features/code-review
GitHub Advanced SecurityFind and fix vulnerabilitieshttps://github.com/security/advanced-security
Code securitySecure your code as you buildhttps://github.com/security/advanced-security/code-security
Secret protectionStop leaks before they starthttps://github.com/security/advanced-security/secret-protection
Why GitHubhttps://github.com/why-github
Documentationhttps://docs.github.com
Bloghttps://github.blog
Changeloghttps://github.blog/changelog
Marketplacehttps://github.com/marketplace
View all featureshttps://github.com/features
Enterpriseshttps://github.com/enterprise
Small and medium teamshttps://github.com/team
Startupshttps://github.com/enterprise/startups
Nonprofitshttps://github.com/solutions/industry/nonprofits
App Modernizationhttps://github.com/solutions/use-case/app-modernization
DevSecOpshttps://github.com/solutions/use-case/devsecops
DevOpshttps://github.com/solutions/use-case/devops
CI/CDhttps://github.com/solutions/use-case/ci-cd
View all use caseshttps://github.com/solutions/use-case
Healthcarehttps://github.com/solutions/industry/healthcare
Financial serviceshttps://github.com/solutions/industry/financial-services
Manufacturinghttps://github.com/solutions/industry/manufacturing
Governmenthttps://github.com/solutions/industry/government
View all industrieshttps://github.com/solutions/industry
View all solutionshttps://github.com/solutions
AIhttps://github.com/resources/articles?topic=ai
Software Developmenthttps://github.com/resources/articles?topic=software-development
DevOpshttps://github.com/resources/articles?topic=devops
Securityhttps://github.com/resources/articles?topic=security
View all topicshttps://github.com/resources/articles
Customer storieshttps://github.com/customer-stories
Events & webinarshttps://github.com/resources/events
Ebooks & reportshttps://github.com/resources/whitepapers
Business insightshttps://github.com/solutions/executive-insights
GitHub Skillshttps://skills.github.com
Documentationhttps://docs.github.com
Customer supporthttps://support.github.com
Community forumhttps://github.com/orgs/community/discussions
Trust centerhttps://github.com/trust-center
Partnershttps://github.com/partners
GitHub SponsorsFund open source developershttps://github.com/sponsors
Security Labhttps://securitylab.github.com
Maintainer Communityhttps://maintainers.github.com
Acceleratorhttps://github.com/accelerator
Archive Programhttps://archiveprogram.github.com
Topicshttps://github.com/topics
Trendinghttps://github.com/trending
Collectionshttps://github.com/collections
Enterprise platformAI-powered developer platformhttps://github.com/enterprise
GitHub Advanced SecurityEnterprise-grade security featureshttps://github.com/security/advanced-security
Copilot for BusinessEnterprise-grade AI featureshttps://github.com/features/copilot/copilot-business
Premium SupportEnterprise-grade 24/7 supporthttps://github.com/premium-support
Pricinghttps://github.com/pricing
Search syntax tipshttps://docs.github.com/search-github/github-code-search/understanding-github-code-search-syntax
documentationhttps://docs.github.com/search-github/github-code-search/understanding-github-code-search-syntax
Sign in https://github.com/login?return_to=https%3A%2F%2Fgithub.com%2FPlotPyStack%2FPlotPy%2Fissues%2F36
Sign up https://github.com/signup?ref_cta=Sign+up&ref_loc=header+logged+out&ref_page=%2F%3Cuser-name%3E%2F%3Crepo-name%3E%2Fvoltron%2Fissues_fragments%2Fissue_layout&source=header-repo&source_repo=PlotPyStack%2FPlotPy
Reloadhttps://github.com/PlotPyStack/PlotPy/issues/36
Reloadhttps://github.com/PlotPyStack/PlotPy/issues/36
Reloadhttps://github.com/PlotPyStack/PlotPy/issues/36
PlotPyStack https://github.com/PlotPyStack
PlotPyhttps://github.com/PlotPyStack/PlotPy
Notifications https://github.com/login?return_to=%2FPlotPyStack%2FPlotPy
Fork 4 https://github.com/login?return_to=%2FPlotPyStack%2FPlotPy
Star 42 https://github.com/login?return_to=%2FPlotPyStack%2FPlotPy
Code https://github.com/PlotPyStack/PlotPy
Issues 2 https://github.com/PlotPyStack/PlotPy/issues
Pull requests 0 https://github.com/PlotPyStack/PlotPy/pulls
Actions https://github.com/PlotPyStack/PlotPy/actions
Projects 0 https://github.com/PlotPyStack/PlotPy/projects
Security 0 https://github.com/PlotPyStack/PlotPy/security
Insights https://github.com/PlotPyStack/PlotPy/pulse
Code https://github.com/PlotPyStack/PlotPy
Issues https://github.com/PlotPyStack/PlotPy/issues
Pull requests https://github.com/PlotPyStack/PlotPy/pulls
Actions https://github.com/PlotPyStack/PlotPy/actions
Projects https://github.com/PlotPyStack/PlotPy/projects
Security https://github.com/PlotPyStack/PlotPy/security
Insights https://github.com/PlotPyStack/PlotPy/pulse
New issuehttps://github.com/login?return_to=https://github.com/PlotPyStack/PlotPy/issues/36
New issuehttps://github.com/login?return_to=https://github.com/PlotPyStack/PlotPy/issues/36
ImageItem not properly scaling along Y-axis with logarithmic scalehttps://github.com/PlotPyStack/PlotPy/issues/36#top
bugSomething isn't workinghttps://github.com/PlotPyStack/PlotPy/issues?q=state%3Aopen%20label%3A%22bug%22
https://github.com/imad-miftek
https://github.com/imad-miftek
imad-miftekhttps://github.com/imad-miftek
on Mar 8, 2025https://github.com/PlotPyStack/PlotPy/issues/36#issue-2904996605
bugSomething isn't workinghttps://github.com/PlotPyStack/PlotPy/issues?q=state%3Aopen%20label%3A%22bug%22
https://github.com
Termshttps://docs.github.com/site-policy/github-terms/github-terms-of-service
Privacyhttps://docs.github.com/site-policy/privacy-policies/github-privacy-statement
Securityhttps://github.com/security
Statushttps://www.githubstatus.com/
Communityhttps://github.community/
Docshttps://docs.github.com/
Contacthttps://support.github.com?tags=dotcom-footer

Viewport: width=device-width


URLs of crawlers that visited me.