Dicom Windowing: Difference between linear default standard formula and window width changes - dicom

What is the difference between applying the Default Linear function for windowing to get the pixel value to display like so
These Attributes are applied according to the following pseudo-code, where x is the input value, y is an output value with a range from ymin to ymax, c is Window Center (0028,1050) and w is Window Width (0028,1051):
if (x <= c - 0.5 - (w-1) /2), then y = ymin
else if (x > c - 0.5 + (w-1) /2), then y = ymax
else y = ((x - (c - 0.5)) / (w-1) + 0.5) * (ymax- ymin) + ymin
and this other approach that many people on the internet also speak off, like so?
lowest_visible_value = window_center - window_width / 2
highest_visible_value = window_center + window_width / 2

The results are very similar and only in rare cases you would visually note a difference.
Obviously, the "official" formula works in floating point space and handles rounding of fractions of pixel values more precisely than the simplified version.

The difference is: the first function is defined in DICOM standard and therefore should be used always!
The sites you linked explained the windowing and gave you a short formula, how to estimate the highest and lowest pixel value that are scaled with the window center and window width parameter. They are not used to calculate the actual pixel value. As you noticed, those short formulas do not contain a input value X.
Maybe you will find some sites on the internet, where they do not use the interpolation as defined in DICOM standard, but they use something like that: (I also have seen sometimes)
y = 128 + 255 * (x - window_center) / window_width
And in fact you will hardly find a difference in the resulting image. But there may be some cornercases where this formula results in different images. And the officially defined is not so hard to implement, so you should use that.
To complete that: DICOM also defined the VOI LUT Function LINEAR_EXACT, that is defined that way:
if (x <= c - w/2), then y = ymin
else if (x > c + w/2), then y = ymax
else y = ((x - c) / w + 0.5) * (ymax- ymin) + ymin
So doing the simplified linear interpolation is also defined in DICOM-Standard. But not as the default function, but only if it is explicitly configured in the DICOM file.

Related

Assistance writing an exponential decay formula

I'm trying to write a decay formula, which is based on the ratio between x and y, assuming always that y > x. The formula needs to have a lower limit of 0.25, and an upper limit of 1.0.
As the ratio between the two numbers decreases, the formula gets closers to 1, as the ratio increases, the formula gets closer to 0.25. The result of the formula is being used as a scalar.
If possible, I'd also like to toggle the rate at which the scalar approaches its limits.
Any guidance is much appreciated, as I'm ripping my hair out right now!
This is an example:
take in account -1/x with x = [0, +inf] then it has f(x) = [-inf, 0]. so now let's take in account 1-1/x with x = [0, +inf] it has f(x) = [-inf, 1], but f(x)=0 <=> x=1.
So now we move the function 1 to the left, so we get f(x) = 1-(1/(x+1)).
now we need to map it in [0.25, 1], so we do the same thing, but instead of 1 we use 0.75, and we get
f(x) = 3/4 - 1/[x + (4/3)]
that has a domain of [0,+inf], f(x)=0 <=> x=0 and an image of [0,0.75], so now we are missing only the offset of 0.25, with which, we get
f(x) = 3/4 - 1/[x + (4/3)] + 1/4
and if we sum up the pieces we get
f(x) = 1 - 1/[x + (4/3)] + 1/4
so now we have the right function, we just need to figure out what to put as x
we want that when x/y = 1 => 0 (to have f(0)= 0.25) and x/y = 0 => +inf (to have f(+inf)= 1), and we achieve that using (y/x)-1
At the end we get:
f(x,y) = 1 - 1/[((y/x)-1) + (4/3)] + 1/4
To manipulate the velocity, put the coefficient in front of the "old", with which you get:
f(x,y) = 1 - 1/[velocity*((y/x)-1) + (4/3)] + 1/4

The time-corrected Verlet numerical integration formula

