6 of 12

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

  1. Install Cropper.
  2. Install Cropper Plugins by placing the *.dll files into C:\Program Files (x86)\Fusion8Design\Cropper\plugins.
  3. Start Cropper and right-click into the blue rectangle. Set output to GIF.
  4. 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:

  1. Double click volume icon in lower, right corner of screen
  2. Set main level to 100
  3. Set individual audio sources to 10 (all of them! Redo this, when you have a new Application open, such as games, media player, etc...)
  4. 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:


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):

Front-Mic-In-+12-dB.m4a

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.

Back-Mic-In.m4a

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:

USB-Mic.m4a

There is still a high frequency hissing sound present, but this can easily be removed using Audacity.

USB-Mic-In-Cleaned.m4a

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:

editfloat in action

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);

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

% --- 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);