Friday, November 21, 2014

Remove unwanted results and other garbage from google searches

Do I have to even explain why this is useful?  I would just assume that people shouldn't naturally enjoy having their daily tasks obstructed by the injection of useless garbage into the information they're trying to parse, but the fact that part of this solution addresses social media links tells me this is probably not the case.

As usual, YARIP comes to the rescue.  To get rid of the top, bottom, and side ads:
//div[@id='tvcap']
//div[@id='bottomads']
//div[@id='rhs_block']
To get rid of extended results boxes for local business locations:
//div/li[@id='lclbox']
To remove all listings from a particular website from the search results:
//li[child::div/div/div/div/cite[contains(., 'pinterest.com')]]
//li[child::div/div/div/div/cite[contains(., 'facebook.com')]]
//li[child::div/div/div/div/cite[contains(., 'twitter.com')]]
//li[child::div/div/div/div/cite[contains(., 'huffingtonpost.com')]]
//li[child::div/div/div/div/cite[contains(., 'pitchfork.com')]]
While it's certainly nice to be able to slap that useless trash off the visible web, there are other more useful strategies for single-site blocking.  How about getting rid of sites that just dilute the results with repeated similar pages?
//li[child::div/div/div/div/cite[contains(., 'alibaba.com')]]
Google does provide several different forms of "extended results", such as the local business listings, maps, conversion utilities, image search previews, and youtube items.  Each of these can also be blocked depending on what irks you and what your browsing habits cause you to encounter.

Exclusion through YARIP is also a quick cure for frustration on any other sites that tend to return volumes of irrelevant or unwanted results for specific searches or where available search tools don't allow exclusions.  One of my current favorite applications is dealing with poor search refinement tools on internet job boards.  For example, perform case insensitive exclusion with in the job title field on LinkedIn:
//li[child::div/h3/a[contains(translate(., 'ABCDEFGHIJKLMNOPQRSTUVWXYZ', 'abcdefghijklmnopqrstuvwxyz'),  'sales engineer')]]
//li[child::div/h3/a[contains(translate(., 'ABCDEFGHIJKLMNOPQRSTUVWXYZ', 'abcdefghijklmnopqrstuvwxyz'),  'senior')]]
//li[child::div/h3/a[contains(translate(., 'ABCDEFGHIJKLMNOPQRSTUVWXYZ', 'abcdefghijklmnopqrstuvwxyz'),  'federal government')]]
//li[child::div/h3/a[contains(translate(., 'ABCDEFGHIJKLMNOPQRSTUVWXYZ', 'abcdefghijklmnopqrstuvwxyz'),  'information systems')]]
//li[child::div/h3/a[contains(translate(., 'ABCDEFGHIJKLMNOPQRSTUVWXYZ', 'abcdefghijklmnopqrstuvwxyz'),  'information technology')]]
//li[child::div/h3/a[contains(translate(., 'ABCDEFGHIJKLMNOPQRSTUVWXYZ', 'abcdefghijklmnopqrstuvwxyz'),  'executive')]]
Of course, each site and set of search tools has its own limitations and it's the conflict between these limitations and your usage patterns that will dictate how useful any of this might be. 

Matlab: Encode images in audio spectrum

UPDATE: This sandbox script has evolved into the functions im2spectrogram() and text2spectrogram() in my aptly named Matlab Image Mangling Toolbox

A while back, I got bored and was looking for various ways to shove pictures where they didn't belong.  Among simpler ideas like concatenation, arbitrary character encoding schemes, and spreadsheet conversion, I tried my hand at conversion to audio.  Using this particular STFT/ISTFT set of tools, as well as basic parts of the image processing toolbox, I threw together this kludge:
%% simplified automatic spectrogram obfuscation

clc; clear all;
format compact;

% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

projdir='/home/assbutt/projects/imagepooper/';
inpict=imread([projdir 'test.jpg'], 'jpeg');
outwavname=[projdir 'soundpicture.wav']; 

% typical image adjustments
invert=0;           % invert if 1
flip=0;             % flip horizontal if 1
bluramt=1;          % gaussian blur amount (approx 0.5-10) (zero for no blur)
blurrad=3;          % gaussian blur radius (approx 2-5)

alteraspect=0.80;   % correct for viewer distortion
padbar=0.08;        % relative height of top padding (H=1+padwidth)
volume=1;           % adjust signal volume (will clip beyond unity)

% add blur to reduce bright edge artifacts
% use nonzero padbar to keep image below mp3 cutoff (0 for none)

% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

% desaturate color images (choose method if desired)
if (ndims(inpict) == 3); inpict=mrgb2gray(inpict,'default'); end

% invert where requested
if (invert == 1); inpict=255-inpict; end

% flip where requested
if (flip == 1); inpict=fliplr(inpict); end