There is a commonly used verlet-integration formula on the web by Johnathan Dummer, called Time-Corrected Verlet. However I've read several forum posts, that people get weird or unexpected results with it in certain conditions.
Formula by Johnathan Dummer:
x1 = x + (x – x0) * dt / dt0 + a * dt^2
There is also a stackoverflow answer, which states that Dummer's time-corrected formula is broken and the poster presents his own derivation as the correct one.
Suggested correct formula by a stackoverflow answer
x1 = x + (x – x0) * dt / dt0 + a * dt * (dt + dt0) / 2
Well, is Dummer's formula really broken? If yes, is the derivation of the poster better?
PS: It is also weird that Dummer uses the verlet integration formula x1 = x - x0 + a * dt^2 on his website instead of the correct x1 = 2x - x0 + a * dt^2.
The wikipedia page Verlet integration - Non-constant time differences presents the two formula, without referenced. I've not checked the derivation myself but the reasoning for the second improved formula looks sound.
I've downloaded Dummer's spreadsheet and modified one of the formula to use the correction. The results are much better.
The exact results are in yellow, we see that just using the normal Verlet algorithm with fluctuating frame-rate is bad. Dummer's time-correct varient in red is pretty good, but a little off. The dark green version with the improved correction is much better.
For projectiles under gravity which has a quadratic solution you may find that the improved version is exact. When the degree gets a bit higher it will vary from the true path and it might be worth testing to see if we still get a better approximation.
Doing the same calculation for a sin curve shows the improved method is considerably better. Here Time-correct Verlet is drifting quite a bit. The improved version is better, only a little bit off the exact answer.
For the PS. Note that if you set dt=dt0 in the TCV formula
x1 = x + (x – x0) * dt / dt0 + a * dt^2
you get
x1 = x + x – x0 + a * dt^2
= 2 x – x0 + a * dt^2
the original Verlet formula.
The true derivation is based on Taylor formulas
x(t-h0) = x(t) - x'(t)*h0 + 0.5*x''(t)*h0^2 + O(h0^3)
x(t+h1) = x(t) + x'(t)*h1 + 0.5*x''(t)*h1^2 + O(h1^3)
and now eliminate x'(t) from these two formulas to get a Verlet-like formula
h0*x(t+h1) + h1*x(t-h0) = (h0+h1)*x(t) + 0.5*a(t)*h0*h1*(h0+h1) +O(h^3)
which makes a propagation formula
x(t+h1) = (1+h1/h0)*x(t) - h1/h0*x(t-h0) + 0.5*a(t)*h1*(h0+h1)
= x(t) + (x(t)-x(t-h0))*h1/h0 + 0.5*a(t)*h1*(h0+h1)
so that indeed the corrected formula is the correct one.
Note that if you use velocity Verlet steps
Verlet(dt) {
v += a * 0.5*dt
x += v*dt
a = acceleration(x)
v += a * 0.5*dt
}
then each step is indepentently symplectic, so that the change of step size between steps is absolutely unproblematic.
Notice that the main advantages of Verlet and other similar symplectic schemes over Runge-Kutta methods etc. crucially depends on using a fixed step. In detail, the modified energy function (and other more than quadratic constants of motion) that is largely constant under the numerical method is a modification of the exact energy where the difference scales with the step size. So when changing the step size a different modification gives a constant energy. Frequent changes of the step size allow thus, possibly, arbitrary changes of the energy level.
I decided to quit being lazy and show some kind of derivation of how the original Verlet method looks with a variable step size. Because it seems like this faulty adaptation by Dummer is more pervasive than I thought, which is saddening. I also noticed that, as the above answer points out, the correct version is now on wikipedia alongside the Dummer one, though it was added after my "suggested correct answer".
When I look at Verlet method, I see that it looks a lot like leapfrog, velocity Verlet, implicit Euler etc., which look like second-order versions of modified midpoint, and some of them may be identical. In each of these, to some degree they have a leapfrog idea where integration of acceleration (into velocity) and integration of constant velocity (into position) are each staggered so that they overlap by half. This brings things like time-reversibility and stability, which are more important for the 'realism' of a simulation than accuracy is. And the 'realism', the believability, is more important for video games. We don't care if something moves to a slightly different position than it's exact mass would have truly caused, so long as it looks and feels realistic. We're not calculating where to point our high-powered satellite telescopes to look at features on distant objects, or future celestial events. Here, stability and efficiency takes priority here over mathematical accuracy. So, it seems like leapfrog method is appropriate. When you adapt leapfrog for variable time step, it loses some of this advantage, and it loses some of it's appeal for game physics. Stormer-Verlet is like leapfrog, except it uses the average velocity of the previous step instead of a separately maintained velocity. You can adapt this Stormer-Verlet in the same way as leapfrog. To integrate velocity forward with a fixed acceleration, you use half the length of the previous step and half the length of the next step, because they are staggered. If the steps were fixed like true leapfrog, they would be the same length and so the two half lengths sum to one. I use h for step size, a/v/p for acceleration/velocity/position, and hl/pl for 'last' as in previous step. These aren't really equations, more like assignment operations.
Original leapfrog:
v = v + a*h
p = p + v*h
With variable time step:
v = v + a*hl/2 + a*h/2
p = p + v*h
Factor a/2:
v = v + a*(hl + h)/2
p = p + v*h
Use previous position (p - pl)/hl for initial velocity:
v = (p - pl)/hl + a*(hl + h)/2
p = p + v*h
Substitute, we don't need v:
p = p + ( (p - pl)/hl + a*(hl + h)/2)*h
Distribute h:
p = p + (p - pl)*h/hl + a*h*(h + hl)/2
The result is not as simple or fast as the original Stormer form of Verlet, 2p - pl + a*h^2. I hope this makes some sense. You would omit the last step in actual code, no need to multiply h twice.

