What is the best way to define spline functions in PMML? - spline

Has anyone defined a spline function (i.e. defineFuction) in PMML?
There is quite a few parameters that need to be defined, with a fairly lengthy math. For example, for a predictor with a 3-knot restrictive cubic spline, I have seven parameters (including two coefficients, three knots, one reference point and one predictor name). The math includes a bit of exponential, max statements, etc.
Here is an example of my Javascript code to calculate the value from a 3-knot RCS.
function spline3(exp_value, exp_mean, exp_coef, exp_coef1, knot1, knot2, knot3) {
var step1 = exp_coef*(exp_value-exp_mean);
var step2 = Math.pow((knot3 - knot1),(2/3));
var step3 = Math.pow(Math.max((exp_value - knot1)/step2,0), 3);
var step4 = ((knot2 - knot1) * Math.pow(Math.max((exp_value - knot3)/step2,0), 3));
var step5 = (knot3 - knot1) * Math.pow(Math.max((exp_value - knot2)/ step2 ,0), 3);
var step6 = (knot3 - knot2);
var output = (step3 + step4 - step5/step6) * exp_coef1 + step1;
return output ;
}

Related

Model Shakes when moved long distance - Godot

I am making a space game in Godot and whenever my ship is a big distance away from (0,0,0) every time I move the camera or the ship, it shakes violently. Here is my code for moving the ship:
extends KinematicBody
export var default_speed = 500000
export var max_speed = 5000
export var acceleration = 100
export var pitch_speed = 1.5
export var roll_speed = 1.9
export var yaw_speed = 1.25
export var input_response = 8.0
var velocity = Vector3.ZERO
var forward_speed = 0
var vert_speed = 0
var pitch_input = 0
var roll_input = 0
var yaw_input = 0
var alt_input = 0
var system = "System1"
func _ready():
look_at(get_parent().get_node("Star").translation, Vector3.UP)
func get_input(delta):
if Input.is_action_pressed("boost"):
max_speed = 299792458
acceleration = 100
else:
max_speed = default_speed
acceleration = 100
if Input.is_action_pressed("throttle_up"):
forward_speed = lerp(forward_speed, max_speed, acceleration * delta)
if Input.is_action_pressed("throttle_down"):
forward_speed = lerp(forward_speed, 0, acceleration * delta)
pitch_input = lerp(pitch_input, Input.get_action_strength("pitch_up") - Input.get_action_strength("pitch_down"), input_response * delta)
roll_input = lerp(roll_input, Input.get_action_strength("roll_left") - Input.get_action_strength("roll_right"), input_response * delta)
yaw_input = lerp(yaw_input, Input.get_action_strength("yaw_left") - Input.get_action_strength("yaw_right"), input_response * delta)
func _physics_process(delta):
get_input(delta)
transform.basis = transform.basis.rotated(transform.basis.z, roll_input * roll_speed * delta)
transform.basis = transform.basis.rotated(transform.basis.x, pitch_input * pitch_speed * delta)
transform.basis = transform.basis.rotated(transform.basis.y, yaw_input * yaw_speed * delta)
transform.basis = transform.basis.orthonormalized()
velocity = -transform.basis.z * forward_speed * delta
move_and_collide(velocity * delta)
func _on_System1_area_entered(area):
print(area, area.name)
system = "E"
func _on_System2_area_entered(area):
print(area, area.name)
system = "System1"
Is there any way to prevent this from happening?
First of all, I want to point out, that this is not a problem unique to Godot. Although other engines have automatic fixes for it.
This happens because the precision of floating point numbers decreases as it goes away form the origin. In other words, the gap between one floating number and the next becomes wider.
The issue is covered in more detail over the game development sister site:
Why loss of floating point precision makes rendered objects vibrate?
Why does the resolution of floating point numbers decrease further from an origin?
What's the largest "relative" level I can make using float?
Why would a bigger game move the gameworld around the Player instead of just moving a player within a gameworld?
Moving player inside of moving spaceship?
Spatial Jitter problem in large unity project
Godot uses single precision. Support for double precision has been added in Godot 4, but that just reduces the problem, it does not eliminate it.
The general solution is to warp everything, in such way that the player is near the origin again. So, let us do that.
We will need a reference to the node we want to keep near the origin. I'm going to assume which node it is does not change during game play.
export var target_node_path:NodePath
onready var _target_node:Spatial = get_node(target_node_path)
And we will need a reference to the world we need to move. I'm also assuming it does not change. Furthermore, I'm also assuming the node we want to keep near the origin is a child of it, directly or indirectly.
export var world_node_path:NodePath
onready var _world_node:Node = get_node(target_node_path)
And we need a maximum distance at which we perform the shift:
export var max_distance_from_origin:float = 10000.0
We will not move the world itself, but its children.
func _process() -> void:
var target_origin := _target_node.global_transform.origin
if target_origin.length() < max_distance_from_origin:
return
for child in _world_node.get_children():
var spatial := child as Spatial
if spatial != null:
spatial.global_translate(-target_origin)
Now, something I have not seen discussed is what happens with physics objects. The concern is that The physics server might be trying to move them in the old position (in practice this is only a problem with RigidBody), and it will overwrite what we did.
So, if that is a problem… We can handle physic objects with a teleport. For example:
func _process() -> void:
var target_origin := _target_node.global_transform.origin
if target_origin.length() < max_distance_from_origin:
return
for child in _world_node.get_children():
var spatial := child as Spatial
if spatial != null:
var body_transform := physics_body.global_transform
var new_transform := Transform(
body_transform.basis,
body_transform.origin - target_origin
)
spatial.global_transform = new_transform
var physics_body := spatial as PhysicsBody # Check for RigidBody instead?
if physics_body != null:
PhysicsServer.body_set_state(
physics_body.get_rid(),
PhysicsServer.BODY_STATE_TRANSFORM,
new_transform
)
But be aware that the above code does not consider any physics objects deeper in the scene tree.

