It is currently Sat Apr 20, 2024 4:41 am


All times are UTC - 5 hours [ DST ]



Post new topic Reply to topic  [ 11 posts ] 
Author Message
 Post subject: A Globular Cluster (astronomical object) script
PostPosted: Sat Jan 17, 2015 10:41 am  (#1) 
Offline
GimpChat Member
User avatar

Joined: Dec 26, 2014
Posts: 198
Though I can download images of globular clusters off the web for use in my images, I wanted to see if I could write a script to generate such and this script is what I came up with.
Attachment:
Globular-cluster.scm [5.16 KiB]
Downloaded 131 times


It works on my computer running Gimp 2.6.11

Please note:

At the default settings the script takes about a few seconds to run, as the "Number of Stars to seed" is increased the time gets progressively longer (minutes for 2000 Stars), and "Cluster Type Dense" takes longer than "Loose" which takes longer than "Open"

Placed at "<Image>/Filters/Decor/Globular cluster"

Any critique/criticism on the output or coding is welcome

Thanks for looking
Attachment:
640 110 loose blue.jpg
640 110 loose blue.jpg [ 83.41 KiB | Viewed 2680 times ]


Share on Facebook Share on Twitter Share on Orkut Share on Digg Share on MySpace Share on Delicious Share on Technorati
Top
 Post subject: Re: A Globular Cluster (astronomical object) script
PostPosted: Sat Jan 17, 2015 11:10 am  (#2) 
Offline
Global Moderator
User avatar

Joined: Apr 07, 2010
Posts: 14182
Very cool Steve, I duped the layer, colorized the dupe, then moved it up.
Image
thanks Steve

_________________
Image


Top
 Post subject: Re: A Globular Cluster (astronomical object) script
PostPosted: Sat Jan 17, 2015 4:46 pm  (#3) 
Offline
GimpChat Member
User avatar

Joined: Dec 26, 2014
Posts: 198
molly wrote:
Very cool Steve, I duped the layer, colorized the dupe, then moved it up.
[ Image ]
thanks Steve

Thanks Molly and nicely done :) , i like the contrast between the colours


Top
 Post subject: Re: A Globular Cluster (astronomical object) script
PostPosted: Sun Jan 18, 2015 12:32 am  (#4) 
Offline
GimpChat Member
User avatar

Joined: Apr 09, 2011
Posts: 1764
very nice effect


Top
 Post subject: Re: A Globular Cluster (astronomical object) script
PostPosted: Sun Jan 18, 2015 4:04 pm  (#5) 
Offline
GimpChat Member
User avatar

Joined: Dec 26, 2014
Posts: 198
akky wrote:
very nice effect

Thank you akky :)


Top
 Post subject: Re: A Globular Cluster (astronomical object) script
PostPosted: Sun Jan 18, 2015 4:05 pm  (#6) 
Offline
GimpChat Member
User avatar

Joined: Dec 26, 2014
Posts: 198
conbagui wrote:
Nice script Steve. I used the Astronomy plugin for Gimp and it has different setting of Clusters.
[ Image ]
Globular Cluster
[ Image ]

Thanks conbagui, the astronomy plugin looks very interesting, will have to give it a try


Top
 Post subject: Re: A Globular Cluster (astronomical object) script
PostPosted: Sun Jan 18, 2015 7:26 pm  (#7) 
Offline
Script Coder
User avatar

Joined: Apr 23, 2010
Posts: 1553
Location: not from Guildford after all
Steve wrote:
Any critique/criticism on the output or coding is welcome
:yes

First, extreme kudos on the excellent naming of your variables. It is such a pleasure to read Scheme code that doesn't resort to using CamelCase or under_scores.

One minor niggle is that you use "*" for your menu constraint in the 'script-fu-register' block. This means that your script will be available regardless of whether the currently opened image is RGB, GRAY, or INDEXED. The thing is, your script doesn't need an image to even be opened (it creates its own) so this constraint should properly be empty quotes, "". You might also consider placing the command in the "File->Create" submenu as the "Filters" menu is generally employed for filters that operate on existing images.

Your code conditioned upon the quadrant value could use a little bit of optimization. Firstly, rather than performing the test twice:
(if (= quadrant 0) (set! Xcord (+ X-axis-centre-line (* hypotenuse (sin radian)))))
(if (= quadrant 0) (set! Ycord (+ Y-axis-centre-line (* hypotenuse (cos radian)))))

Just perform the test once and combine the two calculation steps by wrapping them with (begin...):
(if (= quadrant 0)
  (begin
    (set! Xcord (+ X-axis-centre-line (* hypotenuse (sin radian)))))
    (set! Ycord (+ Y-axis-centre-line (* hypotenuse (cos radian))))))

Better still would be to use (cond...) or (case...) so that once a quadrant is matched, no further testing is performed (this will improve your script's speed by about 5-10%).
(case quadrant
  ((0)
    (set! Xcord (+ X-axis-centre-line (* hypotenuse (sin radian))))
    (set! Ycord (+ Y-axis-centre-line (* hypotenuse (cos radian)))))
  ((1)
    (set! Xcord (- X-axis-centre-line (* hypotenuse (sin radian))))
    (set! Ycord (+ Y-axis-centre-line (* hypotenuse (cos radian)))))
  ((2)
    (set! Xcord (- X-axis-centre-line (* hypotenuse (sin radian))))
    (set! Ycord (- Y-axis-centre-line (* hypotenuse (cos radian)))))
  ((3)
    (set! Xcord (+ X-axis-centre-line (* hypotenuse (sin radian))))
    (set! Ycord (- Y-axis-centre-line (* hypotenuse (cos radian))))))


Finally, you are setting the same pixels to the same color in four different layers each time through the loop. It would be more efficient to just create a single layer and after you've drawn all of your pixels, create three copies of the layer (this will roughly triple the speed of your script). You may have plans to, in the future, do something different with the layers and thus wish to leave things the way they are, but as things stand your approach is suboptimal.

As a general guideline, I personally try to postpone introducing variables until they are needed, rather than pre-declaring them all at the beginning of the script. This can be helpful in minimizing the likelihood of errors in larger Scheme programs, though for typical Script-fus it is more of a personal preference.

_________________
Any sufficiently primitive technology is indistinguishable from a rock.


Top
 Post subject: Re: A Globular Cluster (astronomical object) script
PostPosted: Mon Jan 19, 2015 11:20 am  (#8) 
Offline
GimpChat Member
User avatar

Joined: Dec 26, 2014
Posts: 198
saulgoode wrote:
Steve wrote:
Any critique/criticism on the output or coding is welcome
:yes

First, extreme kudos on the excellent naming of your variables. It is such a pleasure to read Scheme code that doesn't resort to using CamelCase or under_scores.

One minor niggle is that you use "*" for your menu constraint in the 'script-fu-register' block. This means that your script will be available regardless of whether the currently opened image is RGB, GRAY, or INDEXED. The thing is, your script doesn't need an image to even be opened (it creates its own) so this constraint should properly be empty quotes, "". You might also consider placing the command in the "File->Create" submenu as the "Filters" menu is generally employed for filters that operate on existing images.

Your code conditioned upon the quadrant value could use a little bit of optimization. Firstly, rather than performing the test twice:
(if (= quadrant 0) (set! Xcord (+ X-axis-centre-line (* hypotenuse (sin radian)))))
(if (= quadrant 0) (set! Ycord (+ Y-axis-centre-line (* hypotenuse (cos radian)))))

Just perform the test once and combine the two calculation steps by wrapping them with (begin...):
(if (= quadrant 0)
  (begin
    (set! Xcord (+ X-axis-centre-line (* hypotenuse (sin radian)))))
    (set! Ycord (+ Y-axis-centre-line (* hypotenuse (cos radian))))))

Better still would be to use (cond...) or (case...) so that once a quadrant is matched, no further testing is performed (this will improve your script's speed by about 5-10%).
(case quadrant
  ((0)
    (set! Xcord (+ X-axis-centre-line (* hypotenuse (sin radian))))
    (set! Ycord (+ Y-axis-centre-line (* hypotenuse (cos radian)))))
  ((1)
    (set! Xcord (- X-axis-centre-line (* hypotenuse (sin radian))))
    (set! Ycord (+ Y-axis-centre-line (* hypotenuse (cos radian)))))
  ((2)
    (set! Xcord (- X-axis-centre-line (* hypotenuse (sin radian))))
    (set! Ycord (- Y-axis-centre-line (* hypotenuse (cos radian)))))
  ((3)
    (set! Xcord (+ X-axis-centre-line (* hypotenuse (sin radian))))
    (set! Ycord (- Y-axis-centre-line (* hypotenuse (cos radian))))))


Finally, you are setting the same pixels to the same color in four different layers each time through the loop. It would be more efficient to just create a single layer and after you've drawn all of your pixels, create three copies of the layer (this will roughly triple the speed of your script). You may have plans to, in the future, do something different with the layers and thus wish to leave things the way they are, but as things stand your approach is suboptimal.

As a general guideline, I personally try to postpone introducing variables until they are needed, rather than pre-declaring them all at the beginning of the script. This can be helpful in minimizing the likelihood of errors in larger Scheme programs, though for typical Script-fus it is more of a personal preference.

Many thanks for your in depth feedback, its much appreciated, and more than I could have hoped for

I will keep "" (when I create the image) and "File->Create" submenu in mind when writing future scripts

And thanks for showing how to optimize the coding, for me these are excellent examples. I guess I’m trying to run before I can walk, but I’ve always thought the best way to learn is jump in with both feet, make mistakes and learn from them

I must admit I got into a real muddle near the end of the script and took the easy way out setting the same pixels four times over :oops:

At present I prefer to keep all the variables in one neat tidy block where they are easy to locate, and declare them in the order that they are used, but if this method causes problems on longer programs I will adapt

Thanks again saulgoode


Top
 Post subject: Re: A Globular Cluster (astronomical object) script
PostPosted: Tue Jan 20, 2015 11:25 am  (#9) 
Offline
GimpChat Member
User avatar

Joined: Dec 26, 2014
Posts: 198
After further studying

Re: case

I’ve changed the script to use case, much better, I can see how it works by exiting after a match and so will run faster


Re: the code below I can't get it to work, I tried removing an extra parenthesis (top line after sin radian ?) but it drew one quadrant of stars, tried other variations but quadrant always exited on = 0. I did use begin successfully in the SFC with simple equations so can see it works

saulgoode wrote:
Your code conditioned upon the quadrant value could use a little bit of optimization. Firstly, rather than performing the test twice:

Just perform the test once and combine the two calculation steps by wrapping them with (begin...):
(if (= quadrant 0)
  (begin
    (set! Xcord (+ X-axis-centre-line (* hypotenuse (sin radian)))))
    (set! Ycord (+ Y-axis-centre-line (* hypotenuse (cos radian))))))



Re: (gimp-drawable-set-pixel)

I deleted the (gimp-drawable-set-pixel layer1 Xcord Ycord 3 pixel) lines and copied the layers as per your suggestion and the script does seem to run faster.

Taking a 600 by 600 pixel image it has 360 000 pixels. When copying to a new layer all 360 000 pixels have to be set!, yet when setting pixels as I did only a few thousand are set!. I’m assuming copying the layer is faster as the program for it is compiled once as opposed to being compiled each time for each pixel when using (gimp-drawable-set-pixel), or is there something else going on ?


Top
 Post subject: Re: A Globular Cluster (astronomical object) script
PostPosted: Tue Jan 20, 2015 5:31 pm  (#10) 
Offline
Script Coder
User avatar

Joined: Apr 23, 2010
Posts: 1553
Location: not from Guildford after all
Steve wrote:
Re: the code below I can't get it to work, I tried removing an extra parenthesis (top line after sin radian ?) but it drew one quadrant of stars, tried other variations but quadrant always exited on = 0. I did use begin successfully in the SFC with simple equations so can see it works

Sorry about the mistake with the missing parenthesis. I also was lazy and only included the code for the first quadrant. That stanza would need to be repeated three more times (with the appropriate formulae) for the other quadrants. Not sure if this is the problem but since you are using the 'case' statement, I guess it is all for naught.

Steve wrote:
Taking a 600 by 600 pixel image it has 360 000 pixels. When copying to a new layer all 360 000 pixels have to be set!, yet when setting pixels as I did only a few thousand are set!. I’m assuming copying the layer is faster as the program for it is compiled once as opposed to being compiled each time for each pixel when using (gimp-drawable-set-pixel), or is there something else going on ?

That is basically the story but to elaborate a little bit more, Script-fu is by no means a fast language but the real bottleneck in most scripts is calls to PDB functions. For a relative comparison, a simple Script-fu function such as addition or multiplication takes about 5 microseconds. Whereas a procedure call to a PDB function (such as 'gimp-drawable-set-pixel') takes at least 100 microseconds -- this is the basic round-trip time that it takes for the PDB to process the function call, invoke the procedure, and return its values. This 100 microseconds is not counting how long the procedure actually takes to perform its task; of course some procedures take longer to perform (e.g., 'gimp-image-select-rectangle' or 'gimp-histogram') but for simple operations (such as setting a single pixel), the time spent performing the operation is overshadowed by the time spent traversing the PDB.

A 'gimp-layer-copy' call for a 600x600 layer takes about 2 milliseconds, since it is an internal GIMP procedure that is optimized for copying large blocks of memory. Therefore duplicating a layer can be done in about the same time as calling 'gimp-drawable-set-pixel' about 20 times.

This "PDB bottleneck" is about the same for all plug-ins, not just Script-fu. Where plug-ins (written in C, Python, Perl, etc) gain the bulk of their speed advantage is by retrieving a large region of pixels as an array with a single PDB call (such as 'gimp_pixel_rgn_init'), manipulating the data in the array (without using any PDB calls), and then making a PDB call to update the drawable with the newly processed pixel region. If a plug-in were to process an image pixel-by-pixel using PDB functions such as 'gimp-drawable-set-pixel', it would be just about as slow as a Script-fu script.

This is all just to provide a general concept of how Script-fu scripts might be better optimized for speed. It is generally a good idea to avoid pixel-by-pixel functions and to try to minimize the number of PDB calls within large loops.

_________________
Any sufficiently primitive technology is indistinguishable from a rock.


Top
 Post subject: Re: A Globular Cluster (astronomical object) script
PostPosted: Wed Jan 21, 2015 9:51 am  (#11) 
Offline
GimpChat Member
User avatar

Joined: Dec 26, 2014
Posts: 198
saulgoode wrote:
Steve wrote:
Re: the code below I can't get it to work, I tried removing an extra parenthesis (top line after sin radian ?) but it drew one quadrant of stars, tried other variations but quadrant always exited on = 0. I did use begin successfully in the SFC with simple equations so can see it works

Sorry about the mistake with the missing parenthesis.

Thanks, no worries

saulgoode wrote:
I also was lazy and only included the code for the first quadrant. That stanza would need to be repeated three more times (with the appropriate formulae) for the other quadrants. Not sure if this is the problem but since you are using the 'case' statement, I guess it is all for naught.

That’s ok, I understood the code had to be repeated for each quadrant. I’d got the script working with case which was more suited to the task, and have successfully used if/begin on a simpler script so am happy with that.

saulgoode wrote:
Steve wrote:
Taking a 600 by 600 pixel image it has 360 000 pixels. When copying to a new layer all 360 000 pixels have to be set!, yet when setting pixels as I did only a few thousand are set!. I’m assuming copying the layer is faster as the program for it is compiled once as opposed to being compiled each time for each pixel when using (gimp-drawable-set-pixel), or is there something else going on ?

That is basically the story but to elaborate a little bit more, Script-fu is by no means a fast language but the real bottleneck in most scripts is calls to PDB functions. For a relative comparison, a simple Script-fu function such as addition or multiplication takes about 5 microseconds. Whereas a procedure call to a PDB function (such as 'gimp-drawable-set-pixel') takes at least 100 microseconds -- this is the basic round-trip time that it takes for the PDB to process the function call, invoke the procedure, and return its values. This 100 microseconds is not counting how long the procedure actually takes to perform its task; of course some procedures take longer to perform (e.g., 'gimp-image-select-rectangle' or 'gimp-histogram') but for simple operations (such as setting a single pixel), the time spent performing the operation is overshadowed by the time spent traversing the PDB.

A 'gimp-layer-copy' call for a 600x600 layer takes about 2 milliseconds, since it is an internal GIMP procedure that is optimized for copying large blocks of memory. Therefore duplicating a layer can be done in about the same time as calling 'gimp-drawable-set-pixel' about 20 times.

This "PDB bottleneck" is about the same for all plug-ins, not just Script-fu. Where plug-ins (written in C, Python, Perl, etc) gain the bulk of their speed advantage is by retrieving a large region of pixels as an array with a single PDB call (such as 'gimp_pixel_rgn_init'), manipulating the data in the array (without using any PDB calls), and then making a PDB call to update the drawable with the newly processed pixel region. If a plug-in were to process an image pixel-by-pixel using PDB functions such as 'gimp-drawable-set-pixel', it would be just about as slow as a Script-fu script.

This is all just to provide a general concept of how Script-fu scripts might be better optimized for speed. It is generally a good idea to avoid pixel-by-pixel functions and to try to minimize the number of PDB calls within large loops.


Very interesting, thanks for taking the time, I’ll bear these points in mind when writing scripts so as to optimize run speed


Top
Post new topic Reply to topic  [ 11 posts ] 

All times are UTC - 5 hours [ DST ]


   Similar Topics   Replies 
No new posts Attachment(s) Create a Shape Cluster Photo Display plugin

5

No new posts Map to Object

3

No new posts Attachment(s) Quick and Dirty Lightning Object

2

No new posts is there a way to edit all the occurences of a object on a layer?

1

No new posts Attachment(s) WRITING A TEXT IN THE FRONT AROUND AN OBJECT

14



* Login  



Powered by phpBB3 © phpBB Group