Esempio n. 1
0
    def load_from_stats(self):
        '''loads stats data and converts to timeseries without saving'''
        stats = pd.read_csv(self.stats_filename, parse_dates=['timestamp'])

        u = stats['timestamp'].unique()
        u = pd.to_datetime(u)
        sample_volume = scpp.get_sample_volume(
            self.settings.PostProcess.pix_size,
            path_length=self.settings.PostProcess.path_length)

        dias, bin_lims = scpp.get_size_bins()
        vd_oil = np.zeros((len(u), len(dias)))
        vd_gas = np.zeros_like(vd_oil)
        vd_total = np.zeros_like(vd_oil)
        d50_gas = np.zeros(len(u))
        d50_oil = np.zeros_like(d50_gas)
        d50_total = np.zeros_like(d50_gas)
        self.cos = np.zeros_like(d50_total)
        # @todo make this number of particles per image, and sum according to index later
        nparticles_all = 0
        nparticles_total = 0
        nparticles_oil = 0
        nparticles_gas = 0

        for i, s in enumerate(tqdm(u)):
            substats = stats[stats['timestamp'] == s]
            nparticles_all += len(substats)

            nims = scpp.count_images_in_stats(substats)
            sv = sample_volume * nims

            oil = scog.extract_oil(substats)
            nparticles_oil += len(oil)
            dias, vd_oil_ = scpp.vd_from_stats(oil, self.settings.PostProcess)
            vd_oil_ /= sv
            vd_oil[i, :] = vd_oil_

            gas = scog.extract_gas(substats)
            nparticles_gas += len(gas)
            dias, vd_gas_ = scpp.vd_from_stats(gas, self.settings.PostProcess)
            vd_gas_ /= sv
            vd_gas[i, :] = vd_gas_
            d50_gas[i] = scpp.d50_from_vd(vd_gas_, dias)

            nparticles_total += len(oil) + len(gas)
            vd_total_ = vd_oil_ + vd_gas_
            d50_total[i] = scpp.d50_from_vd(vd_total_, dias)
            vd_total[i, :] = vd_total_

            self.cos[i] = scog.cos_check(dias, vd_total[i, :])

        self.vd_total = vd_total
        self.vd_gas = vd_gas
        self.vd_oil = vd_oil
        self.d50_total = d50_total
        self.d50_oil = d50_oil
        self.d50_gas = d50_gas
        self.u = u.tz_localize('UTC')
        self.dias = dias
Esempio n. 2
0
def convert_to_pj_format(stats_csv_file, config_file):
    '''converts stats files into a total, and gas-only time-series csvfile which can be read by the old matlab
    SummaryPlot exe'''

    settings = PySilcamSettings(config_file)
    logger.info('Loading stats....')
    stats = pd.read_csv(stats_csv_file)

    base_name = stats_csv_file.replace('-STATS.csv', '-PJ.csv')
    gas_name = base_name.replace('-PJ.csv', '-PJ-GAS.csv')

    ogdatafile = DataLogger(base_name, ogdataheader())
    ogdatafile_gas = DataLogger(gas_name, ogdataheader())

    stats['timestamp'] = pd.to_datetime(stats['timestamp'])
    u = stats['timestamp'].unique()
    sample_volume = sc_pp.get_sample_volume(
        settings.PostProcess.pix_size,
        path_length=settings.PostProcess.path_length)

    logger.info('Analysing time-series')
    for s in tqdm(u):
        substats = stats[stats['timestamp'] == s]
        nims = sc_pp.count_images_in_stats(substats)
        sv = sample_volume * nims

        oil = extract_oil(substats)
        dias, vd_oil = sc_pp.vd_from_stats(oil, settings.PostProcess)
        vd_oil /= sv

        gas = extract_gas(substats)
        dias, vd_gas = sc_pp.vd_from_stats(gas, settings.PostProcess)
        vd_gas /= sv
        d50_gas = sc_pp.d50_from_vd(vd_gas, dias)

        vd_total = vd_oil + vd_gas
        d50_total = sc_pp.d50_from_vd(vd_total, dias)

        data_total = cat_data_pj(s, vd_total, d50_total, len(oil) + len(gas))
        ogdatafile.append_data(data_total)

        data_gas = cat_data_pj(s, vd_gas, d50_gas, len(gas))
        ogdatafile_gas.append_data(data_gas)

    logger.info('  OK.')

    logger.info('Deleting header!')
    with open(base_name, 'r') as fin:
        data = fin.read().splitlines(True)
    with open(base_name, 'w') as fout:
        fout.writelines(data[1:])
    with open(gas_name, 'r') as fin:
        data = fin.read().splitlines(True)
    with open(gas_name, 'w') as fout:
        fout.writelines(data[1:])
    logger.info('Conversion complete.')
