Sunday, February 22, 2015

Streamline a hopeless task

I mentioned previously about how to use YARIP to block search results on job boards.  Given the utter futility of trying to use the search tools on these sites to sort the unending stream of useless garbage results, I have gone on a bit of a crusade to reduce the amount of time it takes to sweep the boards I frequent.  Here I will include the YARIP blacklist templates I've compiled for these sites, but the keyword blacklisting technique for enforcing search exclusion is a bit of an inelegance.  Since this keyword list would ideally be used for all sites, it makes more sense to do this sort of multiple-site element blacklisting with a userscript rather than YARIP.  Since I suck at writing Javascript, I just wrote a bash script to generate the XML files for YARIP. 

For jobs.ieee.org:
//div[@id='ad_module_120x90']
//div[@id='ad_module_300x250']
//div[child::div/div/div/h3/a[contains(translate(., 'ABCDEFGHIJKLMNOPQRSTUVWXYZ', 'abcdefghijklmnopqrstuvwxyz'),  'keyword')]]
For LinkedIn:
//div[@id='header']
//div[@id='responsive-nav-scrollable']
//div[@id='top-header']
//li[child::div/h3/a[contains(translate(., 'ABCDEFGHIJKLMNOPQRSTUVWXYZ', 'abcdefghijklmnopqrstuvwxyz'),  'keyword')]]
For Indeed.com:
//div[@id='bjobalerts']
//div[@id='femp_list']/div[2][@class='femp_item']
//div[@id='serpRecommendations']
//div[@id='tjobalerts']
//div[child::h2/a[contains(translate(., 'ABCDEFGHIJKLMNOPQRSTUVWXYZ', 'abcdefghijklmnopqrstuvwxyz'),  'keyword')]]
For Ziprecruiter.com:
//div[@id='email_alert_form_wrapper']
//li[child::a/h4/span[contains(translate(., 'ABCDEFGHIJKLMNOPQRSTUVWXYZ', 'abcdefghijklmnopqrstuvwxyz'),  'keyword')]]
For Beyond.com:
//body[@id='body']/div[4][@class='container']/div[@class='row']/div[@class='col-md-12 ']/div[@class='panel panel-default']/div[@class='panel-body no-padding']/div[@class='row']/div[2][@class='col-sm-8 col-md-6']/ul[@class='list-group list-group-lined margin-bottom-sm']/li[28][@class='list-group-item list-group-item-registration-panel']
//body[@id='body']/div[4][@class='container']/div[@class='row']/div[@class='col-md-12 ']/div[@class='panel panel-default']/div[@class='panel-body no-padding']/div[@class='row']/div[3][@class='col-sm-4 col-md-3']
//body[@id='body']/div[4][@class='container']/div[@class='row']/div[@class='col-md-12 ']/div[@class='panel panel-default']/div[@class='panel-body no-padding']/div[@class='row']/div[3][@class='col-sm-4 col-md-3']/div[3][@class='row ng-scope']/div[@class='col-xs-12']/ul[@class='list-group list-group-lined no-margin-bottom-sm']/li[2][@class='list-group-item']
//body[@id='body']/header/nav[1][@class='navbar navbar-default navbar-fixed-top']
//div[@class='job-companylogo hidden-xs']
//div[@class='job-footer']
//div[@id='Display_Header_Top_Text_Position1']
//div[@id='TopNav']/div[@class='navbar-left navbar-center ng-scope']
//img[@class='Areas/Jobs/Search-Index/FeaturedJobStar.gif job-featured-icon']
//li[@class='list-group-item google-ad-zone-bg']
//li[child::div/a/h4[contains(translate(., 'ABCDEFGHIJKLMNOPQRSTUVWXYZ', 'abcdefghijklmnopqrstuvwxyz'),  'keyword')]]
Beyond.com search results with cleanup and keyword exclusion blacklists

