UISlider with different segmentation levels - ios

I'd like to create a range slider that has different sensitivity levels.
It needs to act differently depending on the specific part in the range the user has chosen.
i.e. - if my slider's range is 1-100,000, then setting the range at lower values will jump by 1, and setting the range at the higher values will jump by 100.
eBay implemented this kind of slider in their website (notice the price range slider on the left): http://www.ebay.com/sch/i.html?LH_FS=0&_sacat=0&_from=R40&_nkw=car&_mPrRngCbx=1&_udlo=490&_udhi=21%2C000%2C000
Any idea?

Set the slider's range to be 0 - 5. Then calculate the desired value as 10 ^ sliderValue. This basically gives you a logarithmic scale.
If you want discrete, but different linear ranges, then the answer by kabram is probably more what you want.
Update:
Set the slider's range from 0.0 to 5.0. As the slider's value changes, the calculated value becomes:
double newValue = pow(10, slider.value);
where slider is the UISlider. pow is a standard C math function. This gives you the following:
slider.value newValue
0.0 1.0
1.0 10.0
2.0 100.0
3.0 1000.0
4.0 10000.0
5.0 100000.0

Since the slider is not showing the associated value, why don't you simply add an action outlet to the value-change event and compute the appropriate jumps.
So for e.g., set the slider's range to 1 to 100. Let's assume you are showing the computed range using a label.
Label's value will then be:
if slider.value < 10, then value = range
else if slider.value < 20 then value = 10 + (slider.value - 10) * 2 // increments of 2
else if slider.value < 50 then value = 10 + 10 * 2 + (slider.value - 20) * 5 // increments of 5
...
you get the idea?

Related

Correct use of Histogram Data - Setting interval size?

In my model, I am saving results from numerous Parameter Variation runs in a Histogram Data object.
Here are my Histogram Data settings:
Number of intervals: 7
Value range:
Automatically detected
Initial Interval Size: 10
I then print out these results using the following :
//if final replication, write Histogram Data into Excel
if(getCurrentReplication() == lastReplication){
double intervalWidth = histogramData.getIntervalWidth();
int intervalQty = histogramData.getNumberOfIntervals();
for(int i = 0; i < intervalQty; i++){
traceln(intervalWidth*i + " " + histogramData.getPDF(i));
excelRecords.setCellValue(String.valueOf(intervalWidth*i) + " - " + String.valueOf(intervalWidth*(i+1)), 1, rowIndex, columnIndex);
excelRecords.setCellValue(histogramData.getPDF(i), 1, rowIndex, columnIndex+1);
rowIndex++;
}
}
Example of my intended results:
10 - 80%
20 - 10%
30 - 5%
40 - 2%
50...
60...
Actual results:
0.0 0.0
10.0 0.0
20.0 0.0
30.0 0.998782775272379
40.0 0.0011174522089635631
50.0 9.9772518657461E-5
60.0 0.0
Results after settings initial interval size to 0.1:
0.0 0.9974651710510558
4.0 0.001117719851502934
8.0 9.181270208774101E-4
12.0 2.3951139675062872E-4
16.0 1.5967426450041916E-4
20.0 9.979641531276197E-5
24.0 0.0
How would I go about obtaining my desired results? Am I fundamentally misunderstanding something about the HistogramData object?
Thank you for your help.
The function you are using (getPDF(i)) returns value for the interval in fractions (not in percentages). So, you have to multiply the value by 100 in order to get it as a percentage. As for histogram bars, model analyze the results, specified interval numbers and interval size. After that, it will build the respective number of bars that cover all results. In your case, intervals from 0 to 30 do not provide any results and bars are not presented (PDF here is 0.0).

Algorithm to always sum sliders to 100% failing due to zeroes