Esempio n. 3
0
    def plot_trimmed_stats(self):
        start_time = pd.to_datetime(
            self.ui.dateTimeStart.dateTime().toPyDateTime())
        end_time = pd.to_datetime(
            self.ui.dateTimeEnd.dateTime().toPyDateTime())
        self.trimmed_stats, self.output_filename = scpp.trim_stats(
            self.stats_filename,
            start_time,
            end_time,
            write_new=False,
            stats=self.stats)

        if np.isnan(self.trimmed_stats.equivalent_diameter.max()) or len(
                self.trimmed_stats) == 0:
            QMessageBox.warning(
                self, "No data in this segment!",
                'No data was found within the specified time range.',
                QMessageBox.Ok)
            return

        settings = PySilcamSettings(self.config_file)
        plt.figure(self.figure.number)
        plt.clf()
        stats_oil = scog.extract_oil(self.trimmed_stats)
        stats_gas = scog.extract_gas(self.trimmed_stats)

        sample_volume = scpp.get_sample_volume(
            settings.PostProcess.pix_size,
            path_length=settings.PostProcess.path_length)

        nims = scpp.count_images_in_stats(self.trimmed_stats)
        dias, vd = scpp.vd_from_stats(self.trimmed_stats, settings.PostProcess)
        dias, vd_oil = scpp.vd_from_stats(stats_oil, settings.PostProcess)
        dias, vd_gas = scpp.vd_from_stats(stats_gas, settings.PostProcess)

        sv = sample_volume * nims
        vd /= sv
        vd_oil /= sv
        vd_gas /= sv

        plt.plot(dias, vd_oil + vd_gas, 'k', label='TOTAL')
        plt.plot(dias, vd_oil, 'r', label='OIL')
        plt.plot(dias, vd_gas, 'b', label='GAS')
        plt.xscale('log')
        plt.xlabel('Equiv. diam (um)')
        plt.ylabel('Volume concentration (uL/L)')
        plt.xlim(10, 12000)
        plt.legend()

        self.canvas.draw()
Esempio n. 4
0
def test_analysis(img, PIX_SIZE, PATH_LENGTH, config_file=''):
    '''wrapper for pysilcam processing

    Args:
      img (unit8)           : image to be processed (equivalent to the background-corrected image obtained from the SilCam)
      PIX_SIZE (float)      : pixel size of the setup [um]
      PATH_LENGTH (float)   : path length of the setup [mm]

    Returns:
      dias (array)                      : mid points of the size distribution bins [um]
      vd (array)                        : volume concentration in each size bin [uL/L/bin]
      imbw (uint8)                      : segmented image
      stat_extract_time (timestamp)     : time taken to run statextract

    '''

    # administer configuration settings according to specified setup
    if config_file=='':
        testconfig = os.path.split(sccf.default_config_path())[0]
        testconfig = os.path.join(testconfig, 'tests/config.ini')
        conf.set('Process', 'real_time_stats', 'True')
        conf.set('Process', 'threshold', '0.85')
        conf.set('ExportParticles', 'export_images', 'False')
    else:
        testconfig = config_file
    conf = sccf.load_config(testconfig)
    conf.set('PostProcess', 'pix_size', str(PIX_SIZE))
    conf.set('PostProcess', 'path_length', str(PATH_LENGTH))

    settings = sccf.PySilcamSettings(conf) # pass these settings without saving a config file to disc

    # load tensorflow model
    nnmodel, class_labels = sccl.load_model(model_path=settings.NNClassify.model_path)

    start_time = pd.Timestamp.now() # time statextract
    # process the image
    stats, imbw, saturation = scpr.statextract(img, settings, pd.Timestamp.now(),
                                               nnmodel, class_labels)
    end_time = pd.Timestamp.now() # time statextract
    stat_extract_time = end_time - start_time

    dias, vd = scpp.vd_from_stats(stats, settings.PostProcess) # calculate the volume distribution from the processed stats
    # scale the volume distribution according to the SilCam setup specified
    sv = scpp.get_sample_volume(settings.PostProcess.pix_size,
                                path_length=settings.PostProcess.path_length)
    vd /= sv

    return dias, vd, imbw, stat_extract_time