How do I set a variable to contain rotational degrees?

I'm trying to implement a leaning mechanic in a game that I'm building. To do that I want to set one variable to act as the default number of rotation degrees (ideally x0, y0, and z0), and one for the rotation degrees of a character that is leaning to the right (ideally x0.6, y0, and z0).
Here's my code (for context, this script is attached to a Spatial node called UpperBody):
extends Spatial
const LEAN_LERP = 5
export var default_degrees : Vector3
export var leaning_degrees : Vector3
func _process(delta):
if Input.is_action_pressed("LeanRight"):
transform.origin = transform.origin.linear_interpolate(leaning_degrees, LEAN_LERP * delta)
else:
transform.origin = transform.origin.linear_interpolate(default_degrees, LEAN_LERP * delta)
if Input.is_action_pressed("LeanLeft"):
transform.origin = transform.origin.linear_interpolate(-leaning_degrees, LEAN_LERP * delta)
else:
transform.origin = transform.origin.linear_interpolate(default_degrees, LEAN_LERP * delta)
As you can see, I have both default_degrees and leaning_degrees' types set to Vector3 instead of the (currently unknown) equivalent for rotational degrees.
My question is this: how do I set a variable to contain rotational degrees?
Thanks.
There is no dedicated type for Euler angles. Instead you would use … drum roll … Vector3.
In fact, if you see the rotation_degrees property, you will find it is defined as a Vector3.
That, of course, isn't the only way to represent rotations/orientations. Ultimately, the Transform has two parts:
A Vector3 called origin which represents the translation.
A Basis called basis which represent the rest of the transformation (rotation, scaling and reflection, and shear or skewing).
A Basis can be thought of a trio of Vector3 each representing one of the axis of the coordinate system. Another way to think of Basis is as a 3 by 3 matrix.
Thus whatever you use to represent rotations or orientations will ultimately be converted to a Basis (and then either replace or be composed with the Basis of the transform).
Now, you want to interpolate the rotations, right? Euler angles aren't good for interpolation. Instead you could interpolate:
Transformations (Transform using interpolate_with Transform.interpolate_with).
Basis (Basis using Basis.slerp).
Quaternions (Quat using Quat.slerp).
On the other hand, Euler angles are good for input. In this particular case that means it is relative easy to wrap your head around what the numbers mean compared to writing any of these in the inspector.
Thus, we have two avenues:
Convert Euler angles to either Transform, Basis or Quat.
Find an easy way to input a Transform, Basis or Quat.
Euler angle to Quat
The Quat has a constructor that takes a vector for Euler angles. The catch is that it is Euler angles in radians. So we need to convert degrees to radians (which we can do with deg2rad). Like this:
var target_quat := Quat(
Vector3(
deg2rad(degrees.x),
deg2rad(degrees.y),
deg2rad(degrees.z)
)
)
Alternatively, you could do this:
var target_quat := Quat(degrees * PI / 180.0)
We also need to get the current quaternion from the transform:
var current_quat := transform.basis.get_rotation_quat()
Interpolate them:
var new_quat := current_quat.slerp(target_quat, LEAN_LERP * delta)
And replace the quat:
transform = Transform(
Basis(new_quat).scaled(transform.basis.get_scale()),
transform.origin
)
The above line assumes the transformation is only rotation, scaling, and translation. If we want to keep skewing, we can do this:
transform = Transform(
Basis(new_quat) * Basis(current_quat).inverse() * transform.basis,
transform.origin
)
The explanation for that is in the below section.
Notice we ended up converting the Quat to a Basis. So perhaps we are better off avoiding quaternions entirely.
Euler angle to Basis
The Basis class also has a constructor that works like the one we found in Quat. So we can do this:
var target_basis := Basis(degrees * PI / 180.0)
The catch this time is that Basis does not only represent rotation. So if we do that, we are losing scaling (and any other transformation the Basis has). We can preserve the scaling like this:
target_basis = target_basis.scaled(transform.basis.get_scale())
Ah, of course, the current Basis is this:
var current_basis := transform.basis
We interpolate like this:
var new_basis := current_basis.slerp(target_basis, LEAN_LERP * delta)
And we replace the Basis like this:
transform.basis = new_basis
To be honest, I'm not happy with the above approach. I'll show you a way to have the Basis you interpolate be only for rotation (so it can preserve any skewing the original Basis had, not only its scale), but it is a little more involved. Let us start here again:
var target_rotation := Basis(degrees * PI / 180.0)
And we will not scale that, instead we want to get a Basis that is only the rotation of the current one. We can do that by going from Basis to Quat and back:
var current_rotation := Basis(transform.basis.get_rotation_quat())
We interpolate the same way as before:
var new_rotation := current_rotation.slerp(target_rotation, LEAN_LERP * delta)
But to replace the Basis we want to keep everything about the old Basis that wasn't the rotation. In other words we are going to:
Take the Basis:
transform.basis
Remove its rotation (i.e. compose it with the inverse of its rotation):
Basis(transform.basis.get_rotation_quat()).inverse() * transform.basis
Which is the same as:
current_rotation.inverse() * transform.basis
And apply the new rotation:
new_rotation * current_rotation.inverse() * transform.basis
And that is what we set:
transform.basis = new_rotation * current_rotation.inverse() * transform.basis
I have tested to make sure the composition order is correct. And, yes, code for preserving skewing with Quat I showed above is based on this.
Euler angle to Transform
The way to create a Transform from Euler angles is via a Basis:
var target_transform := Transform(Basis(degrees * PI / 180.0), Vector3.ZERO)
We could preserve scale and translation with this approach:
var target_transform := Transform(
Basis(degrees * PI / 180.0).scaled(trasnform.basis.get_scale()),
transform.origin
)
If you want to interpolate translation at the same time, you can set your target position instead of transform.origin.
The current transform is, of course:
var current_transform := transform
We interpolate them like this:
var new_transform = current_transform.interpolate_with(target_transform, LEAN_LERP * delta)
And we can set that:
transform = new_trasnform
If we inline these variables, we have this:
transform = transform.interpolated_with(target_transform, LEAN_LERP * delta)
If you want to preserve skewing, use the Basis approach.
Alternative input to Euler angles
We have found out that interpolating transforms is actually very easy. Is there a way to easily input a Transform? Rhetorical question. We can add some Position3D to the scene. Position and rotate them (and even scale them, even though Position3D has no size), and then use the Transform from them.
We can make the Position3D children of your Spatial (which is somewhat odd, but don't think too hard about it), or as sibling. Regardless, the idea is that we are going to take the transform from these Position3D and use it to interpolate the transform of your Spatial. It is the same code as before:
transform = transform.interpolated_with(position.transform, LEAN_LERP * delta)
In fact, while we are at it, why not have three Position3D:
The lean left target.
The lean right target.
The default target.
Then you pick which target to use depending on input, and interpolate to that:
extends Spatial
const LEAN_LERP = 5
onready var left_target:Position3D = get_node(…)
onready var right_target:Position3D = get_node(…)
onready var default_target:Position3D = get_node(…)
func _process(delta):
var left := Input.is_action_pressed("LeanLeft")
var right := Input.is_action_pressed("LeanRight")
var target := default_target
if left and not right:
target = left_target
if right and not left:
target = right_target
transform = transform.interpolate_with(target, LEAN_LERP * delta)
Put the node paths where I left ....
Ok, Ok, here is one of the Euler angles versions:
extends Spatial
const LEAN_LERP = 5
export var default_degrees : Vector3
export var leaning_degrees : Vector3
func _process(delta):
var left := Input.is_action_pressed("LeanLeft")
var right := Input.is_action_pressed("LeanRight")
var degrees := default_degrees
if left and not right:
degrees = -leaning_degrees
if right and not left:
degrees = leaning_degrees
var target_rotation := Basis(degrees * PI / 180.0)
var current_rotation := Basis(transform.basis.get_rotation_quat())
var new_rotation := current_rotation.slerp(target_rotation, LEAN_LERP * delta)
transform.basis = new_rotation * current_rotation.inverse() * transform.basis

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()
}

