Useful Windows Batch File Snippets
REM This is a comment
:: This is too, but only newer CMD versions
echo hello &:: This is a line comment, because & seperates commands
REM Set and display variables:
set a=5
echo %a%
set a=5 & echo %a% &:: Not equivalent! Not evaluated left to right!
REM Show available commands:
help
REM Show help on specific commands (both display the same):
help dir
dir /?
REM Redirect command output to file:
dir > test.txt
REM Append command output to file:
dir >> test.txt
REM Show File contents:
type test.txt
REM Redirect command output to another command:
type test.txt | more
How to make GIF screenshots
- Install Cropper.
- Install Cropper Plugins by
placing the *.dll files into
C:\Program Files (x86)\Fusion8Design\Cropper\plugins
. - Start Cropper and right-click into the blue rectangle. Set output to GIF.
- In Cropper Options (Right Click -> Options -> Appearance), make sure, "Hide Crop Window" is checked for both "during capture" and "after capture". This is counterintuitive (a bug?), because "Capture" appears to only be the first frame, otherwise the other frames of the GIF would show the blue overlay.
Note that it only works this "nicely" (not counting the "hiding after capture" weirdness) with the GIF plugin - the AVI capture does not work this nicely.
USB Headset and Windows: Volume too loud
I have only two issues with my recently purchased headset. The volume is too loud, and the granularity to adjust it is too course. Even on 2/100, the lowest setting, YouTube is screaming at me.
I can live with the seriously messed up audio taper, as long as the minimum volume is somewhat reasonable. Unfortunately, the only way to reduce the mininum volume is:
- Double click volume icon in lower, right corner of screen
- Set main level to 100
- Set individual audio sources to 10 (all of them! Redo this, when you have a new Application open, such as games, media player, etc...)
- Set main level to 10.
In the screwed-up world of Microsoft User Interfaces, this is the only way to attenuate all sound sources by some factor (10? It almost feels like a linear scale), before the sound gets sent to the speakers.
Speech Recognition/Dictation on Windows 8
Windows comes with built-in speech recognition since Windows Vista. It's utterly unusable. Here are the main drawbacks:
- I can't interact with other programs while this thing is active. It somehow intercepts UI events, or maybe it just runs with such a high priority, that other programs don't get to update. Either way, it grinds my PC down to a halt.
- After half an hour I have up on dictating/spelling an "@", which I need for such exotic things such as dictating an email. I don't have the faintest idea how this might work.
- The help section is pretty useless. It keeps promising to show an "Interaction Card" or something like it, but instead opens a browser window that shows me Videos on what speech recognition can do. The videos are in English, my system is in German, so that doesn't help me at all. I gave up on using it. I wish Microsoft would have the balls to yank out unusable features - instead, the Windows install is ballooned to tens of GB with crap like this.
Audiorecorder on Windows 8: File Locations
Problem The App doesn't allow you to export the recordings.
Solution The files are .m4a files, and can be found in
C:\Users\YOUR_USER_NAME\AppData\Local\Packages \Microsoft.WindowsSoundRecorder_8wekyb3d8bbwe\LocalState\Indexed\Recordings
Headset with good microphone
I wanted to get a headset with a good microphone. I don't care too much about the speakers - as long as they sound reasonably balanced, I am happy. I first tried the Speedlink Medusa NX Gaming Headset (30 Euro at my local electronics store). The speaker quality was good, but the microphone was awfully noisy. Using the front MIC input of my PC, it sounded like this (Please ignore the nonsense text, I was getting familiar with the Audiorecorder App of Windows 8, which is another story entirely):
Note: This player doesn't seem to work on Firefox right now. I hope this is fixed in future Firefox/Wordpress releases.
I read somewhere that the back input can be less noisier, because the back input is closer to the ADC (the thing that digitizes the signal). This means there is no long cable going through the (noisy) PC intererior, where it picks up noise. The back input did sound better, but still not good.
So I went back to the store and upgraded to the Speedlink Medusa NX 7.1 Surround Headset USB. It's connected via USB, because it has its own soundcard. Because the DAC and ADC are outside of the PC case, and because they can be optimized for the speaker/microphone, this allows a better quality. Drawback: You can't plug it into you iPad and other portable devices.
The audio quality was indeed a lot better:
There is still a high frequency hissing sound present, but this can easily be removed using Audacity.
It's no studio quality, but I'm happy! The main drawback of this headset is that the speakers are a bit too loud.
Matlab GUI: Numeric input for serious work
Design goals
Need GUI element with the following properties:
- Accepts numeric input between a min and max
- Changes value on arrow up/arrow down
- The value change should depend on the caret position
- Bad input makes string and number default to suitable value.
- Doesn't waste screen real estate.
Why a JSpinner doesn't cut it
You can easily create Java Swing objects in your GUI, and the JSpinner is pretty close to what I need. But: To my knowledge, it does not support incrementing/decrementing the value based on the current caret position. The caret always jumps to the beginning of the string.
Example:
f = figure;
jSpinner = javaObjectEDT('javax.swing.JSpinner');
javacomponent(jSpinner);
About "editfloats"
I hacked on edittext fields until they became a bit like JSpinner, but without the superfluous arrows on the right-hand side. Arrow up/arrow down increments/decrements the digit to the right of the caret position. Because the hack is based on edittexts, I call these fields editfloats. The format, minimum, maximum, default number, and default string properties are stored inside the 'UserData' property of the edittext.
The callbacks I needed are not accessible with the Matlab handles. Instead, I use the handles of the underlying Java swing components. Yair Altman wrote an excellent FindJObj function for finding those handles.
I use these edifloat elements in all my GUIs that I had made earlier
(using GUIDE). It's just as easy to put them into GUIs that were
created programmatically (without GUIDE). Caveat: Using java handles
often needs the GUI to be
visible. Therefore I
placed the FindJObj function in GUIDE's autocreated ..._OutputFcn
,
which is called after the GUI is made visible. If you instead use the
..._OpeningFcn
(called when the figure is invisible), the figure will
be made visible/invisible multiple times, and figure creation will take
a long time.
Preparations for creating editfloats
I moved the meaty stuff into external function files, because many of my GUIs and GUI elements will share this code.
The function editfloat_setup.m
takes the handle of an edittext and
sets up the appropriate Callbacks to make it an editfloat.
function floatstr_edit_setup(h, options)
% Takes the handle of an edit_text, and sets up callbacks such that it
% becomes a float_edit box, with arrowup/arrowdown functionality.
% Needs an options struct, which is attached to h as user_data. Must
% contain fields:
% - .format Format of the floating point number
% - .min Minimum number
% - .max Maximum Number
% - .default_num Default Number (for bad input)
% - .default_str Default String (for bad input)
set(h, 'UserData', options)
set(h, 'FontName', 'Courier', 'FontSize', 10)
% Sets callback, calls it to make sure string is in suitable format
set(h,'Callback',@editfloat_Callback);
editfloat_Callback(h, 0)
% Note: 'persistent' fails when the GUI is closed and started again. You need to
% restart Matlab in this case. I stopped using 'persistent'.
% Sets up Callback of underlying Java Swing object.
jh = findjobj(h, 'nomenu'); % external function by Yair Altman.
set(jh,'KeyPressedCallback', ...
{@editfloat_KeyPressedCallback_Java, h});
Because the user is explicity allowed to enter any text into the
editfloat field, we need a function editfloat_Callback
to make sure
the user input is valid.
function editfloat_Callback(hObject,~)
% Called on "commit" event ("Enter" and "LostFocus" or so).
% Parses the element's input and updates the string with parsed input.
edit_str = get(hObject, 'String');
user_data = get(hObject, 'UserData');
[~, clean_str] = editfloat_str_parser(edit_str, user_data);
set(hObject, 'String', clean_str)
Arrow up/arrow down functionality happens inside the
editfloat_KeyPressedCallback_Java Callback
. This checks if the key
pressed was an arrow up or arrow down key, and then
increments/decrements the current value by a value that depends on the
caret position.
function editfloat_KeyPressedCallback_Java(jhObject, event, hObject)
% Called on each button press inside edit text.
% Increments/decrements the value at the current caret position.
% Needs the following fields in the "user_data" struct:
% - .format Format of the floating point number
% - .min Minimum number
% - .max Maximum Number
% - .default_num Default Number (for bad input)
% - .default_str Default String (for bad input)
keynum = get(event, 'keyCode');
if keynum==38 || keynum==40 % arrow up or arrow down
user_data = get(hObject, 'UserData');
% format = user_data.format;
caret_position = get(jhObject, 'CaretPosition') + 1; %matlab indexing
current_str = get(jhObject, 'Text'); %using jhObject, because during edition, hObject contains old stuff
[old_num, parsed_str] = editfloat_str_parser(current_str, user_data);
if caret_position > length(parsed_str)
% we're at the end of the string. do nothing
return
end
if length(parsed_str) ~= length(current_str)
% User was during input. Update field, return
% Update: In the current version, this is impossible, I think
set(hObject, 'String', parsed_str)
drawnow;
return
end
% Prepare a delta_str -> delta_num from the given string and the caret
% position.
numeric_period = int16('.');
delta_str = parsed_str;
delta_str(parsed_str ~= numeric_period) = '0'; % -> 00000.00000 or so
new_num = old_num;
if ~strcmp(delta_str(caret_position), '.')
delta_str(caret_position) = '1'; % -> 00100.00000 or so
delta_num = str2double(delta_str);
if keynum == 38 % up
new_num = new_num + delta_num;
elseif keynum == 40 %down
new_num = new_num - delta_num;
end
end
new_str = sprintf(user_data.format, new_num);
[~, new_str] = editfloat_str_parser(new_str, user_data);
set(hObject, 'String', new_str) %using hObject here, because jhObject led to weird errors
drawnow; % otherwise set() takes place after the setCaretPosition!
% Set correct caret position again. Adjust for possibly new string
% length.
length_difference = length(new_str) - length(current_str);
jhObject.setCaretPosition(caret_position - 1+length_difference);
drawnow; % I was getting more errors. Maybe this helps?
end
The fourth function you need is one that parses a string (usually the content of editfloat) and returns the number that the string represents together with a clean version of that string.
function [num, clean_str] = editfloat_str_parser(float_str, options)
% Converts float_str to a number. Returns this number as
% numeric and as a string.
%
% The input "options" must be a struct that contains the fields:
% - .format Output format of the number string.
% - .min Minimum number
% - .max Maximum Number
% - .default_num Default Number (for bad input)
% - .default_str Default String (for bad input)
% Example output_format: '%016.6f'
% - 0 padded to field length
% - 16 field length (including decimal point! -> 15 digits)
% - 6 digits after the decimal points
% - floating point
no_commas = strrep(float_str, ',', '.'); % having "," as decimal is fine
num = str2double(no_commas);
if isnan(num) % if contained text
num = options.default_num;
clean_str = options.default_str;
return
end
num = real(num); % only keep the real part
if num < options.min num = options.min; elseif num > options.max
num = options.max;
end
clean_str = sprintf(options.format, num);
Adding an editfloat to a GUI
- Save each function outlined above into its own file and put those file into Matlab's PATH.
- Using
GUIDE
, create an edittext field. (Mine has the tag ("name")FreqOffset_edittext
.) - In the GUI's
..._OutputFcn
, calleditfloat_setup
on the edittext.
% --- Outputs from this function are returned to the command line.
function varargout = Advanced_THEs_Plot_GUI_OutputFcn(hObject, eventdata, handles)
% varargout cell array for returning output args (see VARARGOUT);
% This function is executed just after the GUI is made visible. All the
% java swing object stuff needs the object to be visible, which is why the
% following code bits are here.
% Note:
% Makes edittext into editfloats by setting up the right callbacks (for
% arrowup/arrowdown functionality)
% FreqOffset field
editfloat_options.format = '%12.3f';
editfloat_options.min = 0;
editfloat_options.max = 100e6-1e-3;
editfloat_options.default_num = 0;
editfloat_options.default_str = '0.000';
editfloat_setup(handles.FreqOffset_edittext, editfloat_options)
You're done!
Useful Matlab snippets
%% Link two plots together so that the x-axis always shows the same range.
figure(1); ah(1) = gca; figure(2); ah(2) = gca; linkaxes(ah, 'x')
%% Copy lines from one figure to another
L = findobj(2,'type','line'); % first argument is the figure to copy from
for i = 1:length(L)
copyobj(L(i),findobj(3,'type','axes')); %first arg is figure to copy to
end
% By hand: Copy/Paste works too
%% Make line invisible to "legend" command. Mark line first!
hasbehavior(gco, 'legend', false);
%% Do Allan Deviation
xdata = get(get(gca,'Children'),'xdata');
% xdata = (xdata - xdata(1))*24*3600; % in s from env data
ydata = get(get(gca,'Children'),'ydata');
ydata = ydata*200e-6/20/87.6; % relative deviation
delta_t = mean(diff(xdata));
[~,ADEV,~,~,~,TAU] = avar(ydata,delta_t);
figure
loglog(TAU,ADEV,'x-')
set(gca,'YLim',[1e-8,1e-7])
%% Linear Fit with Fit uncertainty
% Fit *column* vectors x,y with linear polynomial y = a*x + b
% Remember to remove mean(x) first, if you want he errors to be
% uncorrelated!
cf = fit(x,y,'poly1');
cf_coeff = coeffvalues(cf);
cf_confint = confint(cf);
a = cf_coeff(1);
b = cf_coeff(2);
a_uncert = (cf_confint(2,1) - cf_confint(1,1))/2;
b_uncert = (cf_confint(2,2) - cf_confint(1,2))/2;
%% Smoothing with moving average
smoothing_length = 10;
filtered_data = filter(ones(1,smoothing_length)/smoothing_length,1,data);
%% Smoothing with butterworth filter
cutoff_freq = 0.02; % in Hz - this is a 50 second filter
sample_freq = 1/(mean(diff(time_data))*24*3600);
[A,B] = butter(2,cutoff_freq/(sample_freq/2));
filtered_data = filtfilt(A,B,data);