Esempio n. 5
0
def nd_scaled(stats, settings, ax, c='k'):
    '''
    Plot the particle number distribution, scaled to the total volume of water sampled
    
    Args:
        stats (DataFrame)           : particle statistics from silcam process
        settings (PySilcamSettings) : settings associated with the data, loaded with PySilcamSettings
        ax ()                       : axis to plot data on
        c='k' (str)                 : color of the line to be plotted
        
    '''
    sv = sc_pp.get_sample_volume(settings.pix_size,
            path_length=settings.path_length,
            imx=2048, imy=2448) # sample volume per image
    # re-scale sample volume to number of images
    sv_total = sv * sc_pp.count_images_in_stats(stats) # total sampled water volume

    nd(stats, settings, ax, line=None, c='k', sample_volume=sv_total)
    return
Esempio n. 6
0
def gor_timeseries(stats, settings):
    from tqdm import tqdm

    u = stats['timestamp'].unique()
    td = pd.to_timedelta('00:00:' + str(settings.window_size / 2.))

    sample_volume = sc_pp.get_sample_volume(settings.pix_size,
                                            path_length=settings.path_length)

    gor = []
    time = []

    for t in tqdm(u):
        dt = pd.to_datetime(t)
        stats_ = stats[(pd.to_datetime(stats['timestamp']) < (dt + td))
                       & (pd.to_datetime(stats['timestamp']) > (dt - td))]

        oilstats = extract_oil(stats_)
        dias, vd_oil = sc_pp.vd_from_stats(oilstats, settings)
        nims = sc_pp.count_images_in_stats(oilstats)
        sv = sample_volume * nims
        vd_oil /= sv

        gasstats = extract_gas(stats_)
        dias, vd_gas = sc_pp.vd_from_stats(gasstats, settings)
        nims = sc_pp.count_images_in_stats(gasstats)
        sv = sample_volume * nims
        vd_gas /= sv

        gor_ = sum(vd_gas) / sum(vd_oil)

        time.append(pd.to_datetime(t))
        gor.append(gor_)

    if (len(gor) == 0) or (np.isnan(max(gor))):
        gor = np.nan
        time = np.nan

    return gor, time