Filter latitude and longitude records based on for given latitude and longitude for given n kilometre [duplicate]

I have data with latitude and longitude stored in my SQLite database, and I want to get the nearest locations to the parameters I put in (ex. My current location - lat/lng, etc.).
I know that this is possible in MySQL, and I've done quite some research that SQLite needs a custom external function for the Haversine formula (calculating distance on a sphere), but I haven't found anything that is written in Java and works.
Also, if I want to add custom functions, I need the org.sqlite .jar (for org.sqlite.Function), and that adds unnecessary size to the app.
The other side of this is, I need the Order by function from SQL, because displaying the distance alone isn't that much of a problem - I already did it in my custom SimpleCursorAdapter, but I can't sort the data, because I don't have the distance column in my database. That would mean updating the database every time the location changes and that's a waste of battery and performance. So if someone has any idea on sorting the cursor with a column that's not in the database, I'd be grateful too!
I know there are tons of Android apps out there that use this function, but can someone please explain the magic.
By the way, I found this alternative: Query to get records based on Radius in SQLite?
It's suggesting to make 4 new columns for cos and sin values of lat and lng, but is there any other, not so redundant way?
1) At first filter your SQLite data with a good approximation and decrease amount of data that you need to evaluate in your java code. Use the following procedure for this purpose:
To have a deterministic threshold and more accurate filter on data, It is better to calculate 4 locations that are in radius meter of the north, west, east and south of your central point in your java code and then check easily by less than and more than SQL operators (>, <) to determine if your points in database are in that rectangle or not.
The method calculateDerivedPosition(...) calculates those points for you (p1, p2, p3, p4 in picture).
/**
* Calculates the end-point from a given source at a given range (meters)
* and bearing (degrees). This methods uses simple geometry equations to
* calculate the end-point.
*
* #param point
* Point of origin
* #param range
* Range in meters
* #param bearing
* Bearing in degrees
* #return End-point from the source given the desired range and bearing.
*/
public static PointF calculateDerivedPosition(PointF point,
double range, double bearing)
{
double EarthRadius = 6371000; // m
double latA = Math.toRadians(point.x);
double lonA = Math.toRadians(point.y);
double angularDistance = range / EarthRadius;
double trueCourse = Math.toRadians(bearing);
double lat = Math.asin(
Math.sin(latA) * Math.cos(angularDistance) +
Math.cos(latA) * Math.sin(angularDistance)
* Math.cos(trueCourse));
double dlon = Math.atan2(
Math.sin(trueCourse) * Math.sin(angularDistance)
* Math.cos(latA),
Math.cos(angularDistance) - Math.sin(latA) * Math.sin(lat));
double lon = ((lonA + dlon + Math.PI) % (Math.PI * 2)) - Math.PI;
lat = Math.toDegrees(lat);
lon = Math.toDegrees(lon);
PointF newPoint = new PointF((float) lat, (float) lon);
return newPoint;
}
And now create your query:
PointF center = new PointF(x, y);
final double mult = 1; // mult = 1.1; is more reliable
PointF p1 = calculateDerivedPosition(center, mult * radius, 0);
PointF p2 = calculateDerivedPosition(center, mult * radius, 90);
PointF p3 = calculateDerivedPosition(center, mult * radius, 180);
PointF p4 = calculateDerivedPosition(center, mult * radius, 270);
strWhere = " WHERE "
+ COL_X + " > " + String.valueOf(p3.x) + " AND "
+ COL_X + " < " + String.valueOf(p1.x) + " AND "
+ COL_Y + " < " + String.valueOf(p2.y) + " AND "
+ COL_Y + " > " + String.valueOf(p4.y);
COL_X is the name of the column in the database that stores latitude values and COL_Y is for longitude.
So you have some data that are near your central point with a good approximation.
2) Now you can loop on these filtered data and determine if they are really near your point (in the circle) or not using the following methods:
public static boolean pointIsInCircle(PointF pointForCheck, PointF center,
double radius) {
if (getDistanceBetweenTwoPoints(pointForCheck, center) <= radius)
return true;
else
return false;
}
public static double getDistanceBetweenTwoPoints(PointF p1, PointF p2) {
double R = 6371000; // m
double dLat = Math.toRadians(p2.x - p1.x);
double dLon = Math.toRadians(p2.y - p1.y);
double lat1 = Math.toRadians(p1.x);
double lat2 = Math.toRadians(p2.x);
double a = Math.sin(dLat / 2) * Math.sin(dLat / 2) + Math.sin(dLon / 2)
* Math.sin(dLon / 2) * Math.cos(lat1) * Math.cos(lat2);
double c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
double d = R * c;
return d;
}
Enjoy!
I used and customized this reference and completed it.
Chris's answer is really useful (thanks!), but will only work if you are using rectilinear coordinates (eg UTM or OS grid references). If using degrees for lat/lng (eg WGS84) then the above only works at the equator. At other latitudes, you need to decrease the impact of longitude on the sort order. (Imagine you're close to the north pole... a degree of latitude is still the same as it is anywhere, but a degree of longitude may only be a few feet. This will mean that the sort order is incorrect).
If you are not at the equator, pre-calculate the fudge-factor, based on your current latitude:
<fudge> = Math.pow(Math.cos(Math.toRadians(<lat>)),2);
Then order by:
((<lat> - LAT_COLUMN) * (<lat> - LAT_COLUMN) +
(<lng> - LNG_COLUMN) * (<lng> - LNG_COLUMN) * <fudge>)
It's still only an approximation, but much better than the first one, so sort order inaccuracies will be much rarer.
I know this has been answered and accepted but thought I'd add my experiences and solution.
Whilst I was happy to do a haversine function on the device to calculate the accurate distance between the user's current position and any particular target location there was a need to sort and limit the query results in order of distance.
The less than satisfactory solution is to return the lot and sort and filter after the fact but this would result in a second cursor and many unnecessary results being returned and discarded.
My preferred solution was to pass in a sort order of the squared delta values of the long and lats:
((<lat> - LAT_COLUMN) * (<lat> - LAT_COLUMN) +
(<lng> - LNG_COLUMN) * (<lng> - LNG_COLUMN))
There's no need to do the full haversine just for a sort order and there's no need to square root the results therefore SQLite can handle the calculation.
EDIT:
This answer is still receiving love. It works fine in most cases but if you need a little more accuracy, please check out the answer by #Teasel below which adds a "fudge" factor that fixes inaccuracies that increase as the latitude approaches 90.
In order to increase performance as much as possible I suggest improve #Chris Simpson's idea with the following ORDER BY clause:
ORDER BY (<L> - <A> * LAT_COL - <B> * LON_COL + LAT_LON_SQ_SUM)
In this case you should pass the following values from code:
<L> = center_lat^2 + center_lon^2
<A> = 2 * center_lat
<B> = 2 * center_lon
And you should also store LAT_LON_SQ_SUM = LAT_COL^2 + LON_COL^2 as additional column in database. Populate it inserting your entities into database. This slightly improves performance while extracting large amount of data.
Try something like this:
//locations to calculate difference with
Location me = new Location("");
Location dest = new Location("");
//set lat and long of comparison obj
me.setLatitude(_mLat);
me.setLongitude(_mLong);
//init to circumference of the Earth
float smallest = 40008000.0f; //m
//var to hold id of db element we want
Integer id = 0;
//step through results
while(_myCursor.moveToNext()){
//set lat and long of destination obj
dest.setLatitude(_myCursor.getFloat(_myCursor.getColumnIndexOrThrow(DataBaseHelper._FIELD_LATITUDE)));
dest.setLongitude(_myCursor.getFloat(_myCursor.getColumnIndexOrThrow(DataBaseHelper._FIELD_LONGITUDE)));
//grab distance between me and the destination
float dist = me.distanceTo(dest);
//if this is the smallest dist so far
if(dist < smallest){
//store it
smallest = dist;
//grab it's id
id = _myCursor.getInt(_myCursor.getColumnIndexOrThrow(DataBaseHelper._FIELD_ID));
}
}
After this, id contains the item you want from the database so you can fetch it:
//now we have traversed all the data, fetch the id of the closest event to us
_myCursor = _myDBHelper.fetchID(id);
_myCursor.moveToFirst();
//get lat and long of nearest location to user, used to push out to map view
_mLatNearest = _myCursor.getFloat(_myCursor.getColumnIndexOrThrow(DataBaseHelper._FIELD_LATITUDE));
_mLongNearest = _myCursor.getFloat(_myCursor.getColumnIndexOrThrow(DataBaseHelper._FIELD_LONGITUDE));
Hope that helps!

