Graphivz does not render edge label when it's connecting two nodes with shape=point - rendering

I have the following graph description:
graph G {
{rank=same a b}
a[shape=point]
b[shape=point]
a -- b [label=e];
}
However, it outputs a single edge without a label (running graphviz with dot -Tpdf -o test.pdf test.dot):
Rendering to PNG yields same result. If I render it to PDF and then look for an "e" in the document, the following are is highlighted:
So, the edge label is here but it's invisible somewhy.
Surprisingly, if I switch rank direction, everything works:
graph G {
rankdir=LR;
a[shape=point]
b[shape=point]
a -- b [label=e];
}

Not an answer really as I cannot provide any explanation but what I have observed is: As long as there is any other character / label rendered in the graph,
the e will also be rendered.
Interestingly enough this even applies for labels that are explicitly set to invisible, so if you compile
graph G
{
{ rank=same; a; b; }
a [ shape = point ];
b [ shape = point ];
a -- b [ label = "e" ];
\\ add this
c [ style = invis ];
}
you get what you want:
The graph area will increase, though.

Related

How can I implement 2d subscripts via AT-POS for different classes?

here is an MRE (showing two attempts, with debug left in to be helpful) to try and get 2d subscripting working with AT-POS across a DataFrame that has columns of Series...
class Series does Positional {
has Real #.data = [0.1,0.2,0.3];
method AT-POS( $p ) {
#!data[$p]
}
}
class DataFrame does Positional {
has Series #.series;
#`[ ATTEMPT #1
method AT-POS( $p, $q? ) {
given $q {
when Int { #say 'Int';
#!series[$p][$q]
}
when Whatever { #say '*';
#!series[$p].data
}
default { #say 'default';
#!series[$p]
}
}
}
#]
# ATTEMPT #2
method AT-POS(|c) is raw { #`[dd c;] #!series.AT-POS(|c) }
}
my $df = DataFrame.new( series => [Series.new xx 3] );
say $df[1].data; #[0.1 0.2 0.3]
say $df[1][2]; #0.3
say $df[0,1]; #(Series.new(data => $[0.1, 0.2, 0.3]) Series.new(data => $[0.1, 0.2, 0.3]))
say $df[1;2]; #0.3
say $df[1;*]; #got (0.1) ... expected [0.1 0.2 0.3]
say $df[*;1]; #got (0.2) ... wanted [0.2 0.2 0.2]
I already researched on SO and found three related questions here, here and here ... and the attempt #2 in my code seeks to apply #lizmats Answer to the third one. Encouragingly both the attempts in my MRE have the same behaviour. But I cannot workout
why the when Whatever {} option is not entered (attempt #1)
what the |c is doing - even though I can see that it works in the single subscript case (attempt #2)
I have done some experimenting with multi postcircumfix:<[ ]>( DataFrame:D $df, #slicer where Range|List ) is export {} but this seems to overcomplicate matters.
==================
Great answer from #jonathan building on the original from #Lizmat - thanks! Here is the final, working code:
class Series does Positional {
has Real #.data = [0.1,0.2,0.3];
method elems {
#!data.elems
}
method AT-POS( |p ) is raw {
#!data.AT-POS( |p )
}
}
class DataFrame does Positional {
has Series #.series;
method elems {
#!series.elems
}
method AT-POS( |p ) is raw {
#!series.AT-POS( |p )
}
}
my $df = DataFrame.new( series => Series.new xx 3 );
say $df[1].data; #[0.1 0.2 0.3]
say $df[1][2]; #0.3
say $df[0,1]; #(Series.new(data => $[0.1, 0.2, 0.3]) Series.new(data => $[0.1, 0.2, 0.3]))
say $df[1;2]; #0.3
say $df[1;*]; #(0.1 0.2 0.3)
say $df[*;1]; #(0.2 0.2 0.2)
The AT-POS method is only ever passed integer array indices.
The logic to handle slicing (with *, ranges, other iterables, the zen slice) is located in the array indexing operator, which is implemented as the multiple-dispatch subroutine postcircumfix:<[ ]> for single-dimension indexing and postcircumfix:<[; ]> for multi-dimension indexing. The idea is that a class that wants to act as an array-alike need not worry about re-implementing all of the slicing behavior and, further, that the slicing behavior will behave consistently over different user-defined types.
For slicing to work, one must implement elems as well as AT-POS. Adding:
method elems() { #!data.elems }
Is Series and:
method elems() { #!series.elems }
In DataFrame gives the results you're looking for.
If one really wants different slicing semantics, or a far more efficient implementation than the standard one is possible, one can also add multi candidates for the indexing operator (remembering to mark them is export).
This answer is simply an elaboration of the point #raiph made in a comment:
You may be able to simplify the code by using handles
Indeed you can – so much so that I thought it was worth showing what that would look like in a code block without a comment's formatting limits.
Using handles, you can simplify each of the two classes from 9 non-whitespace lines to 3:
class Series does Positional {
has Real #.data handles <elems AT-POS> = [0.1,0.2,0.3];
}
class DataFrame does Positional {
has Series #.series handles <elems AT-POS>;
}
(or you could even have each class on 1 line, if you format them the way I'd be tempted to.)
This code produces all the same results to the say statements from the code in the question.

Getting "value without a container" error

Got this:
for $config.IO.slurp.lines <-> $l {
$l .= trim;
...
}
Get this:
t/01-basic.rakutest ..3/5
Parameter '$l' expects a writable container (variable) as an argument,
but got '# karabiner config file' (Str) as a value without a container.
in sub generate_file at...
I've read the docs on containers but it didn't shed any light on what I can do in this situation aside from maybe assigning $l to a scalar variable, which seems hacky. Is there a way I can containerize $l?
The issue is really that .lines does not produce containers. So with <->, you would bind to the value, rather than a container. There are several ways to solve this, by containerizing as you suggested:
for $config.IO.slurp.lines -> $l is copy {
$l .= trim;
...
}
But that only makes sense if you want to do more changes to $l. If this is really just about trimming the line that you receive, you could do this on the fly:
for $config.IO.slurp.lines>>.trim -> $l {
...
}
Or, if you need to do more pre-processing $l, use a .map:
for $config.IO.slurp.lines.map({
.trim.subst("foo","bar",:g)
}) -> $l {
...
}
Maybe below is what you want? Generally, you read a file via slurp you can comfortably handle its size, or you read a file via lines if you want input taken in lazily, one-line-at-a-time:
my $config = 'alphabet_one_letter_per_line.txt';
my $txt1 = $config.IO.slurp;
$txt1.elems.say; #1
$txt1.print; #returns alphabet same as input
my $txt2 = $config.IO.lines;
$txt2.elems.say; #26
$txt2.join("\n").put; #returns alphabet same as input
Above, you get only 1 element when slurping, but 26 elements when reading lines. As you can see from the above code, there's no need to "...(assign) $l to a scalar variable..." because there's no need to create (temporary variable) $l.
You can store text in #txt arrays, and get the same number of elements as above. And you can just call routines on your stored text, as you have been doing (example below continues $txt2 example above):
$txt2.=map(*.uc);
say $txt2;
Sample Output:
(A B C D E F G H I J K L M N O P Q R S T U V W X Y Z)
[Note, this question seems to have triggered questions on the use of $txt2.=map(*.uc); versus $txt2.=uc;. My rule-of-thumb is simple: if the data structure I'm working on has more than one element, I map using * 'whatever-star' to address the routine call to each element].
https://docs.raku.org/

How to apply virtual apperture with 4D-STEM dataset in EFFICIENT way?

I would like to apply arbitrarily defined bit mask as virtual aperture and apply it to 4D-STEM data set in an EFFICIENT way.
I did it using the SliceN function and apply the mask pixel-by-pixel, which is very slow for large datasets. How to optimize it to so to run faster?
Image 4DSTEM := GetFrontImage() // dimention [ScanX, ScanY, Dx, Dy]
Image mask: = iradius // just an arbitrary mask (aperture)
Image out // dimention [ScanX, ScanY]
for (number i=0; i<ScanX; i++)
{ for (number j=0; j<ScanY; j++)
{
Diff2D = 4DSTEM.SliceN(4,2,i,j,0,0,2,Dx,1,3,Dy,1)
out.setpixel(i,j, sum(diff2D*mask))
}
}
out.showimage()
for an [100,100,512,512] dataset, that took few minutes to finish. When I have to repeat the operation several times, that is way to slow compare to matrix operation. but I dont know how to make it in an efficient way.
Thanks!
you're hitting the limitations of scripting languages here. Using sliceN is already pretty much the optimum you can get to, unfortunately. Everything else in speed optimization requires parallelized, compiled code. (i.e. you could code C++ code and use the SDK to compile your own plugin.)
However, there is a bit of room for improvement over your example.
First of all, your example above doesn't run :c) But that is quickly fixed.
Point #1:
Try to avoid number type casting. DM script only knows number but internally there is a difference between the proper number types (integer, floating point, signed/unsigned, byte-size). The script languages uses real-4-byte as the default unless told differently explicitly. And some methods will return real-4-byte by default. For this reason, the processing will be fastest, if both data and mask use real-4-byte data as well.
In my testing, the time-difference between running with uint16 data plus uint8 mask and *real4 data plus real4 mask) was significant! Nearly 30% time difference.
Point #2:
Don't copy you sliced image! Use := not = for your Dif2D.
The SliceN command returns an expression directly addressing the required memory. You can use it directly in any other expression (like I do below) or you can assign an image variable to it using := to give it a name.
The speed increase is not huge, but it's one copy-operation less per loop iteration.
Point #3:
You additional knowledge: Now for arbitrary masks there is not much you can do, but most often masks are zero-valued over large stretches and it is possible to define a smaller ROI containing all non-zero points. If this is the case, you can limit your math operations to that region.
i.e. instead of multiplying the whole DP with the same sized mask, just use a smaller mask and use the according sub-section of the DP.
This can actually make a big difference, but it will depend on your mask.
Of course you need to "find" this ROI first. In my script below I'm having a helper method to do that, utilizing the comparatively fast max() command and image rotation as trick for speed-up.
Point #4:
...would be to get rid of the double-for loop and replace it with image-expressions. Unfortunately, DigitalMicrograph does currently (GMS 3.3) not support this for 4D or 5D data.
The script below executed on a [53 x 52 x 512 x 512] STEM DI (of real-4 byte data) gave me the following timings:
Original: 12.80910 sec
Test 1 : 10.77700 sec
Test 2 : 1.83017 sec
// Helper class for timing
class CTimer{
number s
string n
~CTimer(object self){result("\n"+n+": "+ (GetHighResTickCount()-s)/GetHighResTicksPerSecond()+" sec");}
object Start(object self, string n_) { n=n_; s=GetHighResTickCount(); return self;}
}
// Helper method to find best non-zero containing ROI
void GetNonZeroArea( image src, number &t, number &l, number &b, number &r )
{
image work = !!src // Make a binary image which is 0 only where src==0
number d
max(work,d,t) // get "first" non-zero pixel coordinate, this is y = dist from TOP
rotateRight(work) // rotate image right
max(work,d,l) // get "first" non-zero pixel coordinate, this is y = dist from LEFT
rotateRight(work) // rotate image right
max(work,d,b) // get "first" non-zero pixel coordinate, this is y = dist from BOTTOM
b = work.ImageGetDimensionSize(1) - b // Opposite side!
rotateRight(work) // rotate image right
max(work,d,r) // get "first" non-zero pixel coordinate
r = work.ImageGetDimensionSize(1) - r // Opposite side!
}
// The original proposed script (plus fixes to make it actually run)
image Original(image STEM4D, image mask)
{
Number ScanX = STEM4D.ImageGetDimensionSize(0)
Number ScanY = STEM4D.ImageGetDimensionSize(1)
Number Dx = STEM4D.ImageGetDimensionSize(2)
Number Dy = STEM4D.ImageGetDimensionSize(3)
Image out := RealImage("Test1",4,ScanX,ScanY)
for (number i=0; i<ScanX; i++)
{ for (number j=0; j<ScanY; j++)
{
image Diff2D = STEM4D.SliceN(4,2,i,j,0,0,2,Dx,1,3,Dy,1)
out.setpixel(i,j, sum(Diff2D*mask))
}
}
return out
}
// Remove copying the slice, just reference it
image Test1(image STEM4D, image mask)
{
Number ScanX = STEM4D.ImageGetDimensionSize(0)
Number ScanY = STEM4D.ImageGetDimensionSize(1)
Number Dx = STEM4D.ImageGetDimensionSize(2)
Number Dy = STEM4D.ImageGetDimensionSize(3)
Image out := RealImage("Test1",4,ScanX,ScanY)
for (number i=0; i<ScanX; i++)
{ for (number j=0; j<ScanY; j++)
{
image Diff2D := STEM4D.SliceN(4,2,i,j,0,0,2,Dx,1,3,Dy,1)
out.setpixel(i,j, sum(Diff2D*mask))
}
}
return out
}
// Limit mask size to what is needed!
image Test2(image STEM4D, image mask )
{
Number ScanX = STEM4D.ImageGetDimensionSize(0)
Number ScanY = STEM4D.ImageGetDimensionSize(1)
Number Dx = STEM4D.ImageGetDimensionSize(2)
Number Dy = STEM4D.ImageGetDimensionSize(3)
Image out := RealImage("Test1",4,ScanX,ScanY)
Number t,l,b,r
GetNonZeroArea(mask,t,l,b,r)
Number w = r - l
Number h = b - t
image subMask := mask.slice2(l,t,0, 0,w,1, 1,h,1 )
for (number i=0; i<ScanX; i++)
for (number j=0; j<ScanY; j++)
out.setpixel(i,j, sum(STEM4D.SliceN(4,2,i,j,l,t,2,w,1,3,h,1)*subMask))
return out
}
Image src := GetFrontImage() // dimention [ScanX, ScanY, Dx, Dy]
Number ScanX = src.ImageGetDimensionSize(0)
Number ScanY = src.ImageGetDimensionSize(1)
Number Dx = src.ImageGetDimensionSize(2)
Number Dy = src.ImageGetDimensionSize(3)
Number r = 50 // mask radius
Image maskImg := RealImage("Mask",4,Dx,Dy)
maskImg = iradius < r ? 1 : 0 // just an aperture mask
image resultImg
{
object timer = Alloc(CTimer).Start("Original")
resultImg := Original(src,maskImg)
}
resultImg.SetName("Oringal")
resultImg.ShowImage()
{
object timer = Alloc(CTimer).Start("Test 1")
Test1(src,maskImg).ShowImage()
}
resultImg.SetName("Test 1")
resultImg.ShowImage()
{
object timer = Alloc(CTimer).Start("Test 2")
Test2(src,maskImg).ShowImage()
}
resultImg.SetName("Test 2")
resultImg.ShowImage()
Compiled code comparison:
Now, it should be added that the above script still is rather slow. Because it is iterating and using script language. The fully compiled c++ code of DigitalMicrograph is much faster. So if you have the licensed packages giving you the SI menu, then you want to use the SI/Map/Signal command. This is near-instantaneous for the example STEM DI I've mentioned above. My other answer shows how one could utilize this functionality by script.
As mentioned in my other answer, a real speed-win comes when compiled, parallelized code is used. DigitalMicrograph does this, after all, in the available SI "signal" map functionality. This feature is not available in the free version, but if you have Spectrum-Imaging acquisition, you most likely have the appropriated license as well.
The answer below utilizes this functionality by accessing the UI with the command ChooseMenuItem() and applying a few more tricks. The script is a bit lengthy, but its parts also show some other nice tricks worthwhile knowing:
TestSignalIntegrationInSI is the main script demoing how things can work.
CreatePickerByScript shows how one can create picker-spectra on SIs. This is used to open a 'Picker Diffraction Pattern' image from the STEM DI.
AddTestMasksToDP_ROIs programmatically adds ROIs to the diffraction pattern to be used as mask
AddTestMasksToDP_Threshold programmatically adds an intensity-threshold mask to be used as mask.
AddTestMasksToDP_DPMasks programmatically adds the various types of diffraction-masks to be used as mask
GetIntegratedSignalViaSIMenu is the central step of the script. With a picker-DP and required 'masks' on it front-most, the menu command is called to perform the signal-extraction (as fast as possible.) Then the displayed result-image is returned.
GetNewestImage is just a utility method showing how on can access the latest memory-created image.
Here is the script:
image GetNewestImage()
{
// New images get the next higher imageID.
// This can be used to identify the "latest" created image.
if ( 0 == CountImages() ) Throw( "No image in memory!" )
// We create a temp. image to get the uppder limit
number lastID = RealImage("Dummy",4,1).ImageGetID()
// Then we search for the next lower existing one
image lastImg
for( number ID = lastID - 1; ID>0; ID-- )
{
lastImg := FindImageByID(ID)
if ( lastImg.ImageIsValid() ) break
}
return lastImg
}
image CreatePickerByScript( image SI, number t, number l, number b, number r )
{
if ( SI.ImageGetNumDimensions()<3 ) Throw( "Sorry, LineScans are not supprorted here." )
// Adding a non-volatile ROI of specific RoiNAME acts as if using
// the picker-tool. The ID string must be unique!
ROI pickerROI = NewROI()
pickerROI.RoiSetVolatile( 0 )
string uniqueID = GetDate(0)+"#"+GetTime(1)+";"+round(random()*1000)
pickerROI.RoiSetName( "SICursor(##"+uniqueID+"##)" )
SI.ImageGetImageDisplay(0).ImageDisplayAddROI( pickerROI )
// This creates the picker image.
// So the child is now the "newest" image in memory
image child := GetNewestImage()
return child
}
void AddTestMasksToDP_ROIs( image DP )
{
// Add ROIs to the DP which are your masks (any numebr and type of ROI works)
imageDisplay DPdisp = DP.ImageGetImageDisplay(0)
number dpX = DP.ImageGetDimensionSize(0)
number dpY = DP.ImageGetDimensionSize(1)
// Only simple RECT ROIs are supported
ROI maskRoi1 = NewROI()
maskRoi1.ROISetRectangle( dpY*0.1, dpX*0.1, dpY*0.8, dpX*0.3 )
DPdisp.ImageDisplayAddROI(maskRoi1)
// Arbitrary multi-vertex (use for ovals etc.)
ROI maskRoi2 = NewROI()
maskRoi2.ROISetRectangle( dpY*0.7, dpX*0.1, dpY*0.9, dpX*0.9 )
DPdisp.ImageDisplayAddROI(maskRoi2)
}
void AddTestMasksToDP_Threshold( image DP )
{
// Add intensity treshhold mask (highest 95% intensity range)
imageDisplay DPdisp = DP.ImageGetImageDisplay(0)
DPdisp.RasterImageDisplaySetThresholdOn( 1 )
number low = max(DP) * 0.05
number high = max(DP)
DPdisp.RasterImageDisplaySetThresholdLimits( low, high )
}
void AddTestMasksToDP_DPMasks( image DP )
{
// Add Diffraction masks to the DP
imageDisplay DPdisp = DP.ImageGetImageDisplay(0)
// Spot masks (always symmetric pair)
Component spotMask = NewComponent(8,0,0,0,0) // 8 = Spotmask
spotMask.ComponentSetControlPoint(4, 0, 0,0) // 4 = TopLeft of one spot [Size only]
spotMask.ComponentSetControlPoint(7,10,10,0) // 7 = BottomRight of one spot [Size only]
spotMask.ComponentSetControlPoint(8,150,0,0) // 8 = Spot position [center]
DPdisp.ComponentAddChildAtEnd(spotMask)
// Bandpass mask (Only circles are correctly supported)
Component bandpassMask = NewComponent(15,0,0,0,0) // 15 = Bandpass (ring)
number r1 = 100
number r2 = 120
bandpassMask.ComponentSetControlPoint(7,r1,r1,0) // 7 = BottomRight of one ring [Size only]
bandpassMask.ComponentSetControlPoint(14,r2,r2,0) // 14 = BottomRight of one ring [Size only]
DPdisp.ComponentAddChildAtEnd(bandpassMask)
// Wege mask (symmetric)
Component wedgeMask = NewComponent(19,0,0,0,0) // 19 = wedgemask (ringsegment)
wedgeMask.ComponentSetControlPoint(9,10,20,0) // 9 = One wedge vector
wedgeMask.ComponentSetControlPoint(10,-20,40,0) // 10 = Other wedge vector
DPdisp.ComponentAddChildAtEnd(wedgeMask)
// Array mask (symmetric)
Component arrayMask = NewComponent(9,0,0,0,0) // 9 = arrayMask (ringsegment)
arrayMask.ComponentSetControlPoint(9,-70,-60,0) // 9 = One array vector
arrayMask.ComponentSetControlPoint(10,99,-99,0) // 10 = Other array vector
arrayMask.ComponentSetControlPoint(4, 0, 0,0) // 4 = TopLeft of one spot [Size only]
arrayMask.ComponentSetControlPoint(7,20,20,0) // 7 = BottomRight of one spot [Size only]
DPdisp.ComponentAddChildAtEnd(arrayMask)
}
image GetIntegratedSignalViaSIMenu( image pickerChild )
{
// Call the Menu to do the work
// The picker-spectrum or DP needs to be front-most
pickerChild.SelectImage()
ChooseMenuItem("SI","Map","Signal")
// The created signal map is NOT the newest image
// (some internal iamges are created for the mask)
// but it is the front-most displayed one.
image signalMap := GetFrontImage()
return signalMap
}
image GetMaskFromSignalMap( image signalMap, number DPx, number DPy )
{
// The actual mask is stored in the tags
string tagPath = "Processing:[0]:Parameters:Mask"
tagGroup tg = signalMap.ImageGetTagGroup()
if ( !tg.TagGroupDoesTagExist(tagPath) )
Throw( "Sorry, no mask tag found." )
image mask := RealImage("Mask",4,DPx, DPy )
if ( !tg.TagGroupGetTagAsArray(tagPath,mask) )
Throw( "Sorry, could not retrieve mask. Maybe wrong size?" )
return mask
}
void TestSignalIntegrationInSI()
{
image STEMDI := GetFrontImage()
image DP := STEMDI.CreatePickerByScript(0,0,1,1)
if ( TwoButtonDialog( "Add ROIs as mask?", "Yes", "No" ) )
AddTestMasksToDP_ROIs( DP )
else if ( TwoButtonDialog( "Add intensity treshold as mask?", "Yes", "No" ) )
AddTestMasksToDP_Threshold( DP )
else if ( TwoButtonDialog( "Add diffraction masks as mask?", "Yes", "No" ) )
AddTestMasksToDP_DPMasks( DP )
image signalMap := GetIntegratedSignalViaSIMenu( DP )
number dpX = DP.ImageGetDimensionSize(0)
number dpY = DP.ImageGetDimensionSize(1)
// We may want to close the DP again. No longer needed
//DP.DeleteImage()
// Verification: Get Mask image form SignalMap
image usedMask := GetMaskFromSignalMap( signalMap, dpX, dpY )
usedMask.SetName( "This mask was used." )
usedMask.ShowImage()
}
TestSignalIntegrationInSI()
The solution below utilizes the intrinsic expression loops by performing in-place multiplication and then projection.
Disappointingly, it turns out the solution is actually a bit slower then the for-loop with the SliceN command.
For the same test-data of size [53 x 52 x 512 x 512] the resulting timing is:
Data copy: 1.28073 sec
Inplace multiply: 30.1978 sec
Project 1/2: 1.1208 sec
Project 2/2: 0.0019557 sec
InPlace multiplication with projections (total): 32.9045 sec
InPlace multiplication with projections (total): 34.9853 sec
// Helper class for timing
class CTimer{
number s
string n
~CTimer(object self){result("\n"+n+": "+ (GetHighResTickCount()-s)/GetHighResTicksPerSecond()+" sec");}
object Start(object self, string n_) { n=n_; s=GetHighResTickCount(); return self;}
}
image MaskMultipliedSum( image STEM4D, image MASK2D, number copyFirst )
{
// Boring feasability checks...
if ( 4 != STEM4D.ImageGetNumDimensions() )
Throw( "Input data is not 4D." )
if ( 2 != MASK2D.ImageGetNumDimensions() )
Throw( "Input mask is not 2D." )
Number ScanX = STEM4D.ImageGetDimensionSize(0)
Number ScanY = STEM4D.ImageGetDimensionSize(1)
Number Dx = STEM4D.ImageGetDimensionSize(2)
Number Dy = STEM4D.ImageGetDimensionSize(3)
if ( Dx != MASK2D.ImageGetDimensionSize(0) )
Throw ("X dimension of mask does not match input data." )
if ( Dy != MASK2D.ImageGetDimensionSize(1) )
Throw ("Y dimension of mask does not match input data." )
// Do the maths!
image workCopy4D
if ( copyFirst )
{
object timer = Alloc(CTimer).Start("Data copy")
workCopy4D = STEM4D
}
else
workCopy4D := STEM4D
{
object timer = Alloc(CTimer).Start("Inplace multiply")
workCopy4D *= MASK2D[idimindex(2),idimindex(3)]
}
// Now we want to "sum up" over Dx and Dy
image p1,p2
{
object timer = Alloc(CTimer).Start("Project 1/2")
p1 := project( workCopy4D, 3 )
}
{
object timer = Alloc(CTimer).Start("Project 2/2")
p2 := project( p1, 2 )
}
return p2
}
image stack4D, mask2D
If ( GetTwoLabeledImagesWithPrompt("Please select 4D data and 2D mask", "Select input", "4D data", stack4D, "2D mask", mask2D ) )
{
number doCopy = TwoButtonDialog("Create workcopy?","Yes (takes time)","No (overwrites input data!)")
object timer = Alloc(CTimer).Start("InPlace multiplication with projections (total)")
MaskMultipliedSum(stack4D,mask2D,doCopy).ShowImage()
}

Optimising MST using Prim's algorithm from O(n^3) to O(n^2)

Following is my pseudocode for converting a connected graph to MST using Prim's algorithm. I am however getting a complexity of n^3 rather then n^2. Please help me figure out the non-required steps.I have an adjacency matrix "a" to store the weight of graph edges and a 2D matrix "check" storing "1" for vertices already in the tree and "0" for remaining.
Please also note that this can be done in nlog(n) also, but I don't want to refer any existing pseudocode and want to try it on my own. I would appreciate an answer optimizing my own approach.
Initialize check. //check[0][1]==1
while(--no_of_vertices)
{
minimum_outer = infinite
for(i from 1 to no_of_vertices)
{
minimum_inner = infinite
select i from check having value 1
for(j from 1 to no_of_vertices )
{
select j from check having value 0
if(a[i-j] < minimum_inner)
minimum_inner = a[i-j]
temp_j = j;
}
if(minimum_inner<minimum_outer)
{
minimum_outer = minimum_inner
final_i = i
final_j = temp_j
}
}
//until here basically what I have done is, selected an i-j with lowest
//weight where "i" is chosen from vertices already in MST and "j" from
//remaining vertices
check[final_j][1] = 1
print final_i - final_j
cost_of_mst += a[final_i][final_j]
}
The reason your algorithm runs with O(V^3) time is because in each iteration you are going through the entire adjacency matrix, which takes O(V^2) and performs some redundant actions.
Whenever you are adding a vertex to the spanning tree, there are at most |V-1| new edges that may be added to the solution. At each iteration, you should only check if these edges changed the minimal weight to each of the other vertices.
The algorithm should look like:
1. Select a random vertex v, add v to S, assign an array A where A[i] = d{v, i}
2. While there are vertices that belong to G and not to S do:
2.1. Iterate through A, select the minimum value A[i], add vertex i to S
2.2. for each edge e={i, j} connected to vertex i do:
2.2.1. if d{i, j} < A[j] then A[j] = d{i ,j}
This way you are performing O(V) actions for each vertex you add instead of O(V^2), and the overall running time is O(V^2)
Here's an edit to your code:
Select a random vertex x
Initialize DistanceTo // DistanceTo[i] = d{x, i}
Initialize Visited // Visited[i] = false if i!=x, Visited[x] = true
while(--no_of_vertices)
{
min_val = infinite
min_index = 1;
for(i from 1 to DistanceTo.size)
{
if (Visited[i] = false && DistanceTo[i] < min_val)
{
min_val = DistanceTo[i]
min_index = i
}
}
Visited[min_index] = true
For(i from 1 to Distance.size)
{
if (Visited[i] = false && d{min_index, i} < DistanceTo[i])
{
DistanceTo[i] = d{min_index, i}
}
}
print edge {min_index, i} was added to the MST
cost_of_mst += d{min_index, i}
}

Make edges not clickable in Roassal visualization from within a Glamour browser

I draw a dynamic callgraph with Roassal from within a Glamour browser in Pharo 2.0.
By default not only the nodes, but also the edges are clickable.
As i have no further information to display for the edges, i want them not to be clickable. How do i remove the "clickability"?
That's how i draw the callgraph from within a Glamour browser:
methodsUnderTestAsCallGraphIn: constructor
constructor roassal
painting: [ :view :testFailure |
view shape rectangle
size: 30;
fillColor: ThreeColorLinearNormalizer new.
view nodes: (tests methodsUnderTest: testFailure).
view shape arrowedLine.
view edges: (tests methodsUnderTest: testFailure) from: #yourself toAll: #outgoingCalls.
view treeLayout ];
title: 'Callgraph of methods under test'
I think GLMRoassalPresentation>>renderOn: is responsible for adding the "clickability":
[...]
self shouldPopulateSelection ifTrue: [
aView raw allElementsDo: [:each |
each on: ROMouseClick do: [:event | self selection: each model ]] ].
[...]
I want to to keep this behaviour for the nodes, but not for the edges.
It helps to have a self contained example to clarify the behaviour you want, so I've re-framed your question.
With the two commented-out lines , I guess is the behaviour you don't want. Does uncommmenting those two lines provide the behaviour you want?
browser := GLMTabulator new.
browser column: #myRoassal ; column: #mySelection.
browser transmit
to: #myRoassal ;
andShow:
[ : aGLMPresentation |
aGLMPresentation roassal
painting:
[ : view : numbers | |edges|
view shape rectangle ; withText ; size: 30.
view nodes: numbers.
view interaction noPopup.
view edges: numbers from: [ :x | x / 2] to: [ :x | x ].
" view edges do: [ :edge | edge model:#doNotSelectMe ]."
view treeLayout.
].
].
browser transmit
to: #mySelection ;
from: #myRoassal ;
" when: [ :selection | selection ~= #doNotSelectMe ] ;"
andShow:
[ : aGLMPresentation |
aGLMPresentation text
display: [ : selectedItem | selectedItem asString ]
].
browser openOn: (1 to: 10).
Unfortunately, this is not possible at the moment because the clicking is hardcoded in GLMRoassalPresentation. However, you are right that we should find a solution, so I opened an issue:
http://code.google.com/p/moose-technology/issues/detail?id=981
I am not sure what you mean by "clickability". You have no interaction defined, so the default interaction is a simple popup. If you want to remove the popup, then just insert a "view interaction noPopup". Try this in a fresh Roassal easel:
view shape rectangle size: 40.
view nodes: #(1 2).
view interaction noPopup.
view edgesFrom: 1 to: 2.