Esempio n. 7
0
def export_timeseries(configfile, statsfile):

    settings = PySilcamSettings(configfile)

    print('Loading STATS data: ', statsfile)
    stats = pd.read_csv(statsfile)

    stats['timestamp'] = pd.to_datetime(stats['timestamp'])

    stats.sort_values(by='timestamp', inplace=True)

    print('Extracting oil and gas')
    stats_oil = scog.extract_oil(stats)
    stats_gas = scog.extract_gas(stats)

    print('Calculating timeseries')
    u = pd.to_datetime(stats['timestamp']).unique()

    sample_volume = sc_pp.get_sample_volume(settings.PostProcess.pix_size, path_length=settings.PostProcess.path_length)

    td = pd.to_timedelta('00:00:' + str(settings.PostProcess.window_size / 2.))

    vdts_all = []
    vdts_oil = []
    vdts_gas = []
    d50_all = []
    d50_oil = []
    d50_gas = []
    timestamp = []
    d50_av_all = []
    d50_av_oil = []
    d50_av_gas = []
    gor = []
    for s in tqdm(u):
        timestamp.append(pd.to_datetime(s))
        dt = pd.to_datetime(s)

        dias, vd_all = sc_pp.vd_from_stats(stats[stats['timestamp'] == s],
                                 settings.PostProcess)
        dias, vd_oil = sc_pp.vd_from_stats(stats_oil[stats_oil['timestamp'] == s],
                                 settings.PostProcess)
        dias, vd_gas = sc_pp.vd_from_stats(stats_gas[stats_gas['timestamp'] == s],
                                 settings.PostProcess)

        nims = sc_pp.count_images_in_stats(stats[stats['timestamp'] == s])
        sv = sample_volume * nims
        vd_all /= sv
        vd_oil /= sv
        vd_gas /= sv
        d50_all.append(sc_pp.d50_from_vd(vd_all, dias))
        d50_oil.append(sc_pp.d50_from_vd(vd_oil, dias))
        d50_gas.append(sc_pp.d50_from_vd(vd_gas, dias))

        vdts_all.append(vd_all)
        vdts_oil.append(vd_oil)
        vdts_gas.append(vd_gas)

        stats_av = stats[(stats['timestamp']<(dt+td)) & (stats['timestamp']>(dt-td))]
        stats_av_oil = scog.extract_oil(stats_av)
        stats_av_gas = scog.extract_gas(stats_av)
        d50_av_all.append(sc_pp.d50_from_stats(stats_av, settings.PostProcess))
        d50_av_oil.append(sc_pp.d50_from_stats(stats_av_oil, settings.PostProcess))
        d50_av_gas.append(sc_pp.d50_from_stats(stats_av_gas, settings.PostProcess))

        dias, vdts_av = sc_pp.vd_from_stats(stats_av, settings.PostProcess)
        dias, vdts_av_oil = sc_pp.vd_from_stats(stats_av_oil, settings.PostProcess)
        dias, vdts_av_gas = sc_pp.vd_from_stats(stats_av_gas, settings.PostProcess)
        nims = sc_pp.count_images_in_stats(stats_av)
        sv = sample_volume * nims
        vdts_av /= sv
        vdts_av_oil /= sv
        vdts_av_gas /= sv

        gor.append(np.sum(vdts_av_gas)/np.sum(vdts_av_oil))

    outpath, outfile = os.path.split(statsfile)
    outfile = outfile.replace('-STATS.csv','')
    outfile = os.path.join(outpath, outfile)

    time_series = pd.DataFrame(data=np.squeeze(vdts_all), columns=dias)
    time_series['D50'] = d50_all
    time_series['Time'] = timestamp
    time_series.to_excel(outfile +
            '-TIMESERIES' + '' + '.xlsx')

    time_series = pd.DataFrame(data=np.squeeze(vdts_oil), columns=dias)
    time_series['D50'] = d50_oil
    time_series['Time'] = timestamp
    time_series.to_excel(outfile +
            '-TIMESERIES' + 'oil' + '.xlsx')

    time_series = pd.DataFrame(data=np.squeeze(vdts_gas), columns=dias)
    time_series['D50'] = d50_gas
    time_series['Time'] = timestamp
    time_series.to_excel(outfile +
            '-TIMESERIES' + 'gas' + '.xlsx')

    plt.figure(figsize=(20, 10))

    if not np.min(np.isnan(d50_oil)):
        plt.plot(timestamp, d50_oil, 'ro')
    if not np.min(np.isnan(d50_av_oil)):
        plt.plot(timestamp, d50_av_oil, 'r-')
    lns1 = plt.plot(np.nan, np.nan, 'r-', label='OIL')

    if not np.min(np.isnan(d50_gas)):
        plt.plot(timestamp, d50_gas, 'bo')
    if not np.min(np.isnan(d50_av_gas)):
        plt.plot(timestamp, d50_av_gas, 'b-')
    lns2 = plt.plot(np.nan, np.nan, 'b-', label='GAS')

    plt.ylabel('d50 [um]')
    plt.ylim(0, max(plt.gca().get_ylim()))

    ax = plt.gca().twinx()
    plt.sca(ax)
    plt.ylabel('GOR')
    if not np.min(np.isnan(gor)):
        plt.plot(timestamp, gor, 'k')
    lns3 = plt.plot(np.nan, np.nan, 'k', label='GOR')
    plt.ylim(0, max(plt.gca().get_ylim()))

    lns = lns1 + lns2 + lns3
    labs = [l.get_label() for l in lns]
    plt.legend(lns, labs)

    plt.savefig(outfile +
                '-d50_TimeSeries.png', dpi=600, bbox_inches='tight')

    plt.close()
    print('Export figure made. ')
    print('Exporting averages... ')

    # average all
    dias, vd = sc_pp.vd_from_stats(stats,
                             settings.PostProcess)
    nims = sc_pp.count_images_in_stats(stats)
    sv = sample_volume * nims
    vd /= sv
    d50 = sc_pp.d50_from_vd(vd, dias)
    dfa = pd.DataFrame(data=[vd], columns=dias)
    dfa['d50'] = d50
    timestamp = np.min(pd.to_datetime(stats['timestamp']))
    dfa['Time'] = timestamp
    dfa.to_excel(statsfile.replace('-STATS.csv', '') +
                 '-AVERAGE' + '' + '.xlsx')

    #average oil
    dias, vd = sc_pp.vd_from_stats(stats_oil,
                             settings.PostProcess)
    vd /= sv # sample volume remains the same as 'all'
    d50 = sc_pp.d50_from_vd(vd, dias)
    dfa = pd.DataFrame(data=[vd], columns=dias)
    dfa['d50'] = d50
    timestamp = np.min(pd.to_datetime(stats['timestamp'])) # still use total stats for this time
    dfa['Time'] = timestamp
    dfa.to_excel(statsfile.replace('-STATS.csv', '') +
                 '-AVERAGE' + 'oil' + '.xlsx')

    #average gas
    dias, vd = sc_pp.vd_from_stats(stats_gas,
                             settings.PostProcess)
    vd /= sv # sample volume remains the same as 'all'
    d50 = sc_pp.d50_from_vd(vd, dias)
    dfa = pd.DataFrame(data=[vd], columns=dias)
    dfa['d50'] = d50
    timestamp = np.min(pd.to_datetime(stats['timestamp'])) # still use total stats for this time
    dfa['Time'] = timestamp
    dfa.to_excel(statsfile.replace('-STATS.csv', '') +
                 '-AVERAGE' + 'gas' + '.xlsx')

    print('Export done: ', outfile)