Hash Value for 3D Vector

Is there a way to represent a 3D Vector as a definite number? I mean that two vectors with different values can't ever have the same hash value. I'm sure there already is a question about this but I haven't found it unfortunately. Thanks for your help.
EDIT:
I know this algorithm for 2D vectors which is pretty good (I think): (x + y) * (x + y + 1) / 2 + y
The best approach to get a hash for a vector of floats is to convert it to a string of bytes or characters and calculate a hash on it. An example of this is given using numpy and python in the following answer:
Most efficient property to hash for numpy array.
This will work efficiently for large numbers of vectors, but you cannot guarantee that you will not get collisions due to the simple fact of mapping three floats onto an integer. However there are a number of hashing algorithms available in the python hashlib library to choose from, you might need to experiment. An option in C++ is Boost::Hash.
See the pigeon-hole principle - in the same way you can't fit you can't 100 pigeons into 10 holes, you can't uniquely convert 3 values into 1 value (with all values of the same size). There will have to be duplicates.
Now, if you could have a number with 3x as many bits as the vector values, the problem becomes fairly easy:
// convert x, y and z to the range 0-...
x -= minimum possible value
y -= minimum possible value
z -= minimum possible value
mult = maximum possible value + 1
hash = x * mult * mult + y * mult + z
If you're having trouble understanding the above, just take the example of the range of the values being 0-99. We'd multiple x by 100*100 = 10000 and y by 100, so the hash would be a decimal value with (at most) 6 digits with x, y and z all next to each other, guaranteed to not overlap:
x = 12
y = 34
z = 56
hash = 123456
Now this same idea will hold for any maximum value by just changing the base / radix.
If there isn't any overlap in some base, each unique combination of values of x, y and z will result in a unique hash.
This is by far the simplest approach, although it doesn't produce a particularly good hash, so it depends what you want to use it for - there might be a way to uniquely convert this number to another number which will be a good hash.
Responding to this post a little late, and perhaps this isn't what you're looking for, but I figured I would chime in with another answer.
You could use the function you mentioned, (x + y) * (x + y + 1) / 2 + y , and do it recursively, ex. f( f(x,y) , z).
You can also use other pairing functions as well and use the same method (https://en.wikipedia.org/wiki/Pairing_function).
For my problem, I wanted a function that would order vectors based on their location. The order itself didn't matter, only that a close value means a similar vector. What I ended up doing was:
double get_pairing(double x, double y, double z) {
double normalizer = 0.0;
if(x < 0) {
normalizer += (3.0 * MAX_COORD_VAL);
}
if (y < 0) {
normalizer += (6.0 * MAX_COORD_VAL);
}
if (z < 0) {
normalizer += (9.0 * MAX_COORD_VAL);
}
double g = x + y + z - normalizer + (21 * MAX_COORD_VAL);
return g;
}
This orders vectors based on whether they have negative coordinate values and whether they have large coordinate values.
This works assuming you have a max coordinate value.

Given sum of two numbers A and B find maximum product of A and B

Given sum of A and B let S
i have to find maximum product of A*B
but there is one condition value of A will be in range [P,Q]
How to proceed for it ?
If there is no range then task is pretty simple.
Using derivation method .
How to find Maximum product for eg.
A+B=99
value of A will be range [10,20]
then what will be the maximum product of A and B.
O(N) will not sufficient for the problem
Clearly, B = S - A and you need to maximize A * (S - A).
You know from algebra that A * (S - A) achieves a maximum when A = S / 2.
If S / 2 falls in the allowed range [P Q], then the maximum value is A^2 / 4.
Otherwise, by monotonicity the maximum value is reached at one of the bounds and is the largest of P * (S - P) and Q * (S - Q).
This is an O(1) solution.
This is actually a maths question, nothing to do with programming
Even if you are given it as a programming question, You should first understand it mathematically.
You can think of it geometrically as "if the perimeter of my rectangle is fixed at S, how can I achieve the maximum area?"
The answer is by making sides of equal length, and turning it into a square. If you're constrained, you have to get as close to a square as possible.
You can use calculus to show it formally:
A+B = S, so B = S-A
AB therefore = A(S-A)
A is allowed to vary, so write it as x
y = x(S-x) = -x^2 + Sx
This is a quadratic, its graph Will look like an upsidedown parabola
You want the maximum, so you're looking for the top of the parabola
dy/dx = 0
-2x + S = 0
x = S/2
A better way of looking at it would be to start with our rectangle Pq = A, and say P is the longer edge.
So now make it more oblique, by making the longer edge P slightly longer and the shorter edge q slightly shorter, both by the same amount, so P+q does not change, and we can show that the area goes down:
Pq = A
(P+delta) * (q-delta)
= Pq + (q-P)*delta + delta^2
= A + (q-P)delta
and I throw away the delta^2 as it vanishes as delta shrinks to 0
= A + (something negative)*delta
= A - something positive
i.e. < A

Minimizing a function containing an integral

Does anyone know how to minimize a function containing an integral in MATLAB? The function looks like this:
L = Int(t=0,t=T)[(AR-x)dt], A is a system parameter and R and x are related through:
dR/dt = axRY - bR, where a and b are constants.
dY/dt = -xRY
I read somewhere that I can use fminbnd and quad in combination but I am not able to make it work. Any suggestions?
Perhaps you could give more details of your integral, e.g. where is the missing bracket in [AR-x)dt]? Is there any dependence of x on t, or can we integrate dR/dt = axR - bR to give R=C*exp((a*x-b)*t)? In any case, to answer your question on fminbnd and quad, you could set A,C,T,a,b,xmin and xmax (the last two are the range you want to look for the min over) and use:
[x fval] = fminbnd(#(x) quad(#(t)A*C*exp((a*x-b)*t)-x,0,T),xmin,xmax)
This finds x that minimizes the integral.
If i didn't get it wrong you are trying to minimize respect to t:
\int_0^t{(AR-x) dt}
well then you just need to find the zeros of:
AR-x
This is just math, not matlab ;)
Here's some manipulation of your equations that might help.
Combining the second and third equations you gave gives
dR/dt = -a*(dY/dt)-bR
Now if we solve for R on the righthand side and plug it into the first equation you gave we get
L = Int(t=0,t=T)[(-A/b*(dR/dt + a*dY/dt) - x)dt]
Now we can integrate the first term to get:
L = -A/b*[R(T) - R(0) + Y(T) - Y(0)] - Int(t=0,t=T)[(x)dt]
So now all that matters with regards to R and Y are the endpoints. In fact, you may as well define a new function, Z which equals Y + R. Then you get
L = -A/b*[Z(T) - Z(0)] - Int(t=0,t=T)[(x)dt]
This next part I'm not as confident in. The integral of x with respect to t will give some function which is evaluated at t = 0 and t = T. This function we will call X to give:
L = -A/b*[Z(T) - Z(0)] - X(T) + X(0)
This equation holds true for all T, so we can set T to t if we want to.
L = -A/b*[Z(t) - Z(0)] - X(t) + X(0)
Also, we can group a lot of the constants together and call them C to give
X(t) = -A/b*Z(t) + C
where
C = A/b*Z(0) + X(0) - L
So I'm not sure what else to do with this, but I've shown that the integral of x(t) is linearly related to Z(t) = R(t) + Y(t). It seems to me that there are many equations that solve this. Anyone else see where to go from here? Any problems with my math?

Resources