original_docstring: Creates a stacked bar plot of emissions by generator tech type.
  
          The emission type to plot is defined using the prop argument.
          A separate bar is created for each scenario.
  
          Args:
              prop (str, optional): Controls type of emission to plot.
                  Controlled through the plot_select.csv.
                  Defaults to None.
              start_date_range (str, optional): Defines a start date at which to represent data from. 
                  Defaults to None.
              end_date_range (str, optional): Defines a end date at which to represent data to.
                  Defaults to None.
              custom_data_file_path (str, optional): Path to custom data file to concat extra 
                  data. Index and column format should be consistent with output data csv.
  
          Returns:
              dict: dictionary containing the created plot and its data table.
          
docstring: Creates a stacked bar plot of emissions by generator tech type.
  The emission type to plot is defined using the prop argument.
  A separate bar is created for each scenario.
docstring_tokens: Creates a stacked bar plot of emissions by generator tech type . The emission type to plot is defined using the prop argument . A separate bar is created for each scenario .
code: def total_emissions_by_type(self, prop: str = None, start_date_range: str = None,
                                  end_date_range: str = None, custom_data_file_path: str = None,
                                  **_):
          """Creates a stacked bar plot of emissions by generator tech type.
  
          The emission type to plot is defined using the prop argument.
          A separate bar is created for each scenario.
  
          Args:
              prop (str, optional): Controls type of emission to plot.
                  Controlled through the plot_select.csv.
                  Defaults to None.
              start_date_range (str, optional): Defines a start date at which to represent data from. 
                  Defaults to None.
              end_date_range (str, optional): Defines a end date at which to represent data to.
                  Defaults to None.
              custom_data_file_path (str, optional): Path to custom data file to concat extra 
                  data. Index and column format should be consistent with output data csv.
  
          Returns:
              dict: dictionary containing the created plot and its data table.
          """
          # Create Dictionary to hold Datframes for each scenario
          outputs = {}
  
          # List of properties needed by the plot, properties are a set of tuples and contain 3 parts:
          # required True/False, property name and scenarios required, scenarios must be a list.
          properties = [(True,"emissions_generators_Production",self.Scenarios)]
  
          # Runs get_formatted_data within PlotDataHelper to populate PlotDataHelper dictionary  
          # with all required properties, returns a 1 if required data is missing
          check_input_data = self.get_formatted_data(properties)
  
          if 1 in check_input_data:
              return MissingInputData()
  
          for zone_input in self.Zones:
              emitList = []
              self.logger.info(f"Zone = {zone_input}")
  
              # collect data for all scenarios and pollutants
              for scenario in self.Scenarios:
  
                  self.logger.info(f"Scenario = {scenario}")
  
                  emit = self["emissions_generators_Production"].get(scenario)
  
                  # Check if Total_Gen_Stack contains zone_input, skips if not
                  try:
                      emit = emit.xs(zone_input,level=self.AGG_BY)
                  except KeyError:
                      self.logger.warning(f"No emissions in Scenario : {scenario}")
                      continue
                  
                  # Rename generator technologies
                  emit = self.rename_gen_techs(emit)
                  # summarize annual emissions by pollutant and tech
                  emit = emit.groupby(['pollutant', 'tech']).sum()
                  # rename column based on scenario
                  emit.rename(columns={0:scenario}, inplace=True)
                  emitList.append(emit)
  
              # concatenate chunks
              try:
                  emitOut = pd.concat(emitList, axis=1)
              except ValueError:
                  self.logger.warning(f"No emissions found for : {zone_input}")
                  out = MissingZoneData()
                  outputs[zone_input] = out
                  continue
  
              # format results
              emitOut = emitOut/1E9 # Convert from kg to million metric tons
              emitOut = emitOut.loc[(emitOut != 0).any(axis=1), :] # drop any generators with no emissions
              emitOut = emitOut.T  # transpose back (easier for slicing by pollutant later)
  
              # subset to relevant pollutant (specified by user as property)
              try:
                  emitPlot = emitOut.xs(prop, level="pollutant", axis=1)
              except KeyError:
                  self.logger.warning(prop+ " emissions not found")
                  outputs = InputSheetError()
                  return outputs
  
              if pd.notna(custom_data_file_path):
                  emitPlot = self.insert_custom_data_columns(
                                                          emitPlot, 
                                                          custom_data_file_path)
  
              # Checks if emitOut contains data, if not skips zone and does not return a plot
              if emitPlot.empty:
                  out = MissingZoneData()
                  outputs[zone_input] = out
                  continue
          
              dataOut = emitPlot
                  
              # single pollutant plot
              mplt = PlotLibrary()
              fig, ax = mplt.get_figure()
  
              # Set x-tick labels 
              if len(self.custom_xticklabels) > 1:
                  tick_labels = self.custom_xticklabels
              else:
                  tick_labels = emitPlot.index
  
              mplt.barplot(emitPlot, color=self.PLEXOS_color_dict,
                          stacked=True, 
                          custom_tick_labels=tick_labels)
  
              ax.set_ylabel(f'Annual {prop} Emissions\n(million metric tons)', 
                                  color='black', rotation='vertical')
              # Add legend
              mplt.add_legend(reverse_legend=True)
              # Add title
              if mconfig.parser("plot_title_as_region"):
                  mplt.add_main_title(zone_input)
  
              outputs[zone_input] = {'fig': fig, 'data_table': dataOut}
  
          return outputs
