{"action":"created","issue":{"url":"https://api.github.com/repos/gonum/plot/issues/377","repository_url":"https://api.github.com/repos/gonum/plot","labels_url":"https://api.github.com/repos/gonum/plot/issues/377/labels{/name}","comments_url":"https://api.github.com/repos/gonum/plot/issues/377/comments","events_url":"https://api.github.com/repos/gonum/plot/issues/377/events","html_url":"https://github.com/gonum/plot/issues/377","id":249701562,"node_id":"MDU6SXNzdWUyNDk3MDE1NjI=","number":377,"title":"plotter: plotting an histogram in logscale","user":{"login":"sbinet","id":1070920,"node_id":"MDQ6VXNlcjEwNzA5MjA=","avatar_url":"https://avatars2.githubusercontent.com/u/1070920?v=4","gravatar_id":"","url":"https://api.github.com/users/sbinet","html_url":"https://github.com/sbinet","followers_url":"https://api.github.com/users/sbinet/followers","following_url":"https://api.github.com/users/sbinet/following{/other_user}","gists_url":"https://api.github.com/users/sbinet/gists{/gist_id}","starred_url":"https://api.github.com/users/sbinet/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/sbinet/subscriptions","organizations_url":"https://api.github.com/users/sbinet/orgs","repos_url":"https://api.github.com/users/sbinet/repos","events_url":"https://api.github.com/users/sbinet/events{/privacy}","received_events_url":"https://api.github.com/users/sbinet/received_events","type":"User","site_admin":false},"labels":[{"id":48973962,"node_id":"MDU6TGFiZWw0ODk3Mzk2Mg==","url":"https://api.github.com/repos/gonum/plot/labels/bug","name":"bug","color":"fc2929","default":true},{"id":48973964,"node_id":"MDU6TGFiZWw0ODk3Mzk2NA==","url":"https://api.github.com/repos/gonum/plot/labels/enhancement","name":"enhancement","color":"84b6eb","default":true}],"state":"open","locked":false,"assignee":null,"assignees":[],"milestone":null,"comments":13,"created_at":"2017-08-11T17:39:48Z","updated_at":"2018-06-09T05:49:18Z","closed_at":null,"author_association":"MEMBER","body":"hi,\r\n\r\nconsider the following code:\r\n\r\n```go\r\nfunc TestHistogramLogScale(t *testing.T) {\r\n\trnd := rand.New(rand.NewSource(1))\r\n\tn := 1000\r\n\tvals := make(Values, n)\r\n\tfor i := 0; i < n; i++ {\r\n\t\tvals[i] = rnd.NormFloat64()\r\n\t}\r\n\r\n\tp, err := plot.New()\r\n\tif err != nil {\r\n\t\tlog.Panic(err)\r\n\t}\r\n\tp.Title.Text = \"Histogram in logy\"\r\n\tp.Y.Min = 0.1\r\n\tp.Y.Scale = plot.LogScale{}\r\n\tp.Y.Tick.Marker = plot.LogTicks{}\r\n\r\n\th, err := NewHist(vals, 16)\r\n\tif err != nil {\r\n\t\tt.Fatal(err)\r\n\t}\r\n\th.Normalize(1)\r\n\tp.Add(h)\r\n\r\n\terr = p.Save(200, 200, \"testdata/histogram_log.png\")\r\n\tif err != nil {\r\n\t\tt.Fatal(err)\r\n\t}\r\n}\r\n```\r\n\r\nthis will panic:\r\n```\r\n=== RUN   TestHistogramLogScale\r\n--- FAIL: TestHistogramLogScale (0.01s)\r\npanic: Values must be greater than 0 for a log scale. [recovered]\r\n\tpanic: Values must be greater than 0 for a log scale.\r\n\r\ngoroutine 5 [running]:\r\ntesting.tRunner.func1(0xc42005a9c0)\r\n\t/usr/lib/go/src/testing/testing.go:622 +0x29d\r\npanic(0x7d7160, 0xc4200f7790)\r\n\t/usr/lib/go/src/runtime/panic.go:489 +0x2cf\r\ngithub.com/gonum/plot.LogTicks.Ticks(0x0, 0x3fda71c2dac35ff2, 0xc420123420, 0x4cbec8, 0x857cfb)\r\n\t/home/binet/work/gonum/src/github.com/gonum/plot/axis.go:429 +0x400\r\ngithub.com/gonum/plot.(*LogTicks).Ticks(0xc89e68, 0x0, 0x3fda71c2dac35ff2, 0x4cc5a5, 0x857cfb, 0x9)\r\n\t<autogenerated>:42 +0x5d\r\ngithub.com/gonum/plot.(*verticalAxis).size(0xc420123af8, 0x40278e0000000000)\r\n\t/home/binet/work/gonum/src/github.com/gonum/plot/axis.go:282 +0x7a\r\ngithub.com/gonum/plot.(*Plot).Draw(0xc4200b3000, 0x7f6fa2e5d428, 0xc420058de0, 0x0, 0x0, 0x4069000000000000, 0x406712b000000000)\r\n\t/home/binet/work/gonum/src/github.com/gonum/plot/plot.go:168 +0x232\r\ngithub.com/gonum/plot.(*Plot).WriterTo(0xc4200b3000, 0x4069000000000000, 0x4069000000000000, 0x86945b, 0x3, 0x0, 0x400aa49aec34e97f, 0x1, 0xc4200f7190)\r\n\t/home/binet/work/gonum/src/github.com/gonum/plot/plot.go:455 +0x143\r\ngithub.com/gonum/plot.(*Plot).Save(0xc4200b3000, 0x4069000000000000, 0x4069000000000000, 0x869444, 0x1a, 0x0, 0x0)\r\n\t/home/binet/work/gonum/src/github.com/gonum/plot/plot.go:481 +0x147\r\ngithub.com/gonum/plot/plotter.TestHistogramLogScale(0xc42005a9c0)\r\n\t/home/binet/work/gonum/src/github.com/gonum/plot/plotter/histogram_test.go:129 +0x42b\r\ntesting.tRunner(0xc42005a9c0, 0x873468)\r\n\t/usr/lib/go/src/testing/testing.go:657 +0x96\r\ncreated by testing.(*T).Run\r\n\t/usr/lib/go/src/testing/testing.go:697 +0x2ca\r\nexit status 2\r\n```\r\n\r\nbecause, even though `p.Y.Min` was set, the empty bins of the histogram will still be \"evaluated\".\r\n\r\nLocally, I have implemented a not completely satisfactory hack: implement \"clipping\" decorators for `LogScale` and `LogTicks`:\r\n\r\n```go\r\ntype ClipScale struct {\r\n\tMin  float64\r\n\tMax  float64\r\n\tNorm plot.Normalizer\r\n}\r\n\r\nfunc (cs ClipScale) Normalize(min, max, x float64) float64 {\r\n\tmin = math.Max(cs.Min, min)\r\n\tmax = math.Min(cs.Max, max)\r\n\tswitch {\r\n\tcase x < cs.Min:\r\n\t\tx = cs.Min\r\n\tcase x > cs.Max:\r\n\t\tx = cs.Max\r\n\t}\r\n\treturn cs.Norm.Normalize(min, max, x)\r\n}\r\n\r\nvar _ plot.Normalizer = ClipScale{}\r\n\r\ntype ClipTicker struct {\r\n\tMin    float64\r\n\tMax    float64\r\n\tTicker plot.Ticker\r\n}\r\n\r\nvar _ plot.Ticker = ClipTicker{}\r\n\r\nfunc (ct ClipTicker) Ticks(min, max float64) []plot.Tick {\r\n\tmin = math.Max(min, ct.Min)\r\n\tmax = math.Min(max, ct.Max)\r\n\treturn ct.Ticker.Ticks(min, max)\r\n}\r\n```\r\n\r\nand with:\r\n```go\r\n\t\tp.Y.Scale = ClipScale{p.Y.Min, math.Inf(+1), plot.LogScale{}}\r\n\t\tp.Y.Tick.Marker = ClipTicker{p.Y.Min, math.Inf(+1), plot.LogTicks{}}\r\n```\r\n\r\nbut it's not competely satisfactory because then we get histo-bars for these empty bins:\r\n![histogram_log](https://user-images.githubusercontent.com/1070920/29224890-76d7b4be-7ecc-11e7-9667-d054f35919f1.png)\r\n\r\nany idea ?"},"comment":{"url":"https://api.github.com/repos/gonum/plot/issues/comments/395942448","html_url":"https://github.com/gonum/plot/issues/377#issuecomment-395942448","issue_url":"https://api.github.com/repos/gonum/plot/issues/377","id":395942448,"node_id":"MDEyOklzc3VlQ29tbWVudDM5NTk0MjQ0OA==","user":{"login":"sbinet","id":1070920,"node_id":"MDQ6VXNlcjEwNzA5MjA=","avatar_url":"https://avatars2.githubusercontent.com/u/1070920?v=4","gravatar_id":"","url":"https://api.github.com/users/sbinet","html_url":"https://github.com/sbinet","followers_url":"https://api.github.com/users/sbinet/followers","following_url":"https://api.github.com/users/sbinet/following{/other_user}","gists_url":"https://api.github.com/users/sbinet/gists{/gist_id}","starred_url":"https://api.github.com/users/sbinet/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/sbinet/subscriptions","organizations_url":"https://api.github.com/users/sbinet/orgs","repos_url":"https://api.github.com/users/sbinet/repos","events_url":"https://api.github.com/users/sbinet/events{/privacy}","received_events_url":"https://api.github.com/users/sbinet/received_events","type":"User","site_admin":false},"created_at":"2018-06-09T05:49:17Z","updated_at":"2018-06-09T05:49:17Z","author_association":"MEMBER","body":"Ok, I'll address the initial comments on the PR and create another one\nbased on a 'YMin' mechanism.\n\n-s\n\nsent from my droid\n\nOn Sat, Jun 9, 2018, 03:08 Dan Kortschak <notifications@github.com> wrote:\n\n> I'd be happier if this didn't go in this way. I'd much rather see a\n> composable approach. Can a NaN YMin field be used to do this?\n>\n> —\n> You are receiving this because you authored the thread.\n> Reply to this email directly, view it on GitHub\n> <https://github.com/gonum/plot/issues/377#issuecomment-395928420>, or mute\n> the thread\n> <https://github.com/notifications/unsubscribe-auth/ABBXSMkzKb8wCBg76wCSJ-RBbGOI4nBhks5t6yARgaJpZM4O08AM>\n> .\n>\n"}}
{"actor":{"display_login":"sbinet"}}