Esempio n. 8
0
def generate_report(report_name, PIX_SIZE = 28.758169934640524,
                    PATH_LENGTH=40, d50 = 400, TotalVolumeConcentration = 800,
                    MinD = 108, config_file=''):
    '''Create a report of the expected response of the silcam to the provided experimental setup

    Args:
      report_name   (str)                   :  The path and filename of a pdf to be created
      PIX_SIZE          (float)             :  pixel size of the setup [um]
      PATH_LENGTH (float)                   :  the path length of the setup [mm] Path length is the gap between housings
      d50   (float)                         :  the expected of the oil d50 (50th percentile of the cumulative sum of the volume distribution)
      TotalVolumeConcentration (float)      :  the expected concentration of oil in the sample volume [uL/L]
      MinD (float)                          :  minimum resolvable diameter of the setup [um]. this would usually scale with the pixel size.
                                               synthesized particles smaller than this are also removed for speed purposes
    '''
    plt.close('all')
    pp = PdfPages(report_name)

    # image dimensions (fixed always for GC2450 camera)
    imx = 2448
    imy = 2048

    # get diameters and limits of size bins
    diams, bin_limits_um = scpp.get_size_bins()

    # initial volume distribution, close to Oystein's MPB paper in 2013
    vd = weibull(diams, n=d50)
    vd = vd/np.sum(vd)*TotalVolumeConcentration # scale the distribution according to concentration

    DropletVolume=((4/3)*np.pi*((diams*1e-6)/2)**3) # the volume of each droplet in m3
    nd=vd/(DropletVolume*1e9) # the number distribution in each bin
    nd[diams<MinD] = 0 # remove small particles for speed purposes

    # calculate the sample volume of the SilCam specified
    sv = scpp.get_sample_volume(PIX_SIZE, path_length=PATH_LENGTH, imx=imx, imy=imy)

    nd = nd*sv # scale the number distribution by the sample volume so resulting units are #/L/bin
    nc = int(sum(nd)) # calculate the total number concentration

    vd2 = scpp.vd_from_nd(nd,diams,sv) # convert the number distribution to volume distribution in uL/L/bin
    vc_initial = sum(vd2) # obtain the resulting concentration, now having remove small particles

    d50_theory = scpp.d50_from_vd(vd2, diams) # calculate the d50 in um

    plt.plot(diams, vd2, 'k', label='Initial')
    plt.plot(diams, vd, 'r:', label='Theoretical')
    plt.vlines(d50_theory, 0, max(vd2), linestyle='--')
    plt.xscale('log')
    plt.xlabel('ECD [um]')
    plt.xlabel('Volume distribution [uL/L/bin]')
    plt.legend()
    plt.title('Initial conditions:' +
             '\n\n' + str(nc) + ' particles per image volume' +
             '\n' + str(int(vc_initial)) + ' initial volume concentration [uL/L]' +
              '\n' + str(int(d50_theory)) + ' initial d50 [um]',
             horizontalalignment='left', loc='left')
    pp.savefig(bbox_inches='tight')

    nims = 40 # the number of images to simulate
    # preallocate variables
    log_vd = np.zeros((nims,len(diams)))
    cvd = np.zeros(nims)
    cd50 = np.zeros(nims)

    for I in range(nims):
        # randomly select a droplet radius from the input distribution
        rad = np.random.choice(diams/2, size=nc, p=nd/sum(nd)) / PIX_SIZE # radius is in pixels
        log_ecd = rad*2*PIX_SIZE # log this size as a diameter in um

        necd, edges = np.histogram(log_ecd,bin_limits_um) # count particles into number distribution
        log_vd[I,:] = scpp.vd_from_nd(necd,diams) # convert to volume distribution
        cvd[I] = np.sum(np.mean(log_vd[0:I,:],axis=0)) # calculated the cumulate volume distribution over image number
        cd50[I] = scpp.d50_from_vd(np.mean(log_vd,axis=0), diams) # calcualte the cumulate d50 over image number


    f, a = plt.subplots(1,3,figsize=(16,4))

    plt.sca(a[0])
    plt.plot(diams, vd2, 'k')
    plt.plot(diams, log_vd[0,:]/sv, alpha=0.5, label='1 image')
    plt.plot(diams, np.mean(log_vd[0:4,:], axis=0)/sv, alpha=0.5, label='4 images')
    plt.plot(diams, np.mean(log_vd, axis=0)/sv, alpha=0.5, label=(str(nims) + ' images'))
    plt.xscale('log')
    plt.vlines(d50_theory, 0, max(vd2), linestyle='--')
    plt.xlabel('ECD [um]')
    plt.ylabel('Volume distribution [uL/L/bin]')
    plt.legend()
    plt.title('Statistical summaries')

    plt.sca(a[1])
    plt.plot(cvd/sv,'k')
    plt.hlines(vc_initial, 0, nims, linestyle='--')
    plt.xlabel('Image number')
    plt.ylabel('Volume concentration [uL/L]')

    plt.sca(a[2])
    plt.plot(cd50,'k')
    plt.hlines(d50_theory, 0, nims, linestyle='--')
    plt.xlabel('Image number')
    plt.ylabel('d50 [um]')

    pp.savefig(bbox_inches='tight')

    # synthesize an image, returning the segmented image and the inputted volume distribution
    img, log_vd = synthesize(diams, bin_limits_um, nd, imx, imy, PIX_SIZE)

    plt.figure(figsize=(10,10))
    plt.imshow(img, vmin=0, vmax=255, extent=[0,imx*PIX_SIZE/1000,0,imy*PIX_SIZE/1000])
    plt.xlabel('[mm]')
    plt.ylabel('[mm]')
    plt.title('Synthetic image')
    pp.savefig(bbox_inches='tight')

    vd = np.zeros_like(log_vd)
    imbw = np.zeros_like(img[:,:,0])
    stat_extract_time = pd.Timedelta(seconds=0)
    # @todo this should be handles properly as part of testing
    try:
        diams, vd, imbw, stat_extract_time = test_analysis(img, PIX_SIZE, PATH_LENGTH, config_file=config_file)
    except:
        print('Analysis failed')
        pass


    f, a = plt.subplots(1,2,figsize=(20,8))

    plt.sca(a[0])
    plt.plot(diams, vd2, 'r:', label='Initial')
    plt.plot(diams, log_vd/sv ,'k', label='Statistical Best')
    plt.plot(diams, vd, 'g', alpha=0.5, label='PySilCam')
    plt.xscale('log')
    plt.xlabel('ECD [um]')
    plt.ylabel('Volume distribution [uL/L]')
    plt.legend()
    plt.title('Single image assessment:' +
              '\n\n' + 'Statextract took ' + str(stat_extract_time.seconds) + ' seconds',
             horizontalalignment='left', loc='left')

    plt.sca(a[1])
    plt.imshow(imbw, vmin=0, vmax=1, extent=[0,imx*PIX_SIZE/1000,0,imy*PIX_SIZE/1000], cmap='gray')
    plt.xlabel('[mm]')
    plt.ylabel('[mm]')
    plt.title('imbw')

    pp.savefig(bbox_inches='tight')

    pp.close()