inpict=flipud(inpict);      % flip image (low-f on bottom)
inpict=imadjust(inpict);    % set image contrast

magicnum=660;       
inaspect=length(inpict(1,:))/length(inpict(:,1));
inpict=padarray(inpict,[round(padbar*length(inpict(:,1))) 0],'post'); 
inpict=imresize(inpict,magicnum*[1 alteraspect*inaspect/(1+padbar)]);

if (bluramt > 0);
    h=fspecial('gaussian', blurrad*[1 1], bluramt);
    inpict=imfilter(inpict,h);
end

nft=length(inpict(:,1))*2-2;
h=nft; 
samplefreq=44100;
[x,t]=istft(inpict,h,nft,samplefreq);
[stft, f, t_stft]=stft(x, nft, h, nft, samplefreq);

figure(1)
subplot(1,2,1); plot(t, x);
subplot(1,2,2); imshow(flipdim(real(stft),1));
cmap=colormap('gray');
colormap(flipud(cmap))

xp=x/(max(abs(x))*1.0001)*volume;
wavwrite(xp, samplefreq, 32, outwavname)
Of course, one kind of has to guess at the transform size a person might use when configuring the script parameters, otherwise the arbitrariness of frequency-time scaling makes it basically impossible to enforce any first-view aspect ratio. Most photographs sound pretty terrible, though feeding it high-contrast images with little white content produce nicer audio sweeps.

We take this image
And the script poops out an audio file with a spectrogram like this (using foobar2000)
View your output with foobar2000, audacity, or baudline.  The behavior could probably be improved, but this script is just a novelty.  Nobody cares. I don't care anymore either.

At the time I made this, I also pooped out a version that encodes text strings as a marquee in the top end of the frequency spectrum.  The output is a sound file containing the text.  Simply mix one or more of these files with some music to obtain a song full of hidden inaudible text. I probably should've just made the core of these scripts modular, but I wasn't sure what parts would be common.
%% create text marquee for spectrogram

clc; clear all;
format compact;

% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

instring='put a whole shitload of text here';

projdir='/home/assbutt/projects/imagepooper/';
outwavname=[projdir 'soundpicture.wav']; 

% typical image adjustments
alteraspect=0.80;   % correct for viewer distortion
textheight=0.03;    % relative height of text
textlocation=19000; % frequency center of text
volume=0.1;         % adjust signal volume (will clip beyond unity)

bluramt=5;          % gaussian blur amount (approx 0.5-10) (zero for no blur)
blurrad=3;          % gaussian blur radius (approx 2-5)

% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

magicnum=660;       
samplefreq=44100;

inpict=uint8(text2im(instring));
inpict=255*(1-inpict);

toplim=samplefreq*(1-textheight/2)/2;
botlim=samplefreq/2-toplim;
if (textlocation > toplim); 
    textlocation=toplim; disp('supramaximal text center');end
if (textlocation < botlim); 
    textlocation=botlim; disp('subminimal text center');end

inaspect=length(inpict(1,:))/length(inpict(:,1));
inpict=imresize(inpict,magicnum*textheight*[1 inaspect]);
botpad=floor(magicnum*((2*textlocation/samplefreq) - textheight/2));
toppad=ceil(magicnum*(1-textheight)-botpad);

inpict=padarray(inpict,[0 10],'both'); % pad ends
inpict=padarray(inpict,[toppad 0],'pre'); % top pad
inpict=padarray(inpict,[botpad 0],'post'); % bottom pad
inaspect=length(inpict(1,:))/length(inpict(:,1)); % recalculate
inpict=imresize(inpict,magicnum*[1 alteraspect*inaspect]);
inpict=flipud(inpict);      % flip image (low-f on bottom)

if (bluramt > 0);
    h=fspecial('gaussian', blurrad*[1 1], bluramt);
    inpict=imfilter(inpict,h);
end

nft=length(inpict(:,1))*2-2;
h=nft; 
[x,t]=istft(inpict,h,nft,samplefreq);
[stft, f, t_stft]=stft(x, nft, h, nft, samplefreq);

figure(1)
subplot(1,2,1); plot(t, x);
subplot(1,2,2); imshow(flipdim(real(stft),1));
cmap=colormap('gray');
colormap(flipud(cmap))

xp=x/(max(abs(x))*1.0001)*volume;
wavwrite(xp, samplefreq, 32, outwavname)

Multiple rows of text (one is flipped) mixed into a song
Of course, I only noticed after the fact that I had reinvented the wheel.

Wednesday, November 19, 2014

Matlab: Compile all open figures as a single pdf

As part of my network status log processing script, I needed a way to export weekly overview plots in a format that could be used to convey problems to other people at a glance.  The larger body of the script is a block-mode kludge which does the actual log file processing and plotting in whatever manner I choose.  The final block is a brief bit which rolls the current figure windows into a single pdf.
%% print plots to pdfs; use pdfshuffler to cat or fix rotations