Is there a linspace() like method in Math.Net

Is there function in Math.Net like (MatLab/Octave/numpy)'s linspace() which takes 3 parameters (min, max, length) and creates an vector/array of evenly spaced values between min and max? It is not hard to implement but if there was a function already I would prefer to use that.
There is none exactly like linspace, but the signal generator comes quite close and creates an array:
SignalGenerator.EquidistantInterval(x => x, min, max, len)
I'm not fresh on the VB.net syntax, but I guess it's very close to C#.
In case you need a vector:
new DenseVector(SignalGenerator.EquidistantInterval(x => x, min, max, len))
Or you could implement it e.g. using the static Create function (in practice you may want to precompute the step):
DenseVector.Create(len, i => min + i*(max-min)/(len - 1.0))
Update 2013-12-14:
Since v3.0.0-alpha7 this is covered by two new functions:
Generate.LinearSpaced(length, a, b) -> MATLAB linspace(a, b, length)
Generate.LinearRange(a, [step], b) -> MATLAB a:step:b
I used this C# code to replicate the functionality of linspace (how numpy does it), feel free to use it.
public static float[] linspace(float startval, float endval, int steps)
{
float interval = (endval / MathF.Abs(endval)) * MathF.Abs(endval - startval) / (steps - 1);
return (from val in Enumerable.Range(0,steps)
select startval + (val * interval)).ToArray();
}
Here is the VB Translation I made.
Public Function linspace(startval As Single, endval As Single, Steps As Integer) As Single()
Dim interval As Single = (endval / Math.Abs(endval)) *(Math.Abs(endval - startval)) / (Steps - 1)
Return (From val In Enumerable.Range(0, Steps) Select startval + (val * interval)).ToArray()
End Function
Use examples;
C#
float[] arr = linspace(-4,4,5)
VB
Dim arr as Single() = linspace(-4,4,5)
Result:
-4,-2,0,2,4
I checked the result from the code shown below and MATLAB linspace, it exactly matches. I myself use it for my research work in Monte Carlo implementations.
Below is the code image and the actual code.
static double[] LINSPACE(double StartValue, double EndValue, int numberofpoints)
{
double[] parameterVals = new double[numberofpoints];
double increment = Math.Abs(StartValue - EndValue) / Convert.ToDouble(numberofpoints - 1);
int j = 0; //will keep a track of the numbers
double nextValue = StartValue;
for (int i = 0; i < numberofpoints; i++)
{
parameterVals.SetValue(nextValue, j);
j++;
if (j > numberofpoints)
{
throw new IndexOutOfRangeException();
}
nextValue = nextValue + increment;
}
return parameterVals;
}
Code for creating a linspace function in C#