diff --git a/LArCalorimeter/LArRecConditions/LArRecConditions/BadChanContainer.h b/LArCalorimeter/LArRecConditions/LArRecConditions/BadChanContainer.h
new file mode 100644
index 0000000000000000000000000000000000000000..04b5dda62ab3608b1576adf8bc92e2c966426972
--- /dev/null
+++ b/LArCalorimeter/LArRecConditions/LArRecConditions/BadChanContainer.h
@@ -0,0 +1,65 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+#ifndef BadChanContainer_H
+#define BadChanContainer_H
+
+#include <vector>
+#include <algorithm>
+
+
+template <class Chan, class State>
+class BadChanContainer {
+public:
+
+  typedef std::pair<Chan,State>                BadChanEntry;
+  typedef std::vector<BadChanEntry>            BadChanVec;
+  typedef typename BadChanVec::const_iterator  const_iterator;
+  typedef typename BadChanVec::size_type       size_type;
+
+  struct ChannelLess {
+    bool operator()(const BadChanEntry& a, const BadChanEntry& b) {
+      return a.first < b.first;
+    }
+  };
+
+public:
+
+  BadChanContainer() {}
+
+	
+  BadChanContainer( const BadChanVec& vec) : m_cont(vec) {
+	std::sort(m_cont.begin(), m_cont.end(), ChannelLess());
+  }
+
+  State status( Chan channel) const {
+
+    const_iterator i = 
+      std::lower_bound( m_cont.begin(), m_cont.end(), BadChanEntry( channel,(LArBadChannel) 0),
+		   ChannelLess());
+    if (i != m_cont.end() && i->first == channel) return i->second;
+    else 
+	return State(0);
+  }
+
+  const_iterator begin() const {return m_cont.begin();}
+  const_iterator end() const {return m_cont.end();}
+  size_type      size() const {return m_cont.size();}
+
+  /// Deletes the contents and sets size to 0 (same as stl::vector<T>::clear())
+  void clear() {m_cont.clear();}
+
+  void set( const BadChanVec& cont) {
+    m_cont = cont;
+    std::sort(m_cont.begin(), m_cont.end(), ChannelLess());
+  }
+
+private:
+
+  BadChanVec m_cont;
+
+};
+
+
+#endif
diff --git a/LArCalorimeter/LArRecConditions/LArRecConditions/BadChanService.h b/LArCalorimeter/LArRecConditions/LArRecConditions/BadChanService.h
new file mode 100644
index 0000000000000000000000000000000000000000..4b75e980440e4325b6d91b1fcba075e93ed057b0
--- /dev/null
+++ b/LArCalorimeter/LArRecConditions/LArRecConditions/BadChanService.h
@@ -0,0 +1,25 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+#ifndef BadChanService_H
+#define BadChanService_H
+
+#include "LArRecConditions/LArBadChannel.h"
+#include "LArRecConditions/BadChanContainer.h"
+
+class BadChanService {
+public:
+
+	typedef unsigned int                                    ChannelType;
+	typedef BadChanContainer< ChannelType, LArBadChannel>   BadChanInfo;
+
+  static BadChanInfo& info() {
+    static BadChanInfo* m_info = 0;
+    if (m_info == 0) m_info = new BadChanInfo;
+    return *m_info;
+  }
+
+};
+
+#endif
diff --git a/LArCalorimeter/LArRecConditions/LArRecConditions/ILArBadChanTool.h b/LArCalorimeter/LArRecConditions/LArRecConditions/ILArBadChanTool.h
new file mode 100644
index 0000000000000000000000000000000000000000..9967c9a551ececb30b5e5225ae7c1787aa1859de
--- /dev/null
+++ b/LArCalorimeter/LArRecConditions/LArRecConditions/ILArBadChanTool.h
@@ -0,0 +1,56 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+#ifndef ILArBadChanTool_H
+#define ILArBadChanTool_H
+
+#include "Identifier/HWIdentifier.h"
+#include "LArRecConditions/LArBadChannel.h"
+#include "LArRecConditions/LArBadFeb.h"
+#include "GaudiKernel/IAlgTool.h"
+#include "AthenaKernel/IOVSvcDefs.h"
+
+
+class ILArBadChanTool : public virtual IAlgTool {
+public:
+  virtual ~ILArBadChanTool() {}
+
+  static const InterfaceID& interfaceID() { 
+    static const InterfaceID IID_ILArBadChanTool("ILArBadChanTool", 1 , 0);
+    return IID_ILArBadChanTool; 
+  }
+
+  /// status access via LAr hardware identifier
+  virtual LArBadChannel status( HWIdentifier id) const = 0;
+
+  /// status access via LAr FEB id, and channel number within that FEB (0 to 127)
+  virtual LArBadChannel status(const HWIdentifier& febId, int chanNumber) const = 0;
+
+  /// status access via offline identifier
+  virtual LArBadChannel offlineStatus( Identifier id) const = 0;
+
+  /// returns true if the FEB (identified by it's HWIdentifier) is missing 
+  virtual bool febMissing(  HWIdentifier febId) const = 0;
+
+  /// returns true if the FEB (identified by it's HWIdentifier) does not have 
+  /// any bad channels 
+  virtual bool febAllGood(  HWIdentifier febId) const = 0;
+
+  /// returns the complete FEB status for a FEB HWIdentifier
+  virtual LArBadFeb febStatus( HWIdentifier febId) const = 0;
+
+  /// returns the HWIdentifiers of all the problematic FEBs, no matter what the FEB problem is
+  virtual std::vector<HWIdentifier> missingFEBs() const = 0;
+
+  /// returns all the information about problematic FEBs in one container
+  virtual const std::vector< std::pair<HWIdentifier,LArBadFeb> >& fullBadFebsState() const = 0;
+
+  // Callback functions
+  virtual StatusCode updateFromDB(IOVSVC_CALLBACK_ARGS) = 0;
+  virtual StatusCode updateBadFebsFromDB(IOVSVC_CALLBACK_ARGS) = 0;
+
+};
+
+
+#endif
diff --git a/LArCalorimeter/LArRecConditions/LArRecConditions/ILArBadChannelMasker.h b/LArCalorimeter/LArRecConditions/LArRecConditions/ILArBadChannelMasker.h
new file mode 100644
index 0000000000000000000000000000000000000000..cf6997e459201dacd26545dcf6828ca5e74ad51a
--- /dev/null
+++ b/LArCalorimeter/LArRecConditions/LArRecConditions/ILArBadChannelMasker.h
@@ -0,0 +1,34 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+#ifndef ILArBadChannelMasker_H
+#define ILArBadChannelMasker_H
+
+#include "GaudiKernel/IAlgTool.h"
+#include "CaloIdentifier/CaloGain.h"
+
+class Identifier;
+class HWIdentifier;
+class LArBadChannel;
+
+class ILArBadChannelMasker : public virtual IAlgTool
+{
+public:
+   static const InterfaceID& interfaceID()
+   { 
+      static const InterfaceID IID_ILArBadChannelMasker("ILArBadChannelMasker", 1, 0);
+      return IID_ILArBadChannelMasker; 
+   }
+
+   virtual ~ILArBadChannelMasker()
+   {}
+
+   virtual bool cellShouldBeMasked(const HWIdentifier& hardwareId, const int gain=CaloGain::UNKNOWNGAIN) const = 0;
+   virtual bool cellShouldBeMasked(const Identifier& offlineId, const int gain=CaloGain::UNKNOWNGAIN) const = 0; 
+   virtual bool cellShouldBeMaskedFEB(const HWIdentifier& febId, const int channelNumber, const int gain=CaloGain::UNKNOWNGAIN) const = 0;
+
+   virtual bool isMaskingOn() const = 0;
+};
+
+#endif
diff --git a/LArCalorimeter/LArRecConditions/LArRecConditions/LArBadChanBitPacking.h b/LArCalorimeter/LArRecConditions/LArRecConditions/LArBadChanBitPacking.h
new file mode 100644
index 0000000000000000000000000000000000000000..4e407d02165a9de26988109c731d2ad3ab1cb98d
--- /dev/null
+++ b/LArCalorimeter/LArRecConditions/LArRecConditions/LArBadChanBitPacking.h
@@ -0,0 +1,68 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+#ifndef LArBadChanBitPacking_H
+#define LArBadChanBitPacking_H
+
+#include "LArRecConditions/LArBadChannelEnum.h"
+#include <string>
+#include <vector>
+#include <map>
+
+class LArBadChannel;
+
+class LArBadChanBitPacking : public LArBadChannelEnum {
+ public:
+
+  typedef std::vector<PosType>        PosContainer;
+
+  LArBadChanBitPacking();	
+
+  const std::string& stringName( ProblemType pb) const;
+
+  std::pair<bool, ProblemType> enumName( const std::string& str) const;
+
+  PosType bitPosition( ProblemType pb) const {return m_bitPos[static_cast<PosType>(pb)];}
+
+  PosType wordSize() const {return sizeof(BitWord);}
+
+  void setBit( ProblemType pb, BitWord& word, bool value=true) const;
+  void setBit( ProblemType pb, LArBadChannel& word, bool value=true) const;
+
+  bool setBit( const std::string& name, BitWord& word, bool value=true) const;
+  bool setBit( const std::string& name, LArBadChannel& word, bool value=true) const;
+
+  std::string stringStatus( const LArBadChannel& bc) const;
+
+  // These BitWord masks are used to do gain-dependent masking in LArBadChannelMasker.
+  BitWord highGainMask() const   {return m_highGainMask;}
+  BitWord mediumGainMask() const {return m_mediumGainMask;}
+  BitWord lowGainMask() const    {return m_lowGainMask;}
+
+  int numberOfProblemTypes() const { return m_nameVec.size();}
+
+ private:
+
+  // This is used to describe the dependence of each ProblemType on LAr gain.
+  enum GainDependence { independent, low, medium, high};
+
+  PosContainer               m_bitPos;
+  std::vector<int>           m_index;
+  std::vector< std::pair<ProblemType, GainDependence> >   m_enumVec;  
+
+  std::vector<std::string>   m_nameVec;
+  std::map<std::string, ProblemType>  m_nameMap;
+
+  // These are non-static so that different LArBadChanBitPacking versions can be used simultaneously.
+  BitWord m_highGainMask;
+  BitWord m_mediumGainMask;
+  BitWord m_lowGainMask;
+
+  void addBit( ProblemType pb, const std::string& name, GainDependence gaindep);
+  int index( ProblemType pb) const {return m_index[pb];}
+  void initMasks();
+};
+
+#endif
+
diff --git a/LArCalorimeter/LArRecConditions/LArRecConditions/LArBadChannel.h b/LArCalorimeter/LArRecConditions/LArRecConditions/LArBadChannel.h
new file mode 100644
index 0000000000000000000000000000000000000000..e3fc679bf40a9fba6546213ac8da8ec2382cf161
--- /dev/null
+++ b/LArCalorimeter/LArRecConditions/LArRecConditions/LArBadChannel.h
@@ -0,0 +1,84 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+#ifndef LArBadChannel_H
+#define LArBadChannel_H
+
+#include "LArRecConditions/LArBadChannelEnum.h"
+#include "LArRecConditions/LArBadChanBitPacking.h"
+
+class  LArBadChannel : public LArBadChannelEnum {
+ public:
+
+ LArBadChannel() : m_word(0) {}
+
+  explicit LArBadChannel( BitWord rawStatus) : m_word(rawStatus) {}
+	
+  /// Returns true if corresponding status bit its set		
+  bool statusBad( ProblemType pb) const {
+    BitWord mask = 1 << bitPosition(pb);
+    return ((m_word & mask) != 0);
+  }
+
+  /// Returns true if there is no problem in corresponding status bit
+  bool statusOK( ProblemType pb) const {return !statusBad(pb);}
+	
+  /// Returns true if no problems at all (all bits at zero)
+  bool good() const {return m_word == 0;}
+	
+  bool deadReadout() const { return statusBad( deadReadoutBit);}
+  bool deadCalib() const { return statusBad( deadCalibBit);} 
+  bool deadPhys() const { return statusBad( deadPhysBit);} 
+  bool almostDead() const { return statusBad( almostDeadBit);} 
+  bool shortProblem() const { return statusBad( shortBit);} 
+  bool unstable() const { return statusBad( unstableBit);}
+  bool distorted() const { return statusBad( distortedBit);}
+  bool lowNoiseHG() const { return statusBad( lowNoiseHGBit);}
+  bool highNoiseHG() const { return statusBad( highNoiseHGBit);}
+  bool unstableNoiseHG() const { return statusBad( unstableNoiseHGBit);}
+  bool lowNoiseMG() const { return statusBad( lowNoiseMGBit);}
+  bool highNoiseMG() const { return statusBad( highNoiseMGBit);}
+  bool unstableNoiseMG() const { return statusBad( unstableNoiseMGBit);}
+  bool lowNoiseLG() const { return statusBad( lowNoiseLGBit);}
+  bool highNoiseLG() const { return statusBad( highNoiseLGBit);}
+  bool unstableNoiseLG() const { return statusBad( unstableNoiseLGBit);}
+  bool missingFEB() const { return statusBad( missingFEBBit);}
+  bool peculiarCalibrationLine() const { return statusBad( peculiarCalibrationLineBit);}
+  bool problematicForUnknownReason() const { return statusBad( problematicForUnknownReasonBit);}
+  bool sporadicBurstNoise() const {return statusBad( sporadicBurstNoiseBit);}
+  bool deadSCACell() const {return statusBad( deadSCACellBit);}
+  bool badFirstSample() const {return statusBad( badFirstSampleBit);}
+	
+  bool reallyNoisy() const {return (highNoiseHG() || highNoiseMG() || highNoiseLG() ||
+				    unstableNoiseHG() || unstableNoiseMG() || unstableNoiseLG());}
+  bool noisy() const {return (reallyNoisy() || lowNoiseHG() || lowNoiseMG() || lowNoiseLG());}
+				
+  static PosType bitPosition( ProblemType pb)
+  {
+    // if no bit packing object set, use enumerators as bit positions
+    return s_packing == 0 ? static_cast<PosType>(pb) : s_packing->bitPosition(pb);
+  }
+
+  bool operator!=(BitWord other) {return m_word != other;}
+  bool operator!=(LArBadChannel other) {return m_word != other.packedData();}
+  bool operator==(BitWord other) {return m_word == other;}
+  bool operator==(LArBadChannel other) {return m_word == other.packedData();}
+
+  BitWord packedData() const {return m_word;}
+
+ private:
+
+	
+
+  BitWord m_word;
+  static LArBadChanBitPacking* s_packing;
+  // FIXME declare a friend to set the m_packing
+
+  BitWord& packedDataRef() {return m_word;}
+	
+  friend class LArBadChanBitPacking;
+};
+
+
+#endif
diff --git a/LArCalorimeter/LArRecConditions/LArRecConditions/LArBadChannelEnum.h b/LArCalorimeter/LArRecConditions/LArRecConditions/LArBadChannelEnum.h
new file mode 100644
index 0000000000000000000000000000000000000000..e16fbb164b095a38f92ebd427bd45773c45bba36
--- /dev/null
+++ b/LArCalorimeter/LArRecConditions/LArRecConditions/LArBadChannelEnum.h
@@ -0,0 +1,47 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+#ifndef LArBadChannelEnum_H
+#define LArBadChannelEnum_H
+
+class LArBadChannelEnum {
+ public:
+
+  //typedef unsigned int      BitPackedWord;
+  typedef unsigned int      PosType;
+  typedef unsigned int      BitWord;
+
+  enum ProblemType {
+    deadReadoutBit = 0, 
+    deadCalibBit = 1, 
+    deadPhysBit = 2, 
+    almostDeadBit = 3, 
+    shortBit = 4, 
+    unstableBit = 5,
+    distortedBit = 6,
+    lowNoiseHGBit = 7,
+    highNoiseHGBit = 8,
+    unstableNoiseHGBit = 9,
+    lowNoiseMGBit = 10,
+    highNoiseMGBit = 11,
+    unstableNoiseMGBit = 12,
+    lowNoiseLGBit = 13,
+    highNoiseLGBit = 14,
+    unstableNoiseLGBit = 15,
+    missingFEBBit = 16,
+    peculiarCalibrationLineBit = 17,
+    problematicForUnknownReasonBit = 18,
+    sporadicBurstNoiseBit = 19,
+    deadSCACellBit = 20,
+    badFirstSampleBit = 21
+  };
+
+  ///  const static BitWord HighGainMask;
+  ///  const static BitWord MediumGainMask;
+  ///  const static BitWord LowGainMask;
+
+};
+
+#endif
+
diff --git a/LArCalorimeter/LArRecConditions/LArRecConditions/LArBadChannelParser.h b/LArCalorimeter/LArRecConditions/LArRecConditions/LArBadChannelParser.h
new file mode 100644
index 0000000000000000000000000000000000000000..8876b837203bf6b9c515e00f51b9dc7a4a30f15f
--- /dev/null
+++ b/LArCalorimeter/LArRecConditions/LArRecConditions/LArBadChannelParser.h
@@ -0,0 +1,181 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+#ifndef LArBadChannelParser_H
+#define LArBadChannelParser_H
+
+#include "GaudiKernel/MsgStream.h"
+#include <fstream>
+
+class LArBadChannelParser
+{
+public:
+
+	/** 
+	@brief A parser object must be initialized with the 
+	filename that it is to parse. It must also be given a 
+	MsgStream pointer for logging messages. */
+	LArBadChannelParser(
+		const std::string& filename, MsgStream* const log, 
+		unsigned int numInts, int numStrings, unsigned int firstWildcard = 0);
+
+	virtual	~LArBadChannelParser();
+
+	/**
+	@brief You can use this function to check 
+	whether file-reading will succeed. If false, 
+	parseFile() will return an empty vector. */
+	bool fileStatusGood() const;
+
+ 	/** 
+	@brief Parse the file using the following format for each line:
+	First, exactly numInts integers are required. Then, if numString is negative,
+	at least std::abs(numString) strings are required, otherwise exactly numString 
+	strings are required. These strings are converted to a vector<T>.
+	A vector of all successfully parsed lines is returned.
+	The integer part of a line may contain wildcards, starting from position
+	firstWildcard (where counting begins from 1); firstWildcard = 0 means 
+	wildcards are not allowed. The wildcard character in the input file 
+	is "*", it is replaced by -1 in the parsed output. Comments in the ASCII 
+	file are demarcated with the '#' character. Lines that fail to parse are 
+	skipped, with diagnostic messages sent to the message stream. */
+
+	template<typename T>
+	std::vector< std::pair<std::vector<int>, std::vector<T> > > parseFile();
+
+private:
+
+	// Can not construct a parser without giving filename or MsgStream.
+	LArBadChannelParser();
+
+	std::vector<int> getIdFields(const std::vector<std::string>& words) const;
+	std::vector<std::string> parseLine(std::string& line) const;
+
+	template<typename T> 
+	bool stringToNumber(T& theNumber, const std::string& theStr) const;
+
+	template<typename T> 
+	bool convertStrings(std::vector<T>& result, const std::vector<std::string>::const_iterator begin, 
+		const std::vector<std::string>::const_iterator end) const;
+
+	std::ifstream m_fin;			//to read the file
+	unsigned int m_linenumber;		//line number currently being parsed
+	const std::string m_filename;
+	MsgStream* const m_log;
+
+	const unsigned int m_numInts;		//the number of integers required to represent the Identifier(s)
+	const int m_numStrings;			//the number of strings required to represent the status
+	const unsigned int m_firstWildcard;	// The first admissible position for a wildcard ('*')
+						// The counting is from 1, i.e. first  = 1
+						// If zero, then wildcards are not allowed
+};
+
+inline bool LArBadChannelParser::fileStatusGood() const
+{
+	return m_fin.good();
+}
+
+template<typename T>
+inline std::vector< std::pair<std::vector<int>, std::vector<T> > > LArBadChannelParser::parseFile()
+{
+  typedef std::pair< std::vector<int>, std::vector<T> > LineData;
+  std::vector<LineData> result;
+
+  if(!fileStatusGood())
+  {
+    (*m_log) << MSG::ERROR << "LArBadChannelParser - Could not open file: " << m_filename << endreq;
+    return result;	//empty result
+  }
+
+  while(true)
+  {
+    std::string line;
+    std::getline(m_fin, line);
+    if(!fileStatusGood())
+      break;	// loop termination at end of file
+    ++m_linenumber;
+    std::vector<std::string> input = parseLine(line);
+
+    if(input.size() < m_numInts + std::abs(m_numStrings)) // if line is too short, skip it
+    {
+      if(input.size() != 0) // complain only for non-empty lines
+        {(*m_log) << MSG::WARNING << "LArBadChannelParser REJECTED line " << m_linenumber \
+          << " -\t not enough parameters given: " << input.size() << endreq;}
+      continue;
+    }
+
+    LineData parsedData;
+
+    parsedData.first = getIdFields(input);
+    if(parsedData.first.size() == 0)
+      continue;	// getIdFields failed, with error message. Skip this line.
+
+    const std::vector<std::string>::const_iterator start = input.begin() + m_numInts;
+    const std::vector<std::string>::const_iterator stop = \
+      (m_numStrings < 0) ? static_cast<const std::vector<std::string>::const_iterator>(input.end()) : (start + m_numStrings);
+
+    if(stop > start)
+    { 
+      if(!convertStrings<T>(parsedData.second, start, stop))
+        continue; //convertStrings failed with error message. Skip this line.
+    }
+
+    if(stop < input.end())
+      (*m_log) << MSG::WARNING << "LArBadChannelParser IGNORED unexpected input on line " << m_linenumber << "." << endreq;
+
+    result.push_back(parsedData);
+    (*m_log) << MSG::VERBOSE << "LArBadChannelParser ACCEPTED line " << m_linenumber << " -\t " << line << endreq;
+  }
+
+  (*m_log) << MSG::DEBUG << "LArBadChannelParser - Parsed " << m_linenumber << " lines in file '" << m_filename << "'." << endreq;
+  return result;
+}
+
+// The convertStrings function reads the elements in the input line after the integer part, 
+// and converts them to type T. The code can be easily extended by adding specialized template functions
+// to convert the elements to any desired type. The default template function below will work for any
+// standard C++ numeric type, and the specialized template function below that works for the trivial case
+// where T is string type.
+
+template<typename T> //works for any standard C++ numeric type 
+inline bool LArBadChannelParser::convertStrings(std::vector<T>& result, 
+  const std::vector<std::string>::const_iterator begin, const std::vector<std::string>::const_iterator end) const
+{
+  result.clear();
+  result.reserve(static_cast<unsigned int>(end - begin));
+  for(std::vector<std::string>::const_iterator iter = begin; iter != end; ++iter)
+  {
+    T element;
+    if(stringToNumber<T>(element, *iter))
+      result.push_back(element);
+    else
+    {
+      (*m_log) << MSG::WARNING << "LArBadChannelParser REJECTED line " << m_linenumber \
+        << " -\t failed to extract status." << endreq;
+      return false;
+    }
+  }
+  return true;
+}
+
+//trivial case: convert string to string
+template<>
+inline bool LArBadChannelParser::convertStrings(std::vector<std::string>& result, 
+  const std::vector<std::string>::const_iterator begin, const std::vector<std::string>::const_iterator end) const
+{
+  result.assign(begin, end);
+  return true;
+}
+
+//works for any built-in numeric C++ type
+template<typename T>
+inline bool LArBadChannelParser::stringToNumber(T& theNumber, const std::string& theString) const
+{
+        std::istringstream iss(theString);
+        return !(iss >> std::dec >> theNumber).fail() && (static_cast<int>(theString.size()) ==  iss.tellg());
+       //the second condition checks for invalid input of the form "123abc"
+}
+
+#endif	//end of #ifndef LArBadChannelParser_H
+
diff --git a/LArCalorimeter/LArRecConditions/LArRecConditions/LArBadFeb.h b/LArCalorimeter/LArRecConditions/LArRecConditions/LArBadFeb.h
new file mode 100644
index 0000000000000000000000000000000000000000..dbfde38806c4aa7a0ee7d919c202dba5bfc6aa00
--- /dev/null
+++ b/LArCalorimeter/LArRecConditions/LArRecConditions/LArBadFeb.h
@@ -0,0 +1,68 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+#ifndef LArBadFeb_H
+#define LArBadFeb_H
+
+#include "LArRecConditions/LArBadFebEnum.h"
+
+class  LArBadFeb : public LArBadFebEnum {
+public:
+
+  LArBadFeb() : m_word(0) {}
+
+  explicit LArBadFeb( BitWord rawStatus) : m_word(rawStatus) {}
+	
+  /// Returns true if corresponding status bit its set		
+  bool statusBad( ProblemType pb) const {
+    BitWord mask = 1 << bitPosition(pb);
+    return ((m_word & mask) != 0);
+  }
+
+  /// Returns true if there is no problem in corresponding status bit
+  bool statusOK( ProblemType pb) const {return !statusBad(pb);}
+	
+  /// Returns true if no problems at all (all bits at zero)
+  bool good() const {return (m_word << 16) == 0;} // only use the lower 16 bits
+
+  /// FEB is completely missing, e.g. powered off
+  bool deadAll() const {return statusBad( deadAllBit);} 
+
+  /// FEB is not sending readout data, but the L1 trigger path is working
+  bool deadReadout() const {return statusBad( deadReadoutBit);}
+
+  /// FEB has readout errors, cannot be used
+  bool inError() const {return statusBad( inErrorBit);}
+
+  /// Deactivated in OKS
+  bool deactivatedInOKS() const {return statusBad( deactivatedInOKSBit);}
+
+  unsigned int ignoreErrors() const;
+
+  static PosType bitPosition( ProblemType pb) { return static_cast<PosType>(pb);}
+
+  bool operator!=(BitWord other) {return m_word != other;}
+  bool operator!=(LArBadFeb other) {return m_word != other.packedData();}
+  bool operator==(BitWord other) {return m_word == other;}
+  bool operator==(LArBadFeb other) {return m_word == other.packedData();}
+
+  BitWord packedData() const {return m_word;}
+
+private:
+
+  BitWord m_word;
+
+  BitWord& packedDataRef() {return m_word;}
+	
+  friend class LArBadFebBitPacking;
+
+};
+
+
+inline unsigned int LArBadFeb::ignoreErrors() const 
+{
+  return (m_word >> 16);  // return the most significant 16 bits 
+}
+
+#endif
diff --git a/LArCalorimeter/LArRecConditions/LArRecConditions/LArBadFebBitPacking.h b/LArCalorimeter/LArRecConditions/LArRecConditions/LArBadFebBitPacking.h
new file mode 100644
index 0000000000000000000000000000000000000000..8937006ee7e322f24325b3e560ac1fd1cfc3b53e
--- /dev/null
+++ b/LArCalorimeter/LArRecConditions/LArRecConditions/LArBadFebBitPacking.h
@@ -0,0 +1,55 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+#ifndef LArBadFebBitPacking_H
+#define LArBadFebBitPacking_H
+
+#include "LArRecConditions/LArBadFebEnum.h"
+#include "LArRecConditions/LArBadFeb.h"
+#include <string>
+#include <vector>
+#include <map>
+
+class LArBadFeb;
+
+class LArBadFebBitPacking : public LArBadFebEnum {
+ public:
+
+  typedef std::vector<PosType>        PosContainer;
+
+  LArBadFebBitPacking();	
+
+  const std::string& stringName( ProblemType pb) const;
+
+  std::pair<bool, ProblemType> enumName( const std::string& str) const;
+
+  PosType bitPosition( ProblemType pb) const {return LArBadFeb::bitPosition(pb);}
+
+  PosType wordSize() const {return sizeof(BitWord);}
+
+  void setBit( ProblemType pb, BitWord& word, bool value=true) const;
+  void setBit( ProblemType pb, LArBadFeb& word, bool value=true) const;
+
+  bool setBit( const std::string& name, BitWord& word, bool value=true) const;
+  bool setBit( const std::string& name, LArBadFeb& word, bool value=true) const;
+
+  std::string stringStatus( const LArBadFeb& bc) const;
+
+  int numberOfProblemTypes() const { return m_nameVec.size();}
+
+ private:
+
+  std::vector<int>                    m_index;
+
+  std::vector< ProblemType>           m_enumVec;  
+  std::vector<std::string>            m_nameVec;
+  std::map<std::string, ProblemType>  m_nameMap;
+
+  void addBit( ProblemType pb, const std::string& name);
+  int index( ProblemType pb) const {return m_index[pb];}
+
+};
+
+#endif
+
diff --git a/LArCalorimeter/LArRecConditions/LArRecConditions/LArBadFebEnum.h b/LArCalorimeter/LArRecConditions/LArRecConditions/LArBadFebEnum.h
new file mode 100644
index 0000000000000000000000000000000000000000..5cf27520ea98441980a87153f360ed7037d38c51
--- /dev/null
+++ b/LArCalorimeter/LArRecConditions/LArRecConditions/LArBadFebEnum.h
@@ -0,0 +1,40 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+#ifndef LArBadFebEnum_H
+#define LArBadFebEnum_H
+
+class LArBadFebEnum {
+ public:
+
+  //typedef unsigned int      BitPackedWord;
+  typedef unsigned int      PosType;
+  typedef unsigned int      BitWord;
+
+  enum ProblemType {
+    deadAllBit = 0, 
+    deadReadoutBit = 1, 
+    inErrorBit = 2, 
+    deactivatedInOKSBit = 3,   //From LArFebErrorSummary.h:
+    maskParity         = 16,   //Parity,		 
+    maskBCID            =17,   //BCID,		 
+    maskSampleHeader   = 18,   //SampleHeader,	 
+    maskEVTID          = 19,   //EVTID,		 
+    maskScacStatus     = 20,   //ScacStatus,	 
+    maskScaOutOfRange  = 21,   //ScaOutOfRange,	 
+    maskGainMismatch   = 22,   //GainMismatch,	 
+    maskTypeMismatch   = 23,   //TypeMismatch,	 
+    maskNumOfSamples   = 24,   //NumOfSamples,	 
+    maskEmptyDataBlock = 25,   //EmptyDataBlock,	 
+    maskDspBlockSize   = 26,   //DspBlockSize,	 
+    maskCheckSum       = 27,   //CheckSum, 	 
+    maskMissingHeader  = 28,    //MissingHeader, 	 
+    maskBadGain        = 29    //BadGain, 	 
+                               //N_LArFebErrorType
+  };			       
+			       
+};
+
+#endif
+
diff --git a/LArCalorimeter/LArRecConditions/LArRecConditions/LArHVPathologiesDb.h b/LArCalorimeter/LArRecConditions/LArRecConditions/LArHVPathologiesDb.h
new file mode 100644
index 0000000000000000000000000000000000000000..748deea71d80f4c3b50f6eb95410b0b14adbe627
--- /dev/null
+++ b/LArCalorimeter/LArRecConditions/LArRecConditions/LArHVPathologiesDb.h
@@ -0,0 +1,27 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+#ifndef LARTOOLS_LARHVPATHOLOGIESDB_H
+#define LARTOOLS_LARHVPATHOLOGIESDB_H
+
+#include <vector>
+
+class LArHVPathologiesDb
+{
+ public:
+
+  struct LArHVElectPathologyDb {
+    unsigned int cellID;
+    unsigned short electInd;
+    unsigned short pathologyType;
+  };
+
+  LArHVPathologiesDb() {}
+  virtual ~LArHVPathologiesDb() {}
+
+  std::vector<LArHVElectPathologyDb> m_v;
+};
+
+
+#endif
diff --git a/LArCalorimeter/LArRecConditions/LArRecConditions/LArRecConditionsDict.h b/LArCalorimeter/LArRecConditions/LArRecConditions/LArRecConditionsDict.h
new file mode 100755
index 0000000000000000000000000000000000000000..eafb3c3bdadce46363e358c08011c2f558c19114
--- /dev/null
+++ b/LArCalorimeter/LArRecConditions/LArRecConditions/LArRecConditionsDict.h
@@ -0,0 +1,10 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+#ifndef LARRECCONDITIONS_LARRECCONDITIONSDICT_H
+#define LARRECCONDITIONS_LARRECCONDITIONSDICT_H
+
+#include "LArRecConditions/LArHVPathologiesDb.h"
+
+#endif // LARRECCONDITIONS_LARRECCONDITIONSDICT_H
diff --git a/LArCalorimeter/LArRecConditions/LArRecConditions/selection.xml b/LArCalorimeter/LArRecConditions/LArRecConditions/selection.xml
new file mode 100755
index 0000000000000000000000000000000000000000..9423c0a606cbf5888a0bd1c2ddb2a6eacdd5de36
--- /dev/null
+++ b/LArCalorimeter/LArRecConditions/LArRecConditions/selection.xml
@@ -0,0 +1,8 @@
+<lcgdict>
+
+  <class name="LArHVPathologiesDb::LArHVElectPathologyDb" />
+  <class name="std::vector<LArHVPathologiesDb::LArHVElectPathologyDb>" />
+  <class name="LArHVPathologiesDb" id="6C17B534-249B-4FBA-A4DE-F4CE28312D73" />
+
+</lcgdict>
+
diff --git a/LArCalorimeter/LArRecConditions/cmt/requirements b/LArCalorimeter/LArRecConditions/cmt/requirements
new file mode 100644
index 0000000000000000000000000000000000000000..f2db2c9f42edc9ed017e0325256c4bd195c00a8c
--- /dev/null
+++ b/LArCalorimeter/LArRecConditions/cmt/requirements
@@ -0,0 +1,18 @@
+package LArRecConditions
+
+author Theodore Todorov
+author Ryan Taylor
+
+use AtlasPolicy     AtlasPolicy-*
+use GaudiInterface  GaudiInterface-*   External
+use AthenaKernel    AthenaKernel-*     Control
+use Identifier      Identifier-*       DetectorDescription
+use CaloIdentifier  CaloIdentifier-*   Calorimeter
+
+library LArRecConditions *.cxx -s=components *.cxx
+
+apply_pattern installed_library
+
+private
+use AtlasReflex  AtlasReflex-* External -no_auto_imports
+apply_pattern lcgdict dict=LArRecConditions selectionfile=selection.xml headerfiles="../LArRecConditions/LArRecConditionsDict.h"
diff --git a/LArCalorimeter/LArRecConditions/src/LArBadChanBitPacking.cxx b/LArCalorimeter/LArRecConditions/src/LArBadChanBitPacking.cxx
new file mode 100644
index 0000000000000000000000000000000000000000..f8f04b6b920ac9e9969c61659bb70b31e6111dc5
--- /dev/null
+++ b/LArCalorimeter/LArRecConditions/src/LArBadChanBitPacking.cxx
@@ -0,0 +1,132 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+#include "LArRecConditions/LArBadChanBitPacking.h"
+#include "LArRecConditions/LArBadChannel.h"
+
+LArBadChanBitPacking::LArBadChanBitPacking() : 
+  m_bitPos( 8*sizeof(BitWord),0),
+  m_index( 8*sizeof(BitWord),-1),
+  m_highGainMask(0),
+  m_mediumGainMask(0),
+  m_lowGainMask(0)
+{
+  // Here, specify each problem and its gain dependence.
+  addBit( deadReadoutBit, "deadReadout", independent);
+  addBit( deadCalibBit, "deadCalib", independent);
+  addBit( deadPhysBit, "deadPhys", independent);
+  addBit( almostDeadBit, "almostDead", independent);
+  addBit( shortBit, "short", independent);
+  addBit( unstableBit, "unstable", independent);
+  addBit( distortedBit, "distorted", independent);
+  addBit( lowNoiseHGBit, "lowNoiseHG", high);
+  addBit( highNoiseHGBit, "highNoiseHG", high);
+  addBit( unstableNoiseHGBit, "unstableNoiseHG", high);
+  addBit( lowNoiseMGBit, "lowNoiseMG", medium);
+  addBit( highNoiseMGBit, "highNoiseMG", medium);
+  addBit( unstableNoiseMGBit, "unstableNoiseMG", medium);
+  addBit( lowNoiseLGBit, "lowNoiseLG", low);
+  addBit( highNoiseLGBit, "highNoiseLG", low);
+  addBit( unstableNoiseLGBit, "unstableNoiseLG", low);
+  addBit( missingFEBBit, "missingFEB", independent);
+  addBit( peculiarCalibrationLineBit, "peculiarCalibrationLine", low);
+  addBit( problematicForUnknownReasonBit, "problematicForUnknownReason", independent);
+  addBit( sporadicBurstNoiseBit, "sporadicBurstNoise", independent);
+  addBit( deadSCACellBit, "deadSCACell", independent);
+  addBit( badFirstSampleBit, "badFirstSample", independent);
+
+  for (unsigned int i=0; i<m_enumVec.size(); i++) {
+    m_nameMap[m_nameVec[i]] = m_enumVec[i].first;
+    /// Initial assignment of bit positions same as enumerator values.
+    /// This may be changed FIXME provide method for changing it
+    m_bitPos[m_enumVec[i].first] = m_enumVec[i].first;
+
+    m_index[m_enumVec[i].first] = i;
+  }
+
+  initMasks(); // initialize the gain masks
+}
+
+void LArBadChanBitPacking::addBit( ProblemType pb, const std::string& name, 
+				   GainDependence gaindep)
+{
+  m_enumVec.push_back( std::make_pair( pb, gaindep));
+  m_nameVec.push_back(name);
+}
+
+
+const std::string& LArBadChanBitPacking::stringName( ProblemType pb) const 
+{
+  return m_nameVec.at(index(pb));
+}
+
+std::pair<bool, LArBadChannelEnum::ProblemType>
+LArBadChanBitPacking::enumName( const std::string& str) const
+{
+  std::map<std::string, ProblemType>::const_iterator i = m_nameMap.find( str);
+  if (i != m_nameMap.end()) { return std::make_pair(true,i->second);}
+  else return std::make_pair(false, (ProblemType) 0);
+}
+
+
+void LArBadChanBitPacking::setBit( ProblemType pb, BitWord& word, bool value) const {
+  BitWord mask = 1;
+  mask = mask << m_bitPos[static_cast<PosType>(pb)]; // all at 0 except pb bit
+  if (value) word |= mask;
+  else word &= ~mask;
+}
+
+bool LArBadChanBitPacking::setBit( const std::string& name, 
+				   BitWord& word, bool value) const
+{
+  std::pair<bool, ProblemType> res = enumName( name);
+  if (res.first) { // name corresponds to enum
+    setBit( res.second, word, value);
+    return true;
+  }
+  else return false; // name not recognized
+}
+
+void LArBadChanBitPacking::setBit( ProblemType pb, LArBadChannel& word, bool value) const
+{
+  setBit( pb, word.packedDataRef(), value);
+}
+
+bool LArBadChanBitPacking::setBit( const std::string& name, LArBadChannel& word, bool value) const
+{
+  return setBit( name, word.packedDataRef(), value);
+}
+
+std::string LArBadChanBitPacking::stringStatus( const LArBadChannel& bc) const
+{
+  std::string res;
+  for (unsigned int i=0; i<m_enumVec.size(); ++i) {
+    if ( ! bc.statusOK( m_enumVec.at(i).first  )) {
+      if (!res.empty()) res += " ";
+      res += m_nameVec.at(i);
+    }
+  }
+  return res;
+}
+
+void LArBadChanBitPacking::initMasks()
+{
+  for( std::vector< std::pair<ProblemType, GainDependence> >::const_iterator iter = m_enumVec.begin();
+       iter != m_enumVec.end(); ++iter)  //loop over all problems
+  {
+    // set the appropriate bits in each mask according to the GainDependence of the ProblemType
+    if(iter->second == independent)
+    {
+      setBit(iter->first, m_highGainMask);
+      setBit(iter->first, m_mediumGainMask);
+      setBit(iter->first, m_lowGainMask);
+    }
+    else if(iter->second == high)
+      setBit(iter->first, m_highGainMask);
+    else if(iter->second == medium)
+      setBit(iter->first, m_mediumGainMask);
+    else if(iter->second == low)
+      setBit(iter->first, m_lowGainMask);
+  }
+}
diff --git a/LArCalorimeter/LArRecConditions/src/LArBadChannel.cxx b/LArCalorimeter/LArRecConditions/src/LArBadChannel.cxx
new file mode 100644
index 0000000000000000000000000000000000000000..965a786501d1bbe009dcf9d5f66bda455296a5cc
--- /dev/null
+++ b/LArCalorimeter/LArRecConditions/src/LArBadChannel.cxx
@@ -0,0 +1,7 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+#include "LArRecConditions/LArBadChannel.h"
+
+LArBadChanBitPacking* LArBadChannel::s_packing = 0;
diff --git a/LArCalorimeter/LArRecConditions/src/LArBadChannelEnum.cxx b/LArCalorimeter/LArRecConditions/src/LArBadChannelEnum.cxx
new file mode 100644
index 0000000000000000000000000000000000000000..935f50baf74ba1c60cd13e2309dcadf331aabb3b
--- /dev/null
+++ b/LArCalorimeter/LArRecConditions/src/LArBadChannelEnum.cxx
@@ -0,0 +1,21 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+#include "LArRecConditions/LArBadChannelEnum.h"
+
+// DO NOT USE THESE CONSTANTS!
+///const LArBadChannelEnum::BitWord LArBadChannelEnum::HighGainMask=0x3ff;
+///const LArBadChannelEnum::BitWord LArBadChannelEnum::MediumGainMask=0x1c7f;
+///const LArBadChannelEnum::BitWord LArBadChannelEnum::LowGainMask=0xe07f;
+// Instead, use the following methods:
+// LArBadChanBitPacking::highGainMask()   
+// LArBadChanBitPacking::mediumGainMask()
+// LArBadChanBitPacking::lowGainMask()
+
+
+//Bit-pattern as defined in LArBadChannelEnum
+//     09876 543 210 987 6543210
+// HG: 00000 000 000 111 1111111
+// MG: 00000 000 111 000 1111111
+// LG: 00000 111 000 000 1111111
diff --git a/LArCalorimeter/LArRecConditions/src/LArBadChannelParser.cxx b/LArCalorimeter/LArRecConditions/src/LArBadChannelParser.cxx
new file mode 100644
index 0000000000000000000000000000000000000000..99ff76ac0a3e0038b94a872becf36096213c9ee1
--- /dev/null
+++ b/LArCalorimeter/LArRecConditions/src/LArBadChannelParser.cxx
@@ -0,0 +1,94 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+#include "LArRecConditions/LArBadChannelParser.h"
+
+#include <sstream>
+
+LArBadChannelParser::LArBadChannelParser(
+  const std::string& file, MsgStream* const log, 
+  unsigned int numInts, int numStrings, unsigned int firstWildcard
+  ) : 
+  m_linenumber(0), m_filename(file), m_log(log), 
+  m_numInts(numInts), m_numStrings(numStrings), 
+  m_firstWildcard(firstWildcard)
+{
+  m_fin.open(m_filename.c_str());
+  if(!m_log)
+    std::cerr << "ERROR \t LArBadChannelParser was given a NULL MsgStream pointer!" << std::endl;
+}
+
+LArBadChannelParser::~LArBadChannelParser()
+{
+  m_fin.close();
+}
+
+std::vector<std::string> LArBadChannelParser::parseLine(std::string& line) const
+{
+  std::string::size_type commentPosition = line.find('#');
+  if(commentPosition != std::string::npos)	//if a comment is found
+    line.erase(commentPosition);		//trim off the comment
+  // notice that the input parameter can be changed as a side-effect
+
+  std::vector<std::string> result;
+  std::string readWord;
+  std::istringstream stringIn(line);	
+
+  stringIn >> readWord;
+  while(stringIn)
+  {
+    result.push_back(readWord);
+    stringIn >> readWord;
+  }
+  return result;
+}
+
+
+int upper(int c) {
+  return std::toupper((unsigned char)c);
+}
+
+
+std::vector<int> LArBadChannelParser::getIdFields(const std::vector<std::string>& words) const
+{
+  std::vector<int> result;
+  std::string w;
+  for(unsigned int i = 0; i < m_numInts; ++i)
+  {
+    w=words[i]; //Copy to non-const string
+
+    //Allow 'B' or 'EMB' for Barrel or 'E' for Endcap in first field
+    if (i==0) {  
+      std::transform(w.begin(), w.end(), w.begin(), upper);
+
+      if (w.compare(0,3,"EMB")==0 || w[0]=='B')
+	w=std::string("0"); //Replace for barrel
+      else if (w[0]=='E')
+	w=std::string("1"); //Replace for endcap
+    }
+    else if (i==1) {  //Allow 'A' and 'C' do describe side in second field
+      if (w=="A" || w=="a")
+	w=std::string("1"); //Replace for positive side
+      else if (w=="C" || w=="c")
+	w=std::string("0"); //Replace for negative side
+    }
+
+    int idComponent(0);
+    bool canBeWildcard(m_firstWildcard > 0 && i + 1 >= m_firstWildcard);
+    if(canBeWildcard && w == "*")
+      result.push_back(-1);  	// -1 signifies wildcard 
+    else if(stringToNumber<int>(idComponent, w) && idComponent >= 0)
+      result.push_back(idComponent);
+    else
+    {
+      (*m_log) << MSG::WARNING << "LArBadChannelParser REJECTED line " << m_linenumber \
+        << " -\t word " << i + 1 << " must be a non-negative integer " \
+        << (canBeWildcard ? "or " : "and not " ) \
+        << "a wildcard: " << words[i] << endreq;
+      result.clear();
+      return result;	// return empty vector on error
+    }
+  }
+  return result;
+}
diff --git a/LArCalorimeter/LArRecConditions/src/LArBadFeb.cxx b/LArCalorimeter/LArRecConditions/src/LArBadFeb.cxx
new file mode 100644
index 0000000000000000000000000000000000000000..1c3e1b92f65323135e2047ed43eb9e2e608c98a1
--- /dev/null
+++ b/LArCalorimeter/LArRecConditions/src/LArBadFeb.cxx
@@ -0,0 +1,6 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+#include "LArRecConditions/LArBadFeb.h"
+
diff --git a/LArCalorimeter/LArRecConditions/src/LArBadFebBitPacking.cxx b/LArCalorimeter/LArRecConditions/src/LArBadFebBitPacking.cxx
new file mode 100644
index 0000000000000000000000000000000000000000..db08ca2624b0a83ede5cb070247cfad29482896b
--- /dev/null
+++ b/LArCalorimeter/LArRecConditions/src/LArBadFebBitPacking.cxx
@@ -0,0 +1,96 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+#include "LArRecConditions/LArBadFebBitPacking.h"
+#include "LArRecConditions/LArBadFeb.h"
+
+LArBadFebBitPacking::LArBadFebBitPacking() : 
+  m_index( 8*sizeof(BitWord),-1)
+{
+  // Here, specify each problem and its name
+  addBit( deadAllBit, "deadAll");
+  addBit( deadReadoutBit, "deadReadout");
+  addBit( inErrorBit, "inError");
+  addBit( deactivatedInOKSBit, "deactivatedInOKS");
+  addBit( maskParity, "maskParity");
+  addBit( maskBCID, "maskBCID");
+  addBit( maskSampleHeader, "maskSampleHeader");
+  addBit( maskEVTID, "maskEVTID");
+  addBit( maskScacStatus, "maskScacStatus");
+  addBit( maskScaOutOfRange, "maskScaOutOfRange");
+  addBit( maskGainMismatch, "maskGainMismatch");
+  addBit( maskTypeMismatch, "maskTypeMismatch");
+  addBit( maskNumOfSamples, "maskNumOfSamples");
+  addBit( maskEmptyDataBlock, "maskEmptyDataBlock");
+  addBit( maskDspBlockSize, "maskDspBlockSize");
+  addBit( maskCheckSum, "maskCheckSum");
+  addBit( maskMissingHeader, "maskMissingHeader");
+  addBit( maskBadGain, "maskBadGain");
+
+  for (unsigned int i=0; i<m_enumVec.size(); i++) {
+    m_index[m_enumVec[i]] = i;
+  }
+}
+
+void LArBadFebBitPacking::addBit( ProblemType pb, const std::string& name)
+{
+  m_enumVec.push_back(pb);
+  m_nameVec.push_back(name);
+  m_nameMap[name] = pb;
+}
+
+
+  const std::string& LArBadFebBitPacking::stringName( ProblemType pb) const 
+  {
+    return m_nameVec.at(index(pb));
+  }
+
+  std::pair<bool, LArBadFebEnum::ProblemType>
+    LArBadFebBitPacking::enumName( const std::string& str) const
+  {
+    std::map<std::string, ProblemType>::const_iterator i = m_nameMap.find( str);
+    if (i != m_nameMap.end()) { return std::make_pair(true,i->second);}
+    else return std::make_pair(false, (ProblemType) 0);
+  }
+
+
+  void LArBadFebBitPacking::setBit( ProblemType pb, BitWord& word, bool value) const {
+    BitWord mask = 1;
+    mask = mask << bitPosition(pb); // all at 0 except pb bit
+    if (value) word |= mask;
+    else word &= ~mask;
+  }
+
+  bool LArBadFebBitPacking::setBit( const std::string& name, 
+				    BitWord& word, bool value) const
+  {
+    std::pair<bool, ProblemType> res = enumName( name);
+    if (res.first) { // name corresponds to enum
+      setBit( res.second, word, value);
+      return true;
+    }
+    else return false; // name not recognized
+  }
+
+  void LArBadFebBitPacking::setBit( ProblemType pb, LArBadFeb& word, bool value) const
+  {
+    setBit( pb, word.packedDataRef(), value);
+  }
+
+  bool LArBadFebBitPacking::setBit( const std::string& name, LArBadFeb& word, bool value) const
+  {
+    return setBit( name, word.packedDataRef(), value);
+  }
+
+  std::string LArBadFebBitPacking::stringStatus( const LArBadFeb& bc) const
+  {
+    std::string res;
+    for (unsigned int i=0; i<m_enumVec.size(); ++i) {
+      if ( ! bc.statusOK( m_enumVec.at(i))) {
+	if (!res.empty()) res += " ";
+	res += m_nameVec.at(i);
+      }
+    }
+    return res;
+  }
diff --git a/LArCalorimeter/LArRecConditions/test/BadChanSvcTest.cpp b/LArCalorimeter/LArRecConditions/test/BadChanSvcTest.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..8510538093b6cd4ae8dcec1a6622457347d4b18d
--- /dev/null
+++ b/LArCalorimeter/LArRecConditions/test/BadChanSvcTest.cpp
@@ -0,0 +1,58 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+#include "BadChanService.h"
+#include "LArBadChannelParser.h"
+#include "LArBadChanBitPacking.h"
+#include <iostream>
+#include <cstdlib>
+#include <cmath>
+
+using namespace std;
+
+int main() {
+	
+	typedef BadChanService::BadChanInfo        BadChanInfo;
+	typedef BadChanInfo::BadChanVec            BadChanVec;
+	
+	string name="";
+	cout << "Input filename: " <<endl;
+	cin >> name;
+
+	LArBadChannelParser myParser(name);
+	if(!myParser.fileStatusGood()) cout << "File no good!" << endl;
+	vector<LArBadChannelParser::BadChannelEntry> res = myParser.parseAll();
+	if( res.size()==0) cout << "Empty result!" << endl;
+	
+	BadChanVec bcv;
+	LArBadChanBitPacking packing;
+	for (vector<LArBadChannelParser::BadChannelEntry>::const_iterator i = res.begin();
+		 i != res.end(); ++i) {
+		cout << i->channel << " "
+		<< i->status.packedData() 
+		<< " " << packing.stringStatus( i->status)
+		<< endl;
+		
+		bcv.push_back( BadChanVec::value_type( i->channel, i->status));
+	}
+	
+	BadChanInfo& bci = BadChanService::info();
+	bci.set(bcv);
+
+	cout << endl << "BCI has size " << bci.size() << endl;
+	for (BadChanInfo::const_iterator i=bci.begin(); i!=bci.end(); ++i) {
+		cout << i->first << " " << packing.stringStatus( i->second) << endl;
+	}
+	
+	for (vector<LArBadChannelParser::BadChannelEntry>::const_iterator i = res.begin();
+		 i != res.end(); ++i) {
+		LArBadChannel bc = bci.status(i->channel);
+		cout << i->channel << " "
+		<< bc.packedData() 
+		<< " " << packing.stringStatus( bc)
+		<< endl;
+	}
+
+	
+}
diff --git a/LArCalorimeter/LArRecConditions/test/badchannels.txt b/LArCalorimeter/LArRecConditions/test/badchannels.txt
new file mode 100644
index 0000000000000000000000000000000000000000..b2b87c088654f5fe2490df924fe37e2afe41ab02
--- /dev/null
+++ b/LArCalorimeter/LArRecConditions/test/badchannels.txt
@@ -0,0 +1,76 @@
+#bec pn FT       Slot Chan.   CalibLine   Status
+
+#the following channels belong to EMBC
+0    0	0	 5    117     0		  highNoiseHG  
+0    0	0	 13   48      0		  lowNoiseHG
+0    0	1	 1    121     0		  highNoiseHG
+0    0	1	 5    102     0		  highNoiseHG
+0    0	4	 4    84      0		  unstableNoiseHG
+0    0	5	 11   90      0		  highNoiseHG
+0    0	5	 13   114     0		  highNoiseHG
+0    0	7	 3    18      0		  highNoiseHG
+0    0	7	 6    18      0		  highNoiseHG
+0    0	10	 1    121     0		  highNoiseHG
+0    0	10	 8    3       0		  lowNoiseHG
+0    0	10	 9    55      0		  highNoiseHG
+0    0	14	 3    93      0		  highNoiseHG
+0    0	20	 14   54      0		  highNoiseHG
+0    0	21	 6    56      0		  unstableNoiseHG
+0    0	21	 6    64      0		  highNoiseHG
+0    0	22	 2    127     0		  highNoiseHG
+0    0	22	 3    127     0		  highNoiseHG
+0    0	22	 6    115     0		  lowNoiseHG
+0    0	22	 10   40      0		  unstableNoiseHG
+0    0	23	 9    72      0		  lowNoiseHG
+0    0	23	 12   72      0		  unstableNoiseHG
+0    0	24	 10   44      0		  lowNoiseHG
+0    0	26	 6    32      0		  highNoiseHG
+0    0	27	 1    121     0		  highNoiseHG
+0    0	28	 1    120     0		  highNoiseHG
+0    0	28	 1    121     0		  highNoiseHG
+0    0	28	 13   62      0		  highNoiseHG
+0    0	28	 13   63      0		  highNoiseHG
+0    0	29	 2    119     0		  highNoiseHG
+0    0	29	 14   40      0		  highNoiseHG
+0    0	30	 1    62      0		  highNoiseHG
+0    0	30	 1    63      0		  highNoiseHG
+0    0	30	 2    62      0		  highNoiseHG
+0    0	30	 2    63      0		  highNoiseHG
+0    0	30	 2    100     0		  highNoiseHG
+0    0	30	 2    127     0		  highNoiseHG
+0    0	30	 3    127     0		  highNoiseHG
+0    0	30	 6    113     0		  highNoiseHG
+0    0	31	 2    75      0		  highNoiseHG
+
+#the following channels belong to EMBA
+0    1	5 	 6    85      0		  unstableNoiseHG
+0    1	5 	 6    86      0		  unstableNoiseHG
+0    1	8 	 1    114     0		  highNoiseHG
+0    1	9 	 4    96      0		  highNoiseHG
+0    1	9 	 14   54      0		  unstableNoiseHG
+0    1	11	 1    56      0		  highNoiseHG
+0    1	11	 11   116     0		  highNoiseHG
+0    1	12	 12   77      0		  highNoiseHG
+0    1	13	 12   126     0		  highNoiseHG
+0    1	14	 7    87      0		  highNoiseHG
+0    1	14	 9    38      0		  highNoiseHG
+0    1	14	 9    64      0		  highNoiseHG
+0    1	15	 14   48      0		  highNoiseHG
+0    1	15	 14   50      0		  highNoiseHG
+0    1	16	 2    34      0		  highNoiseHG
+0    1	17	 1    121     0		  highNoiseHG
+0    1	17	 3    100     0		  highNoiseHG
+0    1	17	 6    117     0		  unstableNoiseHG
+0    1	17	 6    118     0		  unstableNoiseHG
+0    1	17	 6    119     0		  unstableNoiseHG
+0    1	17	 8    70      0		  unstableNoiseHG
+0    1	17	 14   20      0		  lowNoiseHG
+0    1	17	 14   21      0		  lowNoiseHG
+0    1	17	 14   22      0		  lowNoiseHG
+0    1	17	 14   23      0		  lowNoiseHG
+0    1	18	 6    86      0		  highNoiseHG
+0    1	21	 1    109     0		  highNoiseHG
+0    1	21	 6    118     0		  unstableNoiseHG
+0    1	24	 13   48      0		  lowNoiseHG
+0    1	26	 7    6       0		  highNoiseHG
+0    1	26	 7    7       0		  highNoiseHG
diff --git a/LArCalorimeter/LArRecConditions/test/ref.log b/LArCalorimeter/LArRecConditions/test/ref.log
new file mode 100644
index 0000000000000000000000000000000000000000..a587033d8df4dcd508a08106bc16885de3b7cfce
--- /dev/null
+++ b/LArCalorimeter/LArRecConditions/test/ref.log
@@ -0,0 +1,24 @@
+Parsing file 'badchannels.txt'.
+Failure on line 4:	ERROR - not enough parameters in command.
+Success on line 5:	SET 65123 highNoiseMG 
+Failure on line 6:	ERROR - unrecognized problem flag: ReallyLousy
+			WARNING - action not yet implemented: ADD
+Failure on line 8:	ERROR - unrecognized action: FIX
+			ERROR - unacceptable channel ID number: 1254s
+Failure on line 9:	ERROR - unacceptable channel ID number: 435.7
+Failure on line 10:	ERROR - unacceptable channel ID number: highNoiseHG
+			ERROR - unrecognized problem flag: 34562
+Failure on line 11:	ERROR - unacceptable channel ID number: -904
+Failure on line 13:	ERROR - unacceptable channel ID number: 984d2
+Success on line 14:	SET 45763 almostDead unstable 
+Failure on line 15:	WARNING - action not yet implemented: ADD
+Failure on line 18:	ERROR - unrecognized action: sdf2
+			ERROR - unacceptable channel ID number: ?3
+			ERROR - unrecognized problem flag: c{a]l
+			ERROR - unrecognized problem flag: hK
+			ERROR - unrecognized problem flag: X<N.--2^&*(
+Success on line 20:	SET 54871 deadReadout deadCalib deadPhys 
+Success on line 21:	SET 32567 unstableNoiseMG 
+Success on line 24:	SET 47852 highNoiseHG unstableNoiseHG 
+
+Parsing finished successfully.