text: import vcf
  import pyranges
  from .json_generator import _get_fhir_json
  import logging
  import sys
  general_logger = logging.getLogger('vcf2fhir.general')
  
  class Converter(object):
      """Converter for a VCF v >4.1 file."""
      def __init__(self, vcf_filename=None, ref_build=None, patient_id = None, has_tabix=False, conv_region_filename=None, conv_region_dict = None, region_studied_filename= None, nocall_filename = None):
          """ 
          Create a new Converter Object to convert a VCF file.
  
          Parameters
          ----------
          vcf_filename : str (Required)
              Path to text-based or bgzipped VCF file containing variants to be converted into FHIR format.
              Valid path and filename without whitespace. VCF file must conform to VCF Version 4.1 or later. 
              FORMAT.GT must be present. Multi-sample VCFs are allowed, but only the first sample will be converted.
          ref_build : str (Required)
              Genome Reference Consortium genome assembly to which variants in the VCF were called. Must be one of 'GRCh37' or 'GRCh38'.
          patient_id : str (Optional)
              Patient who's VCF file is being processed. Alphanumeric string without whitespace. Default value is first sample name.
          has_tabix : bool (Optional)
              If tabix file exist for the vcf than set it to True. Tabix file should have the same name as vcf file, with a '.tbi' extension,
              and must be in the same folder. Default value is False.
          conv_region_filename : str (Optional)
              Path to conversion region bed file. Subset of the VCF file to be converted into FHIR. If absent, the entire VCF file is converted. Must be a valid BED file
          conv_region_dict: dict (Optional)
              Conversion region can also be provided using dict. If 'conv_region_filename' is provided
              it will be ignored. 
              Format:  {"Chromosome": ["chr1", "chr2"], "Start": [100, 200], "End": [150, 201]}
          region_studied_filename : str (Optional)
              Path to region studied bed file. Subset of patient's genome that was studied in the generation of the VCF file. If present, only studied regions are converted. Must be a valid BED file, with first 3 columns: <chr> <start> <stop>.
          nocall_filename : str (Optional)
              Path to no call bed file. Subset of studied region that is deemed noncallable. If present, only studied regions minus noncallable regions are converted. Must be a valid BED file, with first 3 columns: <chr> <start> <stop>.
  
          Returns
          -------
          Object
          An Instance of Conveter that helps to convert vcf file.
  
          Examples
          --------
  
          """
          super(Converter, self).__init__()
          if not (vcf_filename):
              raise Exception('You must provide vcf_filename')
          if not ref_build or ref_build not in ["GRCh37", "GRCh38"]:
              raise Exception('You must provide build number ("GRCh37" or "GRCh38")')
          if nocall_filename and not region_studied_filename:
              raise Exception ("Please also provide region_studied_filename when nocall_filename is provided")
          self.vcf_filename = vcf_filename
          try:
              self._vcf_reader = vcf.Reader(filename=vcf_filename)
          except FileNotFoundError:
              raise
          except :
              self._generate_exception("Please provide valid  'vcf_filename'")
          if not patient_id:
              patient_id = self._vcf_reader.samples[0]
          if nocall_filename:
              try:
                  self.nocall_region = pyranges.read_bed(nocall_filename)
              except FileNotFoundError:
                  raise
              except:
                  self._generate_exception("Please provide valid  'nocall_filename'")
          else:
              self.nocall_region = pyranges.PyRanges()
          if conv_region_filename:
              try:
                  self.conversion_region = pyranges.read_bed(conv_region_filename)
              except FileNotFoundError:
                  raise
              except:
                  self._generate_exception( "Please provide valid 'conv_region_filename'")
          elif conv_region_dict:      
              try:
                  self._fix_conv_region_zero_based(conv_region_dict)
                  self.conversion_region = pyranges.from_dict(conv_region_dict)
              except FileNotFoundError:
                  raise
              except:
                  self._generate_exception("Please provide valid 'conv_region_dict'")
          else:
              self.conversion_region = None         
          if region_studied_filename:
              try:
                  self.region_studied = pyranges.read_bed(region_studied_filename)
              except FileNotFoundError:
                  raise
              except:
                  self._generate_exception("Please provide valid 'region_studied_filename'")
          else:
              self.region_studied = None
          self.has_tabix = has_tabix
          self.patient_id = patient_id
          self.ref_build = ref_build
          self.nocall_filename = nocall_filename
          self.conv_region_filename = conv_region_filename
          general_logger.info("Converter class instantiated successfully")
      def convert(self, output_filename='fhir.json'):
          """ Returns True on success
  
          Parameters
          ----------
          output_filename : str, default fhir.json
              Path to output fhir json.
  
          Returns
          ----------
          bool True on successful conversion
  
          """
          try:
              general_logger.info("Starting VCF to FHIR Conversion")
              _get_fhir_json(self._vcf_reader, self.ref_build, self.patient_id, self.has_tabix, self.conversion_region, self.region_studied, self.nocall_region, output_filename)
          except:
              general_logger.error("Error in converting vcf file", exc_info=True)
              return False
          return True
  
      def _fix_conv_region_zero_based(self, conv_region_dict):
          i = 0
          for start in conv_region_dict["Start"]:
              conv_region_dict["Start"][i] = start - 1
              i += 1
          i = 0
          for end in conv_region_dict["End"]:
              conv_region_dict["End"][i] = end - 1
              i += 1
  
      def _generate_exception(self, msg):
          general_logger.error(msg, exc_info=True)
          raise Exception (msg, sys.exc_info)
  
  