示例#1
0
def get_last_model(**kwargs):
    log_dir = get_varargin(kwargs, 'log_dir', cfg.FILEIO.LOG_DIR)
    and_key = get_varargin(kwargs, 'and_key', ['.ckpt'])
    or_key = get_varargin(kwargs, 'or_key', None)
    # List .h5 files in model_dir directory
    file_list = utils.select_files(log_dir, and_key=and_key, or_key=or_key)
    return sorted(file_list)[-1]
示例#2
0
 def __init__(self, **kwargs):
     super(profiling_Callback, self).__init__()
     self.nb_epochs = get_varargin(kwargs, 'epochs', cfg.TRAIN.NB_EPOCHS)
     self.steps_per_epoch = get_varargin(kwargs, 'steps_per_epoch',
                                         cfg.TRAIN.STEPS_PER_EPOCH)
     self.profiling_freq = get_varargin(kwargs, 'profiling_freq',
                                        cfg.TRAIN.PROFILING_FREQ)
示例#3
0
def downloadimages(query, **kwargs):
    # keywords is the search query
    # format is the image file format
    # limit is the number of images to be downloaded
    # print urs is to print the image file url
    # size is the image size which can
    # be specified manually ("large, medium, icon")
    # aspect ratio denotes the height width ratio
    # of images to download. ("tall, square, wide, panoramic")
    output_dir = get_varargin(kwargs, 'output_directory', os.getcwd())
    nb_images = get_varargin(kwargs, 'nb_images', 4)
    img_size = get_varargin(kwargs, 'size', 'medium')

    arguments = {
        "keywords": query,
        "format": "jpg",
        "limit": nb_images,
        "print_urls": True,
        'output_directory': output_dir,
        "size": img_size
    }
    # creating object
    response = google_images_download.googleimagesdownload()
    try:
        response.download(arguments)
    # Handling File NotFound Error
    except FileNotFoundError:
        pass
示例#4
0
def train_init(model, **kwargs):
    model_name = get_varargin(kwargs, 'model_name', cfg.MODEL.NAME)
    retrain = get_varargin(kwargs, 'retrain', True)
    logging.info('Retrain Model: {}'.format(retrain))
    init_epoch = 0
    if retrain is False:  # Train from scratch
        prefix = datetime.now().strftime('%y%m%d_%H%M')
        ckpts_logdir = os.path.join(cfg.FILEIO.LOG_DIR, '{}-{}-ckpts'\
            .format(prefix, model_name))
        utils.makedir(ckpts_logdir)
        model = model
    else:
        last_model = get_last_model(log_dir=cfg.FILEIO.LOG_DIR)
        ckpts_logdir = os.path.dirname(last_model)
        last_model = last_model.replace('.index', '')
        filename = os.path.splitext(Path(last_model).name)[0]
        init_epoch = int(filename[filename.rfind('-') + 1:])
        logging.info('Load model weights from: {}'.format(
            Path(last_model).name))
        model.load_weights(last_model)
        # model = KM.load_model(last_model)
    # Save cfg to yaml file
    yaml_filepath = Path(ckpts_logdir) / '{}-config.yaml'.format(
        cfg.MODEL.NAME.lower())
    baseConfig.make_yaml_file(cfg, yaml_filepath)
    return model, ckpts_logdir, init_epoch
示例#5
0
def make_captions(**kwargs):
    filepath = get_varargin(kwargs, 'filepath', None)
    save_opt = get_varargin(kwargs, 'save', True)
    data_dir = Path(filepath).parent
    doc = utils.read_txt(filepath=filepath)
    # Parse captions
    logging.info('Create captions for images')
    captions = dict()
    # tqdm_out = TqdmToLogger(logging.getLogger(),level=logging.INFO)
    for line in tqdm(doc.split('\n'), file=logger.logging_tqdm()):
        # split line by white space
        tokens = line.split()
        if len(line) < 2:
            continue

# take the first token as the image id, the rest as the description
        image_id, image_desc = tokens[0], tokens[1:]
        # remove filename from image id
        image_id = image_id.split('.')[0]
        # convert description tokens back to string
        image_desc = 'startseq ' + ' '.join(image_desc) + ' endseq'
        # create the list if needed
        if image_id not in captions:
            captions[image_id] = list()
        captions[image_id].append(image_desc)
    # Clean captions
    logging.info('Clean captions')
    clean_descriptions(captions)
    if save_opt is True:
        utils.save_json(captions, filepath=data_dir / 'flickr8k_captions.json')
    return captions