Indeed.com search results with cleanup and keyword exclusion blacklists
As the images hopefully convey, a bit of work with YARIP blacklists makes it easy to see at a glance if there are any interesting results on a given page.  Removing the clutter and known irrelevant chaff speed up the process and make the experience much less frustrating ... though it does nothing to make filling out broken applications any less of a nightmare.  Of course, it takes a while to build a suitable blacklist of keywords based on what you are and are not looking for.

The hazard that comes with forcing search relevance is that you may find that very few jobs are posted that will fit even an unreasonably broad set of criteria.  With my short list of keywords to essentially enforce "entry level electrical engineer", I eliminated roughly 60% to 80% of all search results.  If something similar happens to you, do not be alarmed, but know that the people who speak of booming demand for tech jobs and a robust economic recovery are not merely mistaken, but lying

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. 

Monday, October 20, 2014

How to destroy a fake FOTEK SSR

In the process of developing a kiln controller on the cheap, I had opted to purchase a cheap Chinese solid state relay from ebay. I've used cheap relays for other projects, and they had worked well. I purchased a grey FOTEK branded unit, as it had nice robust barrier terminals, unlike many of the other cheap options.

Bewaaaaare
After finding out that the absolute minimum input voltage was closer to 5.0-5.3 volts than the stated 3 volts, the doubts began to surface -- but what could go wrong?  The use case was marginal, but not unreasonable.  The system operates at 208V; the relay is rated for 380V.  The operating current is less than 48A, with a cold current less than 53A.  The relay is rated for 60A.  That's less than a conservative 75% derating, but why stick to arbitrary derating factors when an upper boundary on the cold current is known?

All started well in the first cycle test.  The unit ramped up to a test setpoint and we observed the overshoot.  Either the time constant in the feedback path was three times what I'd estimated, or the relay thyristors were still partially conducting... POP.  What was that? Soon the PV fell below the setpoint and the relay driver came on once more... POP.

A bit embarrassed and reluctant to spend a (relatively) lot of money for a Crydom or Gavazzi, I headed back to the internet for options.  Somewhere along the way, a chisel and bandsaw attacked the failed SSR and a few interesting details dripped onto the pavement around its body.

Fused leads and torn trace; melted solder blown through vias

Exploded via and opto, stray solder flash and char
The PCB traces carrying the main current path are 1mil thick, 150 mil wide.  To some degree, the solder from hand-assembly does serve to increase sectional area, but I can't imagine anything more than 25A wouldn't start melting things. The side of the relay case had been blistered from the heat, and liquid solder had been forced between the PCB and the potting, spraying out through cracks and likely shorting the output at least momentarily.

Part of one of the triacs
The output stage is composed of discrete thyristor packages screwed to the backplate.  I could tell this much from the screws visible externally.  I haven't gutted many SSR's, but I imagine a more reliable approach for high-current units would be direct-bonded chips.  Still, my first guess when seeing two screws was to think it was two antiparallel SCR's.  Nope.  It's two CTA24-800 clones (triacs) in parallel without any means of enforcing current sharing (other than a common heat sink).  I should point out that even in the ideal scenario, that only amounts to 25Ax2=50A worth of current capacity, not 60A.  Curiously, the FOTEK product pdf for SSR50DA has transient current capacity curves strikingly similar to twice that of a mounted CTA24-800.  I'm curious to know if they also use paralleled discrete output triacs or if that's just a consequence of a coincidentally similar thermal impedance.

The remnant internals of the triacs can be inspected and tested to clearly indicate that they are the insulated-tab variant.  Considering a junction-case thermal resistance of 1.7 K/W (from STmicro BTA24) and an interface thermal resistance of about 0.20-0.25 K/W for the TO220 insulated tab packages, the overall junction-case thermal resistance for the SSR could be as much as 0.975 K/W -- let's just say 1 K/W.  This is significantly higher than the thermal resistances listed for other SSR's in the 50A class -- by as much as a factor of two.  With an input of 1.2 W/A at 40°C, one needs a 0.3 K/W heat sink to keep the junction temperature safely below 125°C at the limiting current of 50A.  When it's the thermal resistances internal to the assembly that are so significant, it may be difficult to notice an excessive operational condition; the heat sink temps would remain relatively low. Overheating would indeed contribute to the likelihood of a stuck relay.