code_tokens: def total_emissions_by_type ( self , prop : str = None , start_date_range : str = None , end_date_range : str = None , custom_data_file_path : str = None , ** _ ) : outputs = { } properties = [ ( True , "emissions_generators_Production" , self . Scenarios ) ] check_input_data = self . get_formatted_data ( properties ) if 1 in check_input_data : return MissingInputData ( ) for zone_input in self . Zones : emitList = [ ] self . logger . info ( f"Zone = {zone_input}" ) for scenario in self . Scenarios : self . logger . info ( f"Scenario = {scenario}" ) emit = self [ "emissions_generators_Production" ] . get ( scenario ) try : emit = emit . xs ( zone_input , level = self . AGG_BY ) except KeyError : self . logger . warning ( f"No emissions in Scenario : {scenario}" ) continue emit = self . rename_gen_techs ( emit ) emit = emit . groupby ( [ 'pollutant' , 'tech' ] ) . sum ( ) emit . rename ( columns = { 0 : scenario } , inplace = True ) emitList . append ( emit ) try : emitOut = pd . concat ( emitList , axis = 1 ) except ValueError : self . logger . warning ( f"No emissions found for : {zone_input}" ) out = MissingZoneData ( ) outputs [ zone_input ] = out continue emitOut = emitOut / 1E9 emitOut = emitOut . loc [ ( emitOut != 0 ) . any ( axis = 1 ) , : ] emitOut = emitOut . T try : emitPlot = emitOut . xs ( prop , level = "pollutant" , axis = 1 ) except KeyError : self . logger . warning ( prop + " emissions not found" ) outputs = InputSheetError ( ) return outputs if pd . notna ( custom_data_file_path ) : emitPlot = self . insert_custom_data_columns ( emitPlot , custom_data_file_path ) if emitPlot . empty : out = MissingZoneData ( ) outputs [ zone_input ] = out continue dataOut = emitPlot mplt = PlotLibrary ( ) fig , ax = mplt . get_figure ( ) if len ( self . custom_xticklabels ) > 1 : tick_labels = self . custom_xticklabels else : tick_labels = emitPlot . index mplt . barplot ( emitPlot , color = self . PLEXOS_color_dict , stacked = True , custom_tick_labels = tick_labels ) ax . set_ylabel ( f'Annual {prop} Emissions\n(million metric tons)' , color = 'black' , rotation = 'vertical' ) mplt . add_legend ( reverse_legend = True ) if mconfig . parser ( "plot_title_as_region" ) : mplt . add_main_title ( zone_input ) outputs [ zone_input ] = { 'fig' : fig , 'data_table' : dataOut } return outputs
short_docstring: Creates a stacked bar plot of emissions by generator tech type.
short_docstring_tokens: Creates a stacked bar plot of emissions by generator tech type .
comment: """Creates a stacked bar plot of emissions by generator tech type.
  
          The emission type to plot is defined using the prop argument.
          A separate bar is created for each scenario.
  
          Args:
              prop (str, optional): Controls type of emission to plot.
                  Controlled through the plot_select.csv.
                  Defaults to None.
              start_date_range (str, optional): Defines a start date at which to represent data from. 
                  Defaults to None.
              end_date_range (str, optional): Defines a end date at which to represent data to.
                  Defaults to None.
              custom_data_file_path (str, optional): Path to custom data file to concat extra 
                  data. Index and column format should be consistent with output data csv.
  
          Returns:
              dict: dictionary containing the created plot and its data table.
          """$SEP$# Create Dictionary to hold Datframes for each scenario$SEP$# List of properties needed by the plot, properties are a set of tuples and contain 3 parts:$SEP$# required True/False, property name and scenarios required, scenarios must be a list.$SEP$# Runs get_formatted_data within PlotDataHelper to populate PlotDataHelper dictionary  $SEP$# with all required properties, returns a 1 if required data is missing$SEP$# collect data for all scenarios and pollutants$SEP$# Check if Total_Gen_Stack contains zone_input, skips if not$SEP$# Rename generator technologies$SEP$# summarize annual emissions by pollutant and tech$SEP$# rename column based on scenario$SEP$# concatenate chunks$SEP$# format results$SEP$# Convert from kg to million metric tons$SEP$# drop any generators with no emissions$SEP$# transpose back (easier for slicing by pollutant later)$SEP$# subset to relevant pollutant (specified by user as property)$SEP$# Checks if emitOut contains data, if not skips zone and does not return a plot$SEP$# single pollutant plot$SEP$# Set x-tick labels $SEP$# Add legend$SEP$# Add title