This is (supposed to be) a function which makes sure that the the sum of a number of slider's values always adds up to globalTotal.
A slider value can be changed manually by the user to changer.value and then when applying this function to the values of the other sliders, it can determine their new or endVal.
It takes the startVal of the slider which needs changing and the original value of the slider that changed changerStartVal and can determine the new value others by weighting.
The problem and my question is. Sometimes remainingStartVals can be zero (when the slider changing gets moved all the way to maximum) or startVal can be zero (when the slider changing is moved to zero and then another slider is moved). When this happens I get a divide-by-zero or a multiply-by-zero respectively. Both of which are bad and lead to incorrect results. Is there an easy way to fix this?
func calcNewVal(startVal: Float, changerStartVal: Float) -> Float {
let remainingStartVals = globalTotal - changerStartVal
let remainingNewVals = globalTotal - changer.value
let endVal = ((startVal * (100 / remainingStartVals)) / 100) * remainingNewVals
return endVal
}
This is a mathematical problem, not a problem related to Swift or any specific programming language so I'll answer with mathematical formulas and explanations rather than code snippets.
I don't really understand your algorithm either. For example in this line:
let endVal = ((startVal * (100 / remainingStartVals)) / 100) * remainingNewVals
you first multiply by 100 and then divide by 100, so you could just leave all these 100 factors out in the first place!
However, I think I understand what you're trying to achieve and the problem is that there is no generic solution. Before writing an algorithm you have to define exactly how you want it to behave, including all edge cases.
Let's define:
vi as the value of the i-th slider and
Δi as the change of the i-th slider's value
Then you have to think of the following cases:
Case 1:
0 < vi ≤ 1 for all sliders (other than the one you changed)
This is probably the common case you were thinking about. In this case you want to adjust the values of your unchanged sliders so that their total change is equal to the change Δchanged of the slider you changed. In other words:
∑i Δi = 0
If you have 3 sliders this reduces to:
Δ1 + Δ2 + Δ3 = 0
And if the slider that changed is the one with i = 1 then this requirement would read:
Δ1 = – (Δ2 + Δ3)
You want the sliders to adjust proportionally which means that this change Δ1 should not be distributed equally on the other sliders but depending on their current value:
Δ2 = – w2 * Δ1
Δ3 = – w3 * Δ1
The normed weight factors are
w2 = v2 / (v2 + v3)
w3 = v3 / (v2 + v3)
Thus we get:
Δ2 = – v2 / (v2 + v3) * Δ1
Δ3 = – v3 / (v2 + v3) * Δ1
So these are the formulas to applied for this particular case.
However, there are quite a few other cases that don't work with this approach:
Case 2:
vi = 0 for at least one, but not all of the sliders (other than the one you changed)
In this case the approach from case 1 would still work (plus it would be the logical thing to do). However, a slider's value would never change if it's zero. All of the change will be distributed over the sliders with a value > 0.
Case 3:
vi = 0 for all sliders (other than the one you changed)
In this case the proportional change doesn't work because there is simply no information how to distribute the change over the sliders. They're all zero! This is actually your zero division problem: In the case where we have 3 sliders and the slider 1 changes we'll get
v2 + v3 = 0
This is only another manifestation of the fact that the weight factors wi are simply undefined. Thus, you'll have to manually define what will happen in this case.
The most plausible thing to do in this case is to distribute the change evenly over all sliders:
Δi = – (1 / n) * Δ1
where n is the number of sliders (excluding the one that was changed!). With this logic, every slider gets "the same share" of the change.
Now that we're clear with our algorithm you can implement these cases in code. Here some pseudo code as an example:
if sum(valuesOfAllSlidersOtherThanTheSliderThatChanged) == 0 {
for allUnchangedSliders {
// distribute change evenly over the sliders
Δi = – (1 / n) * Δ_changedSlider
}
}
else {
for allUnchangedSliders {
// use weight factor to change proportionally
Δi = – v_i / ∑(v_i) * Δ_changedSlider
}
}
Please be aware that you must cache the values of the current state of your sliders at the beginning or (even better) first compute all the changes and then apply all the changes in a batch. Otherwise you will use a value v2' that you just computed for determining the value v3' which will obviously result in incorrect values.
Hey #Sean the simplest adjustment that I could think of here is to check if the remainingStartVals is not 0 that means that there are weights assigned to the other sliders and also check if a single slider had a weight to begin with which means its startVal shouldn't be equal to 0
func calcNewVal(startVal: Float, changerStartVal: Float) -> Float{
var endVal = 0
let remainingStartVals = globalTotal - changerStartVal
if remainingStartVals != 0 || startVal != 0{
let remainingNewVals = globalTotal - changer.value
endVal = ((startVal * (100 / remainingStartVals)) / 100) * remainingNewVals
}
return endVal
}