filebasename='/home/ikilledsuperman/plot_%d.pdf'
outputname='/home/ikilledsuperman/outputlogfile.pdf'

m=length(findall(0,'type','figure'));
filelist=cell(m,1);
for n=1:1:m
    figure(n);
    set(n,'PaperUnits','normalized');
    set(n,'PaperPosition', [0 0 1 1]);  %fit to page
    filelist(n)=cellstr(sprintf(filebasename,n));
    print(gcf, '-dpdf', sprintf(filebasename,n));
end

delete(outputname)
append_pdfs(outputname, filelist{:});
delete(filelist{:})
As the comment says, pdfshuffler can be used to put the finishing touches on any generated pdfs.  Close any unneeded figure windows with 'close all'.  This script makes use of append_pdfs.  

Friday, November 7, 2014

Reduce risk of mains flashover on a marginal PCB assembly

Thunderstorms are probably of little concern to most people, but lightning has an absurdly strong tendency to destroy my equipment.  Despite robust grounding and protection measures, hardly a year has gone by without loss of televisions, phones, modems, motors, motherboards, or HVAC controls.  It's for this reason and the occasional phase loss on the three phase service that I was faced with a charred phase protection relay.
Kailn TG30s
The particular device was another chinese Ebay special: the Kailn TG30s.  The relay is a compact rail-mountable package and had performed suitably under test.  The internals were quite similar to a quick and dirty design I had sketched up before realizing that the autumnal comfort of my sustained apathy in purposelessness was more valuable than the $8 needed to buy the part from china.  Less than a week after installation, a storm rolled through and blew it to smithereens along with an unrelated compressor motor.

The relay is constructed from two boards soldered to each other at right angles with metal support straps on either side.  The mains sensing/power networks are combinations of resistive and reactive dividers in series with protection thermistors.  The capacitors and thermistors are through-hole devices placed in a very compact arrangement, though creepage distances do meet the IEC61010-1 minimum spec for reinforced insulation. 

Inside the case, there is nothing but black soot and the smell of burned epoxy.  After a bit of degreaser and soap, the failure sequence became apparent. A few observations led me to my conclusions:

  • Extensive charring on the top side near the mains terminals and thermistors
  • Fused traces leading to divider networks, but no caps were punctured
  • Deep burning and metallizing of case adjacent to PCB near thermistor leads
  • The device tripped a 30A thermal breaker nearly an entire second after the lightning strike
  • PCB is contaminated with flux, solder balls and stray solder from post-line hand assembly
  • Thermistor and cap leads are trimmed relatively long


Missing traces and charring down to the glass (after cleaning)

Metallization and charring of plastic case (after cleaning)
My guess is that the strike flashed over on the board near the terminal strip or thermistor leads, either between untrimmed leads or possibly along the board surface.  In a confined case, with freshly carbonized and metallized surfaces everywhere, conduction continued long after the strike impulse passed, allowing ample time for deep charring and thermal loading of the main breaker.

I should clarify that the device wasn't entirely to blame for the failure.  While inexpensive, it did get hit with a strike impulse that was also able to damage other equipment.  This venture is more about using my knowledge to add value to the inexpensive so that I can keep motors protected while not going broke (as fast).  It's a simplistic exercise in general techniques for enforcing isolation when voltages are high or when humidity or environmental contamination becomes a risk.  

  • Trim and ball component leads
  • Clean the board of residues and solder fines
  • Apply conformal coating

When the new device arrived, I immediately popped it open and looked it over.  The build finish was similar: long untrimmed leads, no-clean flux residues and solder fines.  I clipped the component leads short and added sufficient solder to ball the joints.  After thoroughly cleaning the assembly, I brushed on a couple applications of conformal coating in the board areas associated with mains-level voltages.  Attention should also be paid to keeping the coating from encroaching closer than a few mm from the board edge, as the PCB fits into a retainer groove in its case.  I wanted to make sure that the gap between the PCB edges was sealed, so I allowed the coating to flow through from the top before coating the bottom.  In this manner, air entrapment was avoided.

Coated top side (note balled terminal strips)
New board (top) after balling and coating.  Old board (bottom) showing untrimmed leads and missing traces
The coating material I used is not a product marketed for the purpose.  I used a solution of clear Dap Sidewinder sealant diluted with xylene.  Sidewinder is (as far as I know) a modified silicone.  The cured material has some excellent properties -- and no, it's not corrosive to the assembly as an acetoxy cure RTV silicone would be. With a bit of patience and stirring, the resin can be diluted to consistencies ranging from honey to warm maple syrup.  A brushed coating is relatively self-leveling and will dry to the touch in a few hours, though a day or so should be allowed for full curing.