示例#6
0
def ResNet50(input_tensor=None,
             pooling=None,
             **kwargs):
    """Instantiates the ResNet50 architecture.
    # Arguments       
    # Returns
        A Keras model instance.
    """
    # Input arguments
    include_top = get_varargin(kwargs, 'include_top', True)
    nb_classes = get_varargin(kwargs, 'nb_classes', 1000)
    default_input_shape = _obtain_input_shape(None,
                                      default_size=224,
                                      min_size=197,
                                      data_format=K.image_data_format(),
                                      require_flatten=include_top)
    input_shape = get_varargin(kwargs, 'input_shape', default_input_shape)
    if input_tensor is None:
        img_input = KL.Input(shape=input_shape)
    else:
        if not K.is_keras_tensor(input_tensor):
            img_input = KL.Input(tensor=input_tensor, shape=input_shape)
        else:
            img_input = input_tensor
            
    bn_axis = 3 if K.image_data_format() == 'channels_last' else 1        

    x = KL.ZeroPadding2D((3, 3))(img_input)
    x = KL.Conv2D(64, (7, 7), strides=(2, 2), name='conv1')(x)
    x = KL.BatchNormalization(axis=bn_axis, name='bn_conv1')(x)
    x = KL.Activation('relu')(x)
    x = KL.MaxPooling2D((3, 3), strides=(2, 2))(x)
    
    for stage, nb_block in zip([2,3,4,5], [3,4,6,3]):
        for blk in range(nb_block):
            conv_block = True if blk == 0 else False
            strides = (2,2) if stage>2 and blk==0 else (1,1)           
            x = identity_block(x, stage = stage, block_id = blk + 1,
                               conv_block = conv_block, strides = strides)
            
    x = KL.AveragePooling2D((7, 7), name='avg_pool')(x)

    if include_top:
        x = KL.Flatten()(x)
        x = KL.Dense(nb_classes, activation='softmax', name='fc1000')(x)
    else:
        if pooling == 'avg':
            x = KL.GlobalAveragePooling2D()(x)
        elif pooling == 'max':
            x = KL.GlobalMaxPooling2D()(x)
    # Ensure that the model takes into account
    # any potential predecessors of `input_tensor`.
    if input_tensor is not None:
        inputs = get_source_inputs(input_tensor)
    else:
        inputs = img_input
        
    # Create model.
    model = Model(inputs, x, name='resnet50')
    return model
示例#7
0
def logging_figure(fig, **kwargs):
    desc = get_varargin(kwargs, 'description', '')
    img_size = get_varargin(kwargs, 'img_size', 500)
    tmpfile = BytesIO()
    fig.savefig(tmpfile, format='png')
    encoded = base64.b64encode(tmpfile.getvalue()).decode('utf-8')
    html = desc + "<br/>" + "<img src=\'data:image/png;base64,{}\' style = 'width:{}px;height:{}px'>".format(encoded,img_size,img_size)
    logging.info(html)
示例#8
0
 def log_fig(self, fig, **kwargs):
     desc = get_varargin(kwargs, 'description', '')
     img_size = get_varargin(kwargs, 'figsize', (800,600))
     tmpfile = BytesIO()
     fig.savefig(tmpfile, format='png')
     encoded = base64.b64encode(tmpfile.getvalue()).decode('utf-8')
     html = desc + "<br/><br/>" + "<img src=\'data:image/png;base64,{}\' style = 'width:{}px;height:{}px'>"\
         .format(encoded,img_size[0],img_size[1])
     self.filelogger.info(html)    
示例#9
0
def html_text(icon_path, text, **kwargs):
    iconw = get_varargin(kwargs, 'icon_width', 16)
    iconh = get_varargin(kwargs, 'icon_height', 16)
    font_color = get_varargin(kwargs, 'font_color', 'black')
    font_size = get_varargin(kwargs, 'font_size', 4)
    html_icon = '<img src="{}" height = {} width = {}>'.format(icon_path, iconw, iconh)
    html_text = '<font color = {} size="{}"> {} </font>'.format(font_color, font_size, text)
    html_label = html_icon + html_text
    return html_label