Gaussian filter in scipy

I want to apply a Gaussian filter of dimension 5x5 pixels on an image of 512x512 pixels. I found a scipy function to do that:
scipy.ndimage.filters.gaussian_filter(input, sigma, truncate=3.0)
How I choose the parameter of sigma to make sure that my Gaussian window is 5x5 pixels?
Check out the source code here: https://github.com/scipy/scipy/blob/master/scipy/ndimage/filters.py
You'll see that gaussian_filter calls gaussian_filter1d for each axis. In gaussian_filter1d, the width of the filter is determined implicitly by the values of sigma and truncate. In effect, the width w is
w = 2*int(truncate*sigma + 0.5) + 1
So
(w - 1)/2 = int(truncate*sigma + 0.5)
For w = 5, the left side is 2. The right side is 2 if
2 <= truncate*sigma + 0.5 < 3
or
1.5 <= truncate*sigma < 2.5
If you choose truncate = 3 (overriding the default of 4), you get
0.5 <= sigma < 0.83333...
We can check this by filtering an input that is all 0 except for a single 1 (i.e. find the impulse response of the filter) and counting the number of nonzero values in the filtered output. (In the following, np is numpy.)
First create an input with a single 1:
In [248]: x = np.zeros(9)
In [249]: x[4] = 1
Check the change in the size at sigma = 0.5...
In [250]: np.count_nonzero(gaussian_filter1d(x, 0.49, truncate=3))
Out[250]: 3
In [251]: np.count_nonzero(gaussian_filter1d(x, 0.5, truncate=3))
Out[251]: 5
... and at sigma = 0.8333...:
In [252]: np.count_nonzero(gaussian_filter1d(x, 0.8333, truncate=3))
Out[252]: 5
In [253]: np.count_nonzero(gaussian_filter1d(x, 0.8334, truncate=3))
Out[253]: 7
Following the excellent previous answer:
set sigma s = 2
set window size w = 5
evaluate the 'truncate' value: t = (((w - 1)/2)-0.5)/s
filtering: filtered_data = scipy.ndimage.filters.gaussian_filter(data, sigma=s, truncate=t)

Where is my mistake in the following example about Viterbi algorithm?

I am trying to learn Hidden Markov Model, Viterbi algorithm. Therefore I was looking for an example to study. I came across a simple example from this link;
Up to the position 3 I understood everything. However in position 3 when calculating A;
- δ(A) = max { 0.2 x 0.6 x 0.063, 0.7 x 0.7 x 0.7 }
= max { 0.00756(A), 0.09604(B) }
Since the B value is greater than A value we select B in state 2 for A in state 3. The value for A in state 3 should be 0.09604
To calculate B value in state 3;
- δ(B) = max { 0.7 x 0.6 x 0.063, 0.2 x 0.7 x 0.196 }
= max { 0.02646(A), 0.02744(B) }
Since the B value is greater than A value we select B in state 2 for B in state 3. Therefore the value for B in state 3 should be 0.02744
However in the example for state 3 the values are calculated in the example as follows;
δ(B) = 0.02646
δ(A) = 0.02744
Different from my answers.
I am still learning the subject so it is likely that I am making a mistake. However I can't see where.
Why am I getting different answer? What is the problem in my solution?

