I have the following 2n*π-periodic function F(x) = sin(x/n) and I need to graph the dx/dt = γ - F(x) on the segment from 0 to 2pi. So it should look like this. I tried to do it matlab this way:
gamma = 1.01;
n=3;
[t,phi] = ode45(#(t,x)gamma-sin(x/n), [0,400], pi);
[t1,phi1] = ode45(#(t,x)gamma-sin(x/n), [112,400], 0);
[t2,phi2] = ode45(#(t,x)gamma-sin(x/n), [231,250], 0);
figure();
plot(t, phi, 'k', t1, phi1, 'k', t2, phi2, 'k');
ylim([0 2*pi]);
yticks([0 pi 2*pi]);
yticklabels(["0" "\pi" "2\pi"]);
grid on; grid minor;
title('\itsin(x/n)')
but I only got something like this. So there the lines are not transferred, but "begin anew". does anyone here know how to do that?
I get a plot similar to your first sketch, and based on your code in the comments (in future, put such additions into the question itself, use formatting to mark it as addition, and cite it then in the comment) with the changes
use pi as initial point as seen in the drawing,
use the options of the ODE solver to restrict the step size, directly and by imposing error tolerances
your original time span covers about 3 periods, reduce this to [0, 200] to get the same features as the drawing.
gamma = 1.01; n=3;
opts = odeset('AbsTol',1e-6,'RelTol',1e-9,'MaxStep',0.1);
[t, phi] = ode45(#(t,x)gamma-sin(x/n), [0,200], pi, opts);
phi = mod(phi, 2*pi);
plot(t, phi, 'k');
ylim([0 2*pi]); yticks([0 pi 2*pi]); yticklabels(["0" "\pi" "2\pi"]);
grid on; grid minor;
title('\itsin(x/n)')
To get more elaborate, use events to get points on the numerical solution where it exactly crosses the 2*pi periods, then use that to segment the solution plot (styling left out)
function [ res, term, dir ] = event(t,y)
y = mod(y+pi,2*pi)-pi;
res = [ y ];
dir = [1]; % only crossing upwards
term = [0]; % do not terminate
end%function
opts = odeset(opts,'Events',#(t,y)event(t,y));
sol = ode45(#(t,x)gamma-sin(x/n), [0,200], pi, opts);
tfs = [ sol.xe; sol.x(end) ]
N = length(tfs)
clf;
t0 = 0;
for i=1:N
tf = tfs(i);
t = linspace(t0+1e-2,tf-1e-2,150);
y = deval(sol,t); % octave: deval=#(res,t) interp1(res.x, res.y,t)
y = mod(y,2*pi);
plot(t, y);
hold on;
t0=tf;
end;
hold off;
is there a way how to custom format ridiculously large numbers (at least up to 10^100 in both ways) in google sheets:
thousands > K
millions > M
billions > B
trillions > T
etc...
negative quadrillions > Q
decillions > D
either via:
internal custom number formatting
formula (array formula ofc)
script similar to this one just extended to cover more ground
10000.1 10.0K
100 100.0
1000 1.0K
10000 10.0K
-100000 -100.0K
45646454 45.6M
5654894844216 5.7T
4655454544 4.7B
46546465455511 46.5T
-46546465455511 -46.5T
4654646545551184854556546454454400000000000000000000000000010000000 4.7U
-1000.9999 -1.0K
-100.8989 -100.9
-20.354 -20.4
1.03 1.0
22E+32 2.2D
internal custom number formatting solution:
sadly, the internal formatting in google sheets is by default able to work with only 3 types of numbers:
positive (1, 2, 5, 10, ...)
negative (-3, -9, -7, ...)
zero (0)
this can be tweaked to show custom formatting like thousands K, millions M and regular small numbers:
[>999999]0.0,,"M";[>999]0.0,"K";0
or only thousands K, millions M, billions B
[<999950]0.0,"K";[<999950000]0.0,,"M";0.0,,,"B"
or only negative thousands K, negative millions M, negative billions B
[>-999950]0.0,"K";[>-999950000]0.0,,"M";0.0,,,"B"
or only millions M, billions B, trillions T:
[<999950000]0.0,,"M";[<999950000000]0.0,,,"B";0.0,,,,"T"
or only numbers from negative million M to positive million M:
[>=999950]0.0,,"M";[<=-999950]0.0,,"M";0.0,"K"
but you always got only 3 slots you can use, meaning that you can't have trillions as the 4th type/slot. fyi, the 4th slot exists, but it's reserved for text. to learn more about internal formatting in google sheets see:
https://developers.google.com/sheets/api/guides/formats#meta_instructions
https://www.benlcollins.com/spreadsheets/google-sheets-custom-number-format/
formula (array formula) solution:
the formula approach is more versatile... first, you will need to decide on the system/standard you want to use (American, European, Greek, International, Unofficial, etc...):
en.wikipedia.org/wiki/Names_of_large_numbers
en.wikipedia.org/wiki/Metric_prefix
simple.wikipedia.org/wiki/Names_for_large_numbers
home.kpn.nl/vanadovv/BignumbyN
after that try:
=INDEX(REGEXREPLACE(IFNA(TEXT(A:A/10^(VLOOKUP(LEN(TEXT(INT(ABS(A:A)), "0"))-1,
SEQUENCE(35, 1,, 3), 1, 1)), "#.0")&VLOOKUP(ABS(A:A)*1, {{10^SEQUENCE(34, 1, 3, 3)},
{"K "; "M "; "B "; "T "; "Qa "; "Qi "; "Sx "; "Sp "; "O "; "N "; "D "; "Ud ";
"Dd "; "Td "; "Qad"; "Qid"; "Sxd"; "Spd"; "Od "; "Nd "; "V "; "Uv "; "Dv "; "Tv ";
"Qav"; "Qiv"; "Sxv"; "Spv"; "Ov "; "Nv "; "Tr "; "Ut "; "Dt "; "Tt "}}, 2, 1),
IF(ISBLANK(A:A),, TEXT(A:A, "0.0 "))), "^0\.0 $", "0 "))
works with positive numbers
works with negative numbers
works with zero
works with decimal numbers
works with numeric values
works with plain text numbers
works with scientific notations
works with blank cells
works up to googol 10^104 in both ways
extra points if you are interested in how it works...
let's start with virtual array {{},{}}. SEQUENCE(34, 1, 3, 3) will give us 34 numbers in 1 column starting from number 3 with the step of 3 numbers:
these will be used as exponents while rising 10 on the power ^
so our virtual array will be:
next, we insert it as the 2nd argument of VLOOKUP where we check ABS absolute values (converting negative values into positive) of A column multiplied by *1 just in case values of A column are not numeric. via VLOOKUP we return the second 2 column and as the 4th argument, we use approximate mode 1
numbers from -999 to 999 will intentionally error out at this point so we could later use IFNA to "fix" our errors with IF(A:A=IF(,,),, TEXT(A:A, "#.0 ")) translated as: if range A:A is truly empty ISBLANK output nothing, else format A column with provided pattern #.0 eg. if cell A5 = empty, the output will be blank cell... if -999 < A5=50 < 999 the output will be 50.0
and the last part:
TEXT(A:A/10^(VLOOKUP(LEN(TEXT(INT(ABS(A:A)), "0"))-1,
SEQUENCE(35, 1,, 3), 1, 1)), "#.0")
ABS(A:A) to convert negative numbers into positive. INT to remove decimal numbers if any. TEXT(, "0") to convert scientific notations 3E+8 into regular numbers 300000000. LEN to count digits. -1 to correct for base10 notation. VLOOKUP above-constructed number in SEQUENCE of 35 numbers in 1 column, this time starting from number 0 ,, with the step of 3 numbers. return via VLOOKUP the first 1 column (eg. the sequence) in approximate mode 1 of vlookup. insert this number as exponent when rising the 10 on power ^. and take values in A column and divide it by the above-constructed number 10 raised on the power ^ of a specific exponent. and lastly, format it with TEXT as #.0
to convert ugly 0.0 into beautiful 0 we just use REGEXREPLACE. and INDEX is used instead of the longer ARRAYFORMULA.
sidenote: to remove trailing spaces (which are there to add nice alignment lol) either remove them from the formula or use TRIM right after INDEX.
script solution:
gratitude to #TheMaster for covering this
here is a mod of it:
/**
* formats various numbers according to the provided short format
* #customfunction
* #param {A1:C100} range a 2D array
* #param {[X1:Y10]} database [optional] a real/virtual 2D array
* where the odd column holds exponent of base 10
* and the even column contains format suffixes
* #param {[5]} value [optional] fix suffix to fixed length
* by padding spaces (only if the second parameter exists)
*/
// examples:
// =CSF(A1:A)
// =CSF(2:2; X5:Y10)
// =CSF(A1:3; G10:J30)
// =CSF(C:C; X:Y; 2) to use custom alignment
// =CSF(C:C; X:Y; 0) to remove alignment
// =INDEX(TRIM(CSF(A:A))) to remove alignment
// =CSF(B10:D30; {3\ "K"; 4\ "TK"}) for non-english sheets
// =CSF(E5, {2, "deci"; 3, "kilo"}) for english sheets
// =INDEX(IF(ISERR(A:A*1); A:A; CSF(A:A))) to return non-numbers
// =INDEX(IF((ISERR(A:A*1))+(ISBLANK(A:A)), A:A, CSF(A:A*1))) enforce mode
function CSF(
range,
database = [
[3, 'K' ], //Thousand
[6, 'M' ], //Million
[9, 'B' ], //Billion
[12, 'T' ], //Trillion
[15, 'Qa' ], //Quadrillion
[18, 'Qi' ], //Quintillion
[21, 'Sx' ], //Sextillion
[24, 'Sp' ], //Septillion
[27, 'O' ], //Octillion
[30, 'N' ], //Nonillion
[33, 'D' ], //Decillion
[36, 'Ud' ], //Undecillion
[39, 'Dd' ], //Duodecillion
[42, 'Td' ], //Tredecillion
[45, 'Qad'], //Quattuordecillion
[48, 'Qid'], //Quindecillion
[51, 'Sxd'], //Sexdecillion
[54, 'Spd'], //Septendecillion
[57, 'Od' ], //Octodecillion
[60, 'Nd' ], //Novemdecillion
[63, 'V' ], //Vigintillion
[66, 'Uv' ], //Unvigintillion
[69, 'Dv' ], //Duovigintillion
[72, 'Tv' ], //Trevigintillion
[75, 'Qav'], //Quattuorvigintillion
[78, 'Qiv'], //Quinvigintillion
[81, 'Sxv'], //Sexvigintillion
[84, 'Spv'], //Septenvigintillion
[87, 'Ov' ], //Octovigintillion
[90, 'Nv' ], //Novemvigintillion
[93, 'Tr' ], //Trigintillion
[96, 'Ut' ], //Untrigintillion
[99, 'Dt' ], //Duotrigintillion
[100, 'G' ], //Googol
[102, 'Tt' ], //Tretrigintillion or One Hundred Googol
],
value = 3
) {
if (
database[database.length - 1] &&
database[database.length - 1][0] !== 0
) {
database = database.reverse();
database.push([0, '']);
}
const addSuffix = num => {
const pad3 = (str = '') => str.padEnd(value, ' ');
const decim = 1 // round to decimal places
const separ = 0 // separate number and suffix
const anum = Math.abs(num);
if (num === 0)
return '0' + ' ' + ' '.repeat(separ) + ' '.repeat(decim) + pad3();
if (anum > 0 && anum < 1)
return String(num.toFixed(decim)) + ' '.repeat(separ) + pad3();
for (const [exp, suffix] of database) {
if (anum >= Math.pow(10, exp))
return `${(num / Math.pow(10, exp)).toFixed(decim)
}${' '.repeat(separ) + pad3(suffix)}`;
}
};
return customFunctionRecurse_(
range, CSF, addSuffix, database, value, true
);
}
function customFunctionRecurse_(
array, mainFunc, subFunc, ...extraArgToMainFunc
) {
if (Array.isArray(array))
return array.map(e => mainFunc(e, ...extraArgToMainFunc));
else return subFunc(array);
}
sidenote 1: this script does not need to be authorized priorly to usage
sidenote 2: cell formatting needs to be set to Automatic or Number otherwise use enforce mode
extra:
convert numbers into plain text strings/words
convert array of numbers into plain text strings/words
convert custom formatted numbers into numeric numbers/values
convert text string datetime into duration value
convert text string formatted numbers into duration
convert your age into years-months-days
For almost all practical purposes we can use Intl compact format to achieve this functionality.
/**
* Utility function needed to recurse 2D arrays
*/
function customFunctionRecurse_(
array,
mainFunc,
subFunc,
...extraArgToMainFunc
) {
if (Array.isArray(array))
return array.map(e => mainFunc(e, ...extraArgToMainFunc));
else return subFunc(array);
}
/**
* Simple custom formating function using Intl
* #see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/NumberFormat/NumberFormat
* #customfunction
* #author TheMaster https://stackoverflow.com/users/8404453
* #param {A1:D2} numArr A 2D array
* #returns {String[][]}Compact Intl formatted 2D array
*/
function format(numArr) {
const cIntl = new Intl.NumberFormat('en-GB', {
notation: 'compact',
compactDisplay: 'short',
});
return customFunctionRecurse_(numArr, format, (num) => cIntl.format(num));
}
But for extreme ends or custom formatting, We need to use a custom script:
/**
* Formats various numbers according to the provided format
* #customfunction
* #author TheMaster https://stackoverflow.com/users/8404453
* #param {A1:D2} numArr A 2D array
* #param {X1:Y2} formatArr [optional] A format 2D real/virtual array
* with base 10 power -> suffix mapping
* eg: X1:3 Y1:K represents numbers > 10^3 should have a K suffix
* #param {3} suffixPadLength [optional] Fix suffix to fixed length by padding spaces
* #returns {String[][]} Formatted 2D array
*/
function customFormat(
numArr,
formatArr = [
/**This formatArr array is provided by
* by player0 https://stackoverflow.com/users/5632629/
* #see https://stackoverflow.com/questions/69773823#comment123503634_69809210
*/
[3, 'K'], //Thousand
[6, 'M'], //Million
[9, 'B'], //Billion
[12, 'T'], //Trillion
[15, 'Qa'], //Quadrillion
[18, 'Qi'], //Quintillion
[21, 'Sx'], //Sextillion
[24, 'Sp'], //Septillion
[27, 'O'], //Octillion
[30, 'N'], //Nonillion
[33, 'D'], //Decillion
[36, 'Ud'], //Undecillion
[39, 'Dd'], //Duodecillion
[42, 'Td'], //Tredecillion
[45, 'Qad'], //Quattuordecillion
[48, 'Qid'], //Quindecillion
[51, 'Sxd'], //Sexdecillion
[54, 'Spd'], //Septendecillion
[57, 'Od'], //Octodecillion
[60, 'Nd'], //Novemdecillion
[63, 'V'], //Vigintillion
[66, 'Uv'], //Unvigintillion
[69, 'Dv'], //Duovigintillion
[72, 'Tv'], //Trevigintillion
[75, 'Qav'], //Quattuorvigintillion
[78, 'Qiv'], //Quinvigintillion
[81, 'Sxv'], //Sexvigintillion
[84, 'Spv'], //Septenvigintillion
[87, 'Ov'], //Octovigintillion
[90, 'Nv'], //Novemvigintillion
[93, 'Tr'], //Trigintillion
[96, 'Ut'], //Untrigintillion
[99, 'Dt'], //Duotrigintillion
[102, 'G'], //Googol
],
suffixPadLength = 3,
inRecursion = false
) {
if (!inRecursion) {
formatArr = formatArr.reverse();
formatArr.push([0, '']);
}
const addSuffix = num => {
const pad3 = (str = '') => str.padEnd(suffixPadLength, ' '); //pad 3 spaces if necessary
const anum = Math.abs(num);
if (num === 0) return '0' + pad3();
if (anum > 0 && anum < 1) return String(num.toFixed(2)) + pad3();
for (const [exp, suffix] of formatArr) {
if (anum >= Math.pow(10, exp))
return `${(num / Math.pow(10, exp)).toFixed(2)}${pad3(suffix)}`;
}
};
return customFunctionRecurse_(
numArr,
customFormat,
addSuffix,
formatArr,
suffixPadLength,
true
);
}
Usage:
=CUSTOMFORMAT(A1:A5,{{3,"k"};{10,"G"}})
Tells custom function to use k for numbers>10^3 and G for 10^10
Illustration:
/*<ignore>*/console.config({maximize:true,timeStamps:false,autoScroll:false});/*</ignore>*/
/**
* Utility function needed to map 2D arrays
*/
function customFunctionRecurse_(array, mainFunc, subFunc, extraArgToMainFunc) {
if (Array.isArray(array))
return array.map((e) => mainFunc(e, extraArgToMainFunc));
else return subFunc(array);
}
/**
* Simple custom formating function using Intl
* #see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/NumberFormat/NumberFormat
* #customfunction
* #param {A1:D2} A 2D array
* #returns {String[][]}Compact Intl formatted 2D array
*/
function format(numArr) {
const cIntl = new Intl.NumberFormat('en-GB', {
notation: 'compact',
compactDisplay: 'short',
});
return customFunctionRecurse_(numArr, format, (num) => cIntl.format(num));
}
/**
* Formats various numbers according to the provided format
* #customfunction
* #param {A1:D2} A 2D array
* #param {X1:Y2=} [optional] A format 2D real/virtual array
* with base 10 power -> suffix mapping
* eg: X1:3 Y1:K represents numbers > 10^3 should have a K suffix
* #returns {String[][]} Formatted 2D array
*/
function customFormat(
numArr,
formatArr = [
//sample byte => kb formatting
[3, 'kb'],
[6, 'mb'],
[9, 'gb'],
[12, 'tb'],
]
) {
//console.log({ numArr, formatArr });
if (
formatArr[formatArr.length - 1] &&
formatArr[formatArr.length - 1][0] !== 0
) {
formatArr = formatArr.reverse();
formatArr.push([0, '']);
}
const addSuffix = (num) => {
const anum = Math.abs(num);
if (num === 0) return '0.00';
if (anum > 0 && anum < 1) return String(num.toFixed(2));
for (const [exp, suffix] of formatArr) {
if (anum >= Math.pow(10, exp))
return `${(num / Math.pow(10, exp)).toFixed(2)}${suffix}`;
}
};
return customFunctionRecurse_(numArr, customFormat, addSuffix, formatArr);
}
console.log(
customFormat([
[
0,
1000,
153,
12883255,
235688235123,
88555552233355888,
-86555,
0.8523588055,
Math.pow(10, 15),
],
])
);
<!-- https://meta.stackoverflow.com/a/375985/ --> <script src="https://gh-canon.github.io/stack-snippet-console/console.min.js"></script>
sometimes when we deal with nuclear physics we need to shorten the time so this is how:
=INDEX(IF(ISBLANK(A2:A),,TEXT(TRUNC(TEXT(IF(A2:A*1<1,
TEXT(A2:A*1, "0."&REPT(0, 30))*VLOOKUP(A2:A*1, {SORT({0; 1/10^SEQUENCE(9, 1, 3, 3)}),
{0; 10^SORT(SEQUENCE(9, 1, 3, 3), 1,)}}, 2, 1), TEXT(A2:A*1, REPT(0, 30))/
VLOOKUP(A2:A*1, TEXT({1; 60; 3600; 86400; 31536000; 31536000*10^SEQUENCE(8, 1, 3, 3)},
{"#", "#"})*1, 2, 1)), "0."&REPT("0", 30)), 3), "0.000")&" "&
VLOOKUP(A2:A*1, {SORT({0; 1/10^SEQUENCE(9, 1, 3, 3);
{1; 60; 3600; 86400; 31536000}; 31536000*10^SEQUENCE(8, 1, 3, 3)}), FLATTEN(SPLIT(
"s ys zs as fs ps ns μs ms s m h d y ky My Gy Ty Py Ey Zy Yy", " ",,))}, 2, 1)))
it's a simple conversion from seconds into abbreviation utilizing the International System of Units where:
in seconds
____________________________________
ys = yoctosecond = 0.000000000000000000000001
zs = zeptosecond = 0.000000000000000000001
as = attosecond = 0.000000000000000001
fs = femtosecond = 0.000000000000001
ps = pikosecond = 0.000000000001
ns = nanosecond = 0.000000001
μs = microsecond = 0.000001
ms = millisecond = 0.001
s = second = 1
m = minute = 60
h = hour = 3600
d = day = 86400
y = year = 31536000
ky = kiloyear = 31536000000
My = megayear = 31536000000000
Gy = gigayear = 31536000000000000
Ty = terayear = 31536000000000000000
Py = petayear = 31536000000000000000000
Ey = exayear = 31536000000000000000000000
Zy = zettayear = 31536000000000000000000000000
Yy = yottayear = 31536000000000000000000000000000
Hi Iam using mindwave to control with OSC some Ndefs. I need to write a function that chooses from a list (eg [x, f]) the next and stops the previous. Also I need to be able to play only the first Ndef (eg x) and not the second (eg f) until I get the appropriate message (eg msg[3]) and at the same time to stop x. Here is my try which doesnt work as wanted:
(
OSCdef.new(
\select,
{
arg msg, time, addr, port;
[msg, time, addr, port].postln;
if ((msg[3] > 200), {x.clear;} && {f.play;});
},'/neurovals'
);
SynthDef.new(\Syn, { arg freq = 440, amp = 1, sustain = 0.5;
var sig, env, mod;
env = EnvGen.kr(Env.linen(0.05, sustain, 0.5, 0.08), doneAction: 2);
mod = Saw.ar(freq * 0.1) * LFNoise1.kr(2).range(10,800);
sig = SinOsc.ar(freq + mod) * env;
Out.ar(0, RLPF.ar(sig, freq, 1.7)).dup;
}).add;
x= Ndef(\blinkpat1, Pbind(
\instrument, \Syn,
\dur, 0.03,
\freq, 440
));
OSCdef.new(
\base,
{
arg msg, time, addr, port;
[msg, time, addr, port].postln;
if ((msg[1] == msg[1]),
{x.set(\freq, msg[1].linlin(0, 100, 300, 1000);)});
},'/neurovals'
);
SynthDef.new(\fmsyn, { arg freq = 440, amp = 1, sustain = 1;
var sig, env, mod;
env = EnvGen.kr(Env.linen(0.05, sustain, 0.5, 0.08), doneAction: 2);
mod = SinOsc.ar(freq * 0.5) * LFNoise1.kr(2).range(10,800);
sig = SinOsc.ar(freq + mod) * env;
Out.ar(0, RLPF.ar(sig, freq, 1.7)).dup;
}).add;
f = Ndef(\blinkpat2, Pbind(
\instrument, \fmsyn,
\freq, 440,
\sustain, 2,
\octave, 3,
\amp, 0.4,
));
OSCdef.new(
\base2,
{
arg msg, time, addr, port;
[msg, time, addr, port].postln;
if ((msg[1] == msg[1]),
{f.set(\freq, msg[1].linlin(0, 100, 300, 1000);)});
if ((msg[1] == msg[1]),
{f.set(\sustain, msg[1].linlin(0, 100, 1, 2);)});
},'/neurovals'
);
)
Firstly, this if statement:
if ((msg[3] > 200), {x.clear;} && {f.play;});
is strange - it's not clear trying to get with that, but it's unlikely that it's doing what you want. The && is a boolean operator, so the general expectation is the left and right sides are true/false. In your use, it's actually performing function composition on the left and right hand side functions, but that still isn't doing anything coherent, given your functions. I think what you probably intended is:
if (msg[3] > 200) {
x.clear;
f.play;
}
....which will clear x and play f.
There are a number of ways you can do what I think you're trying to do. Here's one suggestion - Pdef's can be assigned to each other, and hot swapped during playback. This means, you can do:
( // set up \a, \b, and \player, and start playing \player
Pdef(\a, Pbind(
\dur, 1/4,
\degree, 0,
));
Pdef(\b, Pbind(
\dur, 1/3,
\degree, 2,
));
\\ Start playing an empty Pdef to use later.
Pdef(\player).play;
)
Then, you can set \player to one of \a or \b to transparently switch between them:
// Assign Pdef(\a) to player, to start it playing
Pdef(\player, Pdef(\a));
// Assign Pdef(\b) to player, which starts \b and stops \a
Pdef(\player, Pdef(\b));
I am creating a GUI where a user inputs a value and when he presses a pushbutton it runs an external function and displays error messages. I am having trouble with inserting the variable successfully in the GUI coding. I am confused as to where to insert my variable. I have tried handles but unfortunately its not working.
% --- Executes just before Stallfunction is made visible.
function Stallfunction_OpeningFcn(hObject, ~, handles, varargin)
% This function has no output args, see OutputFcn.
% hObject handle to figure
% eventdata reserved - to be defined in a future version of MATLAB
% handles structure with handles and user data (see GUIDATA)
% varargin command line arguments to Stallfunction (see VARARGIN)
% Choose default command line output for Stallfunction
handles.user_entry = user_entry;
% Update handles structure
guidata(hObject, handles);
% UIWAIT makes Stallfunction wait for user response (see UIRESUME)
% uiwait(handles.figure1);
I have inserted the variable in the above code, which is 'user_entry' is that correct?
user_entry is not assigned a value in your function. If you launch your GUI by passing a value for user_entry like this:
Stallfunction(user_entry)
then the first lines of your code in the openingFcn should be:
if ~isempty(varargin)
user_entry = varargin{1};
else
error('please start the GUI with an input value')
end
After this, you can assign user_entry to the handles structure as you're doing already.
Try this:
function num = get_num()
fig = figure('Units', 'characters', ...
'Position', [70 20 30 5], ...
'CloseRequestFcn', #close_Callback);
edit_num = uicontrol(...
'Parent', fig, ...
'Style', 'edit', ...
'Units', 'characters', ...
'Position', [1 1 10 3], ...
'HorizontalAlignment', 'left', ...
'String', 'init', ...
'Callback', #edit_num_Callback);
button_finish = uicontrol( ...
'Parent', fig, ...
'Tag', 'button_finish', ...
'Style', 'pushbutton', ...
'Units', 'characters', ...
'Position', [15 1 10 3], ...
'String', 'Finish', ...
'Callback', #button_finish_Callback);
% Nested functions
function edit_num_Callback(hObject,eventdata)
disp('this is a callback for edit box');
end
function button_finish_Callback(hObject,eventdata)
% Exit
close(fig);
end
function close_Callback(hObject,eventdata)
num_prelim = str2num(get(edit_num,'string'));
if(isempty(num_prelim))
errordlg('Must be a number.','Error','modal');
return;
end
num = num_prelim;
delete(fig);
end
waitfor(fig);
end
See if you can mess with this and get what you want. Also, learn to use nested functions and how callbacks work in matlab. Save this as a function file and then call "num = getnum;"
I am using Octave.
My problem is this: I want to fill the bubbles of my scatter plot, as well as place a legend. But I get errors when I try to use 'filled', and no legend comes up when I use legend(...).
Part of my code looks like this:
%ALL SAMPLES, PHI(Signal) # THETA(Sample)=0
figure(5)
plot( Angles(:,1)([18:27]), ALL([18:27]), 10, [1 0 1]); %Magenta
hold on
scatter(Angles(:,1)([68:76]), ALL([68:76]), 10, [0 0 0]); %Black
scatter(Angles(:,1)([86:95]), ALL([86:95]), 10, [1 0 0]); %Red
scatter(Angles(:,1)([119:127]), ALL([119:127]), 10, [0 1 0]); %Green
scatter(Angles(:,1)([133:141]), ALL([133:141]), 10, [0 0 1]); %Blue
hold off
xlabel('Signal PMT angle (Sample angle at 0)');
ylabel('Normalized (signal/monitor) intensity');
legend('Control', 'Control', '1+2','Virgin','Cycle #1', 'Location','NorthEast');
title('Plot of All Samples, "-int Intensity"')
I know it should beplot( Angles(:,1)([18:27]), ALL([18:27]), 10, [1 0 1], 'filled');, but I receive errors when I do that. Also, a legend never seems to show up.
Apparently there is a problem with using legend with scatter in Octave. Based on this post:
http://octave.1599824.n4.nabble.com/Legend-in-scatter-plot-td3568032.html
the trick is to use the plot function to make scatter plot. I wrote the following function for plotting a bunch of scatter plots on the same axis.
This function takes in a bunch of cell arrays of the same length. Each element of the cell array corresponds to a separate series. The function returns a cell array of the same length containing the handle associated with each plot. The arguments of the function are explained below:
x_vals: a cell array of arrays of doubles corresponding to x values.
y_vals: a cell array of arrays of doubles corresponding to y values.
sizes: a cell array of doubles representing the size of the markers.
colors: a cell array of double arrays of length 3, representing [R, G, B] color values of the markers.
styles: a cell array of strings representing the shape of the markers.
function [handles] = scatter_series_set(x_vals, y_vals, sizes, colors, styles)
N = length(x_vals);
if ( (~ ( N == length(y_vals))) || (~ ( N == length(sizes))) || ...
(~ ( N == length(colors))) || (~ ( N == length(styles))) )
error('scatter_series_set: all arguments must be cell arrays of the same length');
end
%plot the first series
handles = cell([N, 1]);
handles{1} = plot(x_vals{1}, y_vals{1});
set(handles{1}, 'linestyle', 'none');
set(handles{1}, 'marker', styles{1});
set(handles{1}, 'markersize', sizes{1});
set(handles{1}, 'color', colors{1});
%plot additional series if present
if N > 1
hold on;
for ind = 2:N
handles{ind} = plot(x_vals{ind}, y_vals{ind});
set(handles{ind}, 'linestyle', 'none');
set(handles{ind}, 'marker', styles{ind});
set(handles{ind}, 'markersize', sizes{ind});
set(handles{ind}, 'color', colors{ind});
end
hold off;
end
end
The following example demonstrates how to use this function.
x1 = 0:(2*pi/100):(2*pi);
x2 = 2*x1;
y1 = sin(x1);
y2 = cos(x1);
y3 = sin(x2);
y4 = cos(x2);
names = {'a', 'b', 'c', 'd'};
x_vals = {x1, x1, x1, x1};
y_vals = {y1, y2, y3, y4};
sizes = {10, 10, 10, 10};
colors = {[1, 0, 0], [0, 0, 1], [0, 0, 0], [0.7071, 0, 0.7071]};
styles = {'^', 's', 'x', '+'}
scatter_series_set(x_vals, y_vals, sizes, colors, styles);
legend(names, 'location', 'southeast');
The example code produces the following plot:
The following works for me:
n = 100;
x = randn(n, 1);
y = randn(n, 1);
S = rand(n, 1)*20;
hold on
scatter(x(1:50), y(1:50), S(1:50), "red", "filled")
scatter(x(51:100), y(51:100), S(51:100), "green", "filled")
hold off
print('-depsc', 'bubbleplot.eps');
However, I'm not able to add a legend, and I didn't find any bug report or indication of a missing functionality for this. So, as an alternative, I would suggest adding marker and text to your plot.