示例#10
0
 def plt_keras_model(self, model, **kwargs):
     desc = get_varargin(kwargs, 'description', '')
     img_size = get_varargin(kwargs, 'figsize', (500,800))
     kerasUtils.plot_model(model, to_file = 'model.png',
                           show_shapes = True,
                           dpi = 120,
                           expand_nested = True)
     encoded = base64.b64encode(open('model.png', 'rb').read()).decode('utf-8')
     img_tag = desc + "<br/><br/>" + "<img src=\'data:image/png;base64,{}\' style = 'width:{}px;height:{}px'>"\
         .format(encoded,img_size[0],img_size[1])
     os.remove('model.png')
     self.filelogger.info(img_tag)    
示例#11
0
def identity_block(x, **kwargs):
    """The identity block is the block that has no conv layer at shortcut.
    # Arguments
        input_tensor: input tensor
        kernel_size: defualt 3, the kernel size of middle conv layer at main path
        filters: list of integers, the filterss of 3 conv layer at main path
        stage: integer, current stage label, used for generating layer names
        block: 'a','b'..., current block label, used for generating layer names
    # Returns
        Output tensor for the block.
    """
    kernel_size = get_varargin(kwargs, 'kernel_size', 3)
    strides = get_varargin(kwargs, 'strides', (1,1))
    stage = get_varargin(kwargs, 'stage', 2)
    conv_block = get_varargin(kwargs, 'conv_block', False)
    block_id = get_varargin(kwargs, 'block_id', 1)
    
    if stage == 2:
        filters = config.MODEL.RESNET.FILTERS_C2
    elif stage == 3:
        filters = config.MODEL.RESNET.FILTERS_C3
    elif stage == 4:
        filters = config.MODEL.RESNET.FILTERS_C4
    else:
        filters = config.MODEL.RESNET.FILTERS_C5
        
    filters1, filters2, filters3 = filters
    bn_axis = 3 # Channel last, tensorflow backend
    prefix_blockname = 'C{}_branch2_blk{}_'.format(stage, block_id)    
    fx = KL.Conv2D(filters1, (1, 1), strides = strides, name = '{}Conv1'.format(prefix_blockname))(x)
    fx = KL.BatchNormalization(axis=bn_axis, name = '{}Bnorm1'.format(prefix_blockname))(fx) #bn: batchnorm
    fx = KL.Activation('relu', name = '{}Act1'.format(prefix_blockname))(fx)

    fx = KL.Conv2D(filters2, kernel_size,padding='same', name = '{}Conv2'.format(prefix_blockname))(fx)
    fx = KL.BatchNormalization(axis = bn_axis, name = '{}Bnorm2'.format(prefix_blockname))(fx)
    fx = KL.Activation('relu', name = '{}Act2'.format(prefix_blockname))(fx)

    fx = KL.Conv2D(filters3, (1, 1), name = '{}Conv3'.format(prefix_blockname))(fx)
    fx = KL.BatchNormalization(axis=bn_axis, name = '{}Bnorm3'.format(prefix_blockname))(fx)
    
    prefix_blockname = 'C{}_branch1_blk{}_'.format(stage, block_id)    
    #Shortcut branch     
    if conv_block is True:
        shortcut = KL.Conv2D(filters3, (1, 1), strides = strides, name = '{}Conv1'.format(prefix_blockname))(x)
        shortcut = KL.BatchNormalization(axis=bn_axis, name = '{}Bnorm1'.format(prefix_blockname))(shortcut)
    else:
        shortcut = x
        
#   Merge
    fx = KL.Add()([fx, shortcut])
    fx = KL.Activation('relu')(fx)
    return fx
示例#12
0
    def __init__(self, **kwargs):
        # Initialize Class
        default_logfile = os.path.join(current_dir, 'logging.html')
        write_mode = get_varargin(kwargs, 'mode', 'a')
        log_file = get_varargin(kwargs, 'log_file', default_logfile)
        if not os.path.isfile(log_file) or write_mode == 'w':
            with open(log_file,'w') as fid:
                fid.write('<head><title>luulog</title></head>')

        file_hdl = logging.FileHandler(log_file, mode = 'a')
        file_hdl.setFormatter(html_colorFormatter())
        self.file_hdl = file_hdl
        self.make_logger()
示例#13
0
def show_msg_dialog(**kwargs):
    msg_type = get_varargin(kwargs, 'type', 'info')
    title = get_varargin(kwargs, 'title', 'Message Dialog')
    message = get_varargin(kwargs, 'message', 'Custom message')

    msg = QMessageBox()
    if msg_type == 'info':
        msg.setIcon(QMessageBox.Information)
    elif msg_type == 'warning':
        msg.setIcon(QMessageBox.Warning)
    elif msg_type == 'question':
        msg.setIcon(QMessageBox.Question)
    msg.setText(message)
    msg.setWindowTitle(title)
    msg.exec_()