Find successive maximum differences in array

I have created an application in which the user continually rotates the phone about the z-axis (yaw) with the screen of the phone facing upwards. I would like to generate the angle between the two extremes each time the rotation changes direction.
Imagine an array of the following values: [-5,-3,-2, 0, 1, 2, 6, 5, 3, 2,-1,-3,-4,-7,-4,-3,...]. What I would like to do is find the relative maximums and minimums of the array in order to find the differences from one relative minimum to the next relative maximum. In the given array, -5 would be the first relative minimum and then 6 would be the next relative maximum. The difference here would be 11 units. From that relative maximum of 6, the next relative minimum is -7. The difference here would be 13 units. The process would continue on until the end of the array. I would like these difference values to be entered into an array of their own, i.e. [11,13,...]. Would greatly appreciate any assistance!
The way I see this your first value in the array is always your initial relative minimum AND maximum since you have absolutely no basis of comparison from the get-go (unless you prime both relMin and relMax to 0 OR define a range to find your relMin and relMax). With that in mind the logic behind your example itself is flawed given your assumption of using -5 & 6 as the first comparison pair.
Let's use your array and iterate through the array with a For Loop...
[-5,-3,-2, 0, 1, 2, 6, 5, 3, 2,-1,-3,-4,-7,-4,-3,...]
0: relMin = -5, relMax = -5, delta = 0
1: relMin = -5, relMax = -3, delta = 2
2: relMin = -5, relMax = -2, delta = 3
3: relMin = -5, relMax = 0, delta = 5
4: relMin = -5, relMax = 1, delta = 6
5: relMin = -5, relMax = 2, delta = 2
6: relMin = -5, relMax = 6, delta = 11
7:
....
13: relMin = -7, relMax = 6, delta = 13
....
Essentially what you're doing is writing to your output array any time your current delta is not equal to your previous delta. Since a change between relMin and relMax is mutually exclusive (only one of those values can change as you traverse the array) all you have to check for is inequality...
//prime your values
//if it make sense for your purposes prime them both with 0
//this also assumes you have at least 1 value in valueArray
relMin = valueArray[0];
relMax = valueArray[0];
//the following line will always be true if you use valueArray[0] as your relMin and relMax baseline
deltaArray[0] = 0;
for (i = 0; i < [valueArray count]; i++)
{
if (valueArray[i] < relMin)
{
relMin = valueArray[i];
}
if (valueArray[i] > relMax)
{
relMax = valueArray[i];
}
deltaPrevious = deltaArray[[deltaArray count] - 1];
deltaCurrent = relMax - relMin;
if (deltaCurrent != deltaPrevious)
{
deltaArray[deltaArray count] = deltaCurrent;
}
}
My approach to this problem would be to first write an algorithm that detects the indices of the maximums and minimums, and then finds differences from there.
To get the maxes and mins, I would recommend iterating through the array and looking at the difference between the current and the previous and next value. You need to looking at changes in sign of the differences:
A minimum will occur when the differences change from negative to positive, and a maximum will occur when the differences change from positive to negative.
For example, look at this part of your array: [1,2,6,5,3]. The difference from 1 to 2 is positive, from 2 to 6 is positive, but from 6 to 5 is negative. The sign of the differences changed from positive to negative at the 6, so we know it is a maximum.
Note that you also need to include the first and last elements as possible maxes or mins.
Once you get the indices of maximums and minimums, you should be able to get their differences fairly easily.
In a most basic sense, you could iterate through the array, checking to see if the next value is greater than or less than the previous value. Whenever you reach a change (was increasing, now decreasing, or vice versa) you have found a relative max/min (respectively). A for loop to iterate, a boolean flag to check against (whether you were increasing or decreasing) and the obvious knowledge of both your current and previous index in the array to check/store.
I don't quite feel comfortable giving exact code for this since it's very basic and seems very much like a homework question...

Resources