My casual guess at what happened was that one of the triacs remained on after the input went low, a condition made more likely if one had been hogging current.  This resulted in the failure of the stuck triac.  When the input signal reappeared, the remaining device destroyed itself, blowing out the optocoupler in the process.

Note position of R5 and suggested alternate location
Interpreting the schematic from the board is trivial, though a few curiosities appear.  The series input circuit ensures that the device will not trigger at 3v input.  At the rated 5mA threshold current for the MOC3063, the input voltage would indeed need to be higher than 5v.  The FOTEK device pdf shows a parallel input structure and specifies a minimum ON transition voltage of 2.4v.

I found the location of R5 to be curious.  Its manner of connection to the snubber network seems a bit odd.  The resistor actually looks as if it were improperly installed through a via in this node, as the pad spacing is too small for the device to properly fit.  There is a stub trace with an unpopulated PTH nearby which connects to the AC2 node.  The spacing is more appropriate in this location, so this may be an alternate or a defect.  It may also be that the PCB is used for multiple layouts.

It's also worth noting that the trace spacing reduces the input-output isolation distance to roughly 20 mil.  I haven't checked, but even under thin coating of epoxy, I doubt that meets the 2.5kV isolation spec.

So what are the actual capabilities of this thing?  If one is able to trust that the components (triacs, optocoupler) meet their individual specifications, I would still feel reluctant to trust this relay above about 20A at 240V.  I don't trust the configuration to share current reliably between triacs, so I'd derate it to the capacity of a single component.  Even still, one needs to consider the added thermal resistance caused by the packaging as mentioned before.  The signal voltage range would be limited to an inconvenient 5.5v to 12v, as restricted by the series input structure.  The extra indicator LED increases the minimum voltage to reach a reliable trigger current, and it also restricts the maximum allowable current.  While the optocoupler can accept up to 60mA forward current, the indicator won't likely be reliable at 300% of its absolute maximum current.  For people wanting to drive it directly from a microcontroller IO pin, this would probably cause problems as it did for me.  At 5v, the relay may trigger unreliably because the opto would be operating near or below its specified trigger current.  Operating at voltages slightly above 12v would probably be okay, but 32v is asking for trouble in my opinion.

In the end, the device design is a functioning SSR, but it is not capable of performing to the specified capacity.  I'm curious to know how the 100A or 600V units are constructed.  As I mentioned, I've used cheap chinese SSR's before; perhaps for a 25A relay, all this gimmickry doesn't impact the performance as much.  Without knowing the details of construction or being able to trust the specifications, there is no reliable method to use these devices within their actual range of functionality.  There are other stories online of fake FOTEK SSR's sticking on or melting.  Hopefully I can contribute a little bit of information to explain the failure beyond "it was cheap". 

Kill internet trolls with fire

Well maybe it's not actual fire, but it certainly gives me a warm feeling inside.

Do you frequent any sites where the user comment section is overrun with trolls, plants, and paid shills? Are you sick of their comments reminding you that they remain capable of breathing? Use YARIP to eliminate all their comments from view. Just use Firefox's element inspector (use the right-click menu) to take a peek at the local structure and put together an appropriate XPATH to use in YARIP.

For example, delete entire posts based on a partial name match on reason.com:
//li[child::p/strong[contains(., 'Viagra')]]
Or delete just the post content based on a full name match on zerohedge.com:
//div[child::div/b/a[@href="/users/bangalore-equity-trader"]]/div[@class='comment-content']
Adapt to suit your browsing habits.