示例#14
0
 def list_private_function_names(self, **kwargs):
     key = get_varargin(kwargs, 'key', 'all')
     func_names = []
     for mem in self.function_members:
         if mem[0].startswith('_'):
             func_names.append(mem[0])
     return self.match_key(func_names, key)
示例#15
0
def plt_samples(img_list, **kwargs):
    figsize = get_varargin(kwargs, 'figsize', (6, 6))
    nb_cols = get_varargin(kwargs, 'nb_cols', 3)
    nb_img = len(img_list)
    labels = get_varargin(kwargs, 'labels', [None] * nb_img)
    cmap = get_varargin(kwargs, 'cmap', 'gray_r')
    suptitle = get_varargin(kwargs, 'suptitle', 'Train Images Samples')
    nb_rows = np.ceil(nb_img / nb_cols)
    fig = plt.figure(figsize=figsize)
    for idx, (img, label) in enumerate(zip(img_list, labels)):
        ax = fig.add_subplot(nb_rows, nb_cols, idx + 1)
        plt.imshow(img, cmap=cmap)
        plt.axis('off')
        ax.set_title(label)
        plt.suptitle(suptitle)
    return fig
示例#16
0
 def list_method_names(self, **kwargs):
     key = get_varargin(kwargs, 'key', 'all')
     names = []
     for mem in self.method_members:
         if not mem[0].startswith('_'):
             names.append(mem[0])
     return self.match_key(names, key)
示例#17
0
 def list_attrs(self, **kwargs):
     key = get_varargin(kwargs, 'key', 'all')
     attrs = []
     for mem in self.attr_members:
         if not mem[0].startswith('_'):
             attrs.append(mem[0])
     return self.match_key(attrs, key)
示例#18
0
 def get_nb_gpus(**kwargs):
     verbose = get_varargin(kwargs, 'verbose', False)
     local_devices = device_lib.list_local_devices()
     gpu_list = [
         x.name for x in local_devices if x.device_type.lower() == 'gpu'
     ]
     if verbose:
         print(gpu_list)
     return len(gpu_list)
示例#19
0
 def add_layouts(current_layout, layout_list, **kwargs):
     nb_comps = len(layout_list)
     ratio_list = get_varargin(kwargs, 'ratio',[np.floor(100/nb_comps)]*nb_comps)
     for layout, ratio in zip(layout_list, ratio_list):
         layout_type = layout.__class__.__name__
         if layout_type == 'QGroupBox':
             current_layout.addWidget(layout, ratio)
         else:
             current_layout.addLayout(layout, ratio)
示例#20
0
def matplotlib_canvas(**kwargs):
    layout_type = get_varargin(kwargs, 'layout', 'vertical')
    if layout_type == 'vertical':
        layout = QVBoxLayout()
    else:
        layout = QHBoxLayout()
    figure = Figure()
    canvas = FigureCanvasQTAgg(figure)
    layout.addWidget(canvas)
    return layout, figure
示例#21
0
 def create_slider(**kwargs):
     slider_type = get_varargin(kwargs, 'type', 'horizontal')
     if slider_type == 'horizontal':
         py_comp = QSlider(Qt.Horizontal)
     else:
         py_comp = QSlider(Qt.Vertical)
     py_comp.setMinimum(0)
     py_comp.setMaximum(100)
     py_comp.setValue(50)
     py_comp.setTickInterval(10)
     py_comp.setTickPosition(QSlider.TicksBelow)
     return py_comp
示例#22
0
def download_model_weight(model_url,**kwargs):
    """
    Download pre-trained model weight .h5 from url
    
    Arguments:
        model_url {str} -- link to .h5 file
    """
    model_dir = cfg.FILEIO.PRE_TRAINED_DIR
    model_filename = os.path.split(model_url)[1]
    to_file = get_varargin(kwargs, 'to_file', os.path.join(model_dir, model_filename))
    # Start downloading
    utils.download_url(model_url, to_file)
示例#23
0
def make_subset_captions(caption_filepath, subsetImg_filepath, **kwargs):
    # Parse input arguments
    save_opt = get_varargin(kwargs, 'save', True)
    data_dir = Path(subsetImg_filepath).parent
    # subsetImg_filename = os.path.splitext(Path(subsetImg_filepath).name)[0]
    captions = make_captions(filepath=caption_filepath)

    subsetid_set = make_imgID_set(subsetImg_filepath)

    logging.info('Create Captions for subset image Ids')
    subset_captions = dict()
    for key, val in captions.items():
        if key in subsetid_set:
            subset_captions[key] = val
    return subset_captions
示例#24
0
 def __init__(self, **kwargs):
     line_height = get_varargin(kwargs, 'line_height', 0.5)
     black = "<p  style = 'line-height: {}; color:black; white-space:pre'>".format(line_height)
     blue = "<p style='color:blue'>"
     orange = "<p style='color:#ff8c00; font-weight:bold'>"
     red = "<p style='color:red; font-weight:bold'>"
     span = "<span style='color: #026440;''>"
     reset = "</p>"
     msgformat = '%(asctime)s|%(filename)s:%(lineno)d|%(levelname)s|'
     self.FORMATS = {
         logging.DEBUG: blue + msgformat + "\t" + '%(message)s' + reset,
         logging.INFO: black + span +  msgformat + "</span>\t" + '%(message)s' + reset,
         logging.WARNING: orange + msgformat + "\t" + '%(message)s' + reset,
         logging.ERROR: red + msgformat +"\t"+ '%(message)s' +  reset,
         logging.CRITICAL: red + msgformat + "\t" + '%(message)s' + reset
     }
示例#25
0
def load_df(fullfilename, **kwargs):
    """Load .csv or .xlxs file to pandas dataframe
    Input:
        fullfilename: fullpath to input data file in .csv or .xlsx format
        Options:
            skiprows: row index to skip
    Returns:
        df: pandas dataframe
    """
    skiprows = get_varargin(kwargs, 'skiprows', None)
    filename, file_ext = os.path.splitext(fullfilename)
    logging.info('Pandas read: {}{}'.format(filename, file_ext))
    if file_ext == '.csv':
        df = pd.read_csv(fullfilename, skiprows=skiprows)
    else:
        df = pd.read_excel(fullfilename, skiprows=skiprows)
    # ==== END ====
    logging.info('DONE: %s' % inspect.stack()[0][3])
    return df
示例#26
0
def logging_setup(**kwargs):
    default_logfile = os.path.join(current_dir, 'logging.html')
    log_file = get_varargin(kwargs, 'log_file', default_logfile)
    # 	Logging
    logger = logging.getLogger()
    html_logger = logging.getLogger()
    
    stream_hdl = logging.StreamHandler(sys.stdout)
    file_hdl = logging.FileHandler(log_file, mode = 'a')
    stream_hdl.setFormatter(colorFormatter())
    logger.addHandler(stream_hdl)
    file_hdl.setFormatter(html_colorFormatter())
    
    logger.addHandler(file_hdl)
    logger.setLevel(logging.INFO)
    html_logger.addHandler(file_hdl)
    html_logger.setLevel(logging.INFO)
    # Only keep one logger
    for h in logger.handlers[:-2]: 
        logger.removeHandler(h)
    return logger
示例#27
0
def fileIO_config(**kwargs):
    """
     **kwargs:
        project -- str. project name. Default: serviceBot
    Returns:
        FILEIO -- ecict. FileIO configuration
    """
    project_name = get_varargin(kwargs, 'project', 'serviceBot')
    FILEIO = edict()
    # Directories
    FILEIO.PROJECT_DIR = os.path.join(user_dir, project_name)
    FILEIO.LOG_DIR = os.path.join(FILEIO.PROJECT_DIR, 'logs')
    FILEIO.PRE_TRAINED_DIR = os.path.join(FILEIO.PROJECT_DIR,
                                          'train/pre_trained')
    FILEIO.DATASET_DIR = os.path.join(FILEIO.PROJECT_DIR, 'datasets')
    # files
    FILEIO.YAML_CONFIG = os.path.join(current_dir, 'base_config.yaml')
    # Make dirs
    for ipath in [FILEIO.LOG_DIR, FILEIO.DATASET_DIR, FILEIO.PRE_TRAINED_DIR]:
        utils.makedir(ipath)

    return FILEIO
示例#28
0
def train(model, **kwargs):
    train_dataset, test_dataset = load_dataset(X_train, y_train, X_test, y_test)
    nb_epochs = get_varargin(kwargs, 'epochs', NB_EPOCHS)
    
    for epoch in range(1, nb_epochs+1):
        progress = utils.ProgressBar(NB_BATCHS,
                                 title = 'Batch', 
                                 start = 0,
                                 symbol = '=', printer = 'stdout')
        start_time = time.time()
        total_loss = 0
        for idx, batch_data in enumerate(train_dataset):
            progress.current = idx +1
            progress()
            step_loss = train_step(model, batch_data)    
            total_loss += step_loss
        train_loss = total_loss/progress.current
        _,_,secs = utils.elapsed_time(start_time)
        logger.info('Training Model. Epochs: {}/{}. Batch size: {}. Elapsed time: {:.1f}s'\
            .format( epoch, nb_epochs, BATCH_SIZE, secs))
        logger.info('Train loss: {:.3f}, Train acc: {:.3f}%'\
            .format(train_loss, train_acc.result()*100))
        
        train_acc.reset_states()
示例#29
0
def logging_head(inputvar, **kwargs):
    size = get_varargin(kwargs, 'size', 5)
    if type(inputvar) is dict:
        inputdict = inputvar
        for key in list(inputdict)[:size]:
            logging.info('{}: {}'.format(key, inputdict[key]))
示例#30
0
def uigridcomp(**kwargs):
    layout_type = get_varargin(kwargs, 'layout', 'horizontal')
    font = get_varargin(kwargs, 'font', QFont('Arial', 11, QFont.Normal))
    groupbox = get_varargin(kwargs, 'groupbox', None)
    groupbox_icon = get_varargin(kwargs, 'groupbox_icon', None)
    comp_list = get_varargin(kwargs, 'components', None)
    nb_comps = len(comp_list)
    icon_path_list = get_varargin(kwargs, 'icons', [None] * nb_comps)
    label_list = get_varargin(kwargs, 'labels', [None] * nb_comps)
    ratio_list = get_varargin(kwargs, 'ratios',
                              [np.floor(100 / nb_comps)] * nb_comps)

    if layout_type == 'vertical':
        layout = QVBoxLayout()
    else:
        layout = QHBoxLayout()

    def create_slider(**kwargs):
        slider_type = get_varargin(kwargs, 'type', 'horizontal')
        if slider_type == 'horizontal':
            py_comp = QSlider(Qt.Horizontal)
        else:
            py_comp = QSlider(Qt.Vertical)
        py_comp.setMinimum(0)
        py_comp.setMaximum(100)
        py_comp.setValue(50)
        py_comp.setTickInterval(10)
        py_comp.setTickPosition(QSlider.TicksBelow)
        return py_comp

    output_widgets = []
    for comp, label, icon, ratio in zip(comp_list, label_list, icon_path_list,
                                        ratio_list):
        py_comp = None
        if comp == 'pushbutton':
            py_comp = QPushButton(label)
            py_comp.setIcon(QIcon(icon))
        elif comp == 'togglebutton':
            py_comp = QPushButton(label)
            py_comp.setIcon(QIcon(icon))
            py_comp.setCheckable(Tru)
            py_comp.toggle()
        elif comp == 'hSlider':
            py_comp = create_slider(type='horizontal')
        elif comp == 'vSlider':
            py_comp = create_slider(type='vertical')
        elif comp == 'edit':
            py_comp = QLineEdit(label)
        elif comp == 'combobox':
            py_comp = QComboBox()
            py_comp.setInsertPolicy(QComboBox.InsertAtTop)
            py_comp.addItems(label)
        elif comp == 'label':
            py_comp = QLabel(label)
        elif comp == 'list':
            py_comp = QListWidget()
            py_comp.addItems(label)
            # py_comp.setSelectionMode(QAbstractItemView.MultiSelection)
        elif comp == 'radio':
            py_comp = QRadioButton(label)
            py_comp.setIcon(QIcon(icon))
        elif comp == 'blank':
            layout.addStretch(0)
        if comp != 'blank':
            py_comp.setFont(font)
            output_widgets.append(py_comp)
            layout.addWidget(py_comp, ratio)

    if groupbox is not None:
        groupbox_obj = QGroupBox(groupbox)
        gbox_font = font
        gbox_font.setBold(True)
        groupbox_obj.setFont(gbox_font)
        groupbox_obj.setLayout(layout)
        return groupbox_obj, output_widgets
    else:
        return layout, output_widgets