def load_exc(ibw_folder='', pixels=64, scale=1, offset=1, verbose=False): """ Loads excitation files into a single .h5 file Parameters ---------- ibw_folder : string, optional The folder containing the excitation files to load pixels : int, optional How many pixels per line to divide the excitation ibw scale : float, optional The AC signal scaling, assuming the input excitation is wrong offset : float, optional The DC offset for the excitation """ if not any(ibw_folder): exc_file_path = usid.io_utils.file_dialog( caption='Select any file in destination folder', file_filter='IBW Files (*.ibw)') exc_file_path = '/'.join(exc_file_path.split('/')[:-1]) filelist = os.listdir(exc_file_path) data_files = [ os.path.join(exc_file_path, name) for name in filelist if name[-3:] == 'ibw' ] h5_path = os.path.join(exc_file_path, 'excitation') + '.h5' h5_file = h5py.File(h5_path, 'w') _line0 = loadibw(data_files[0])['wave']['wData'] _pix0 = np.split(_line0, pixels, axis=1)[0].mean(axis=1) _pix0 = scale * ((_pix0 - np.min(_pix0)) / (np.max(_line0) - np.min(_line0)) - 0.5) + offset data = h5_file.create_dataset('excitation', shape=(len(data_files), pixels, len(_pix0)), compression='gzip') for n, d in enumerate(data_files): if verbose: print('### Loading', d.split('/')[-1], '###') _line = loadibw(d)['wave']['wData'] for m, l in enumerate(np.split(_line, pixels, axis=1)): _pix = np.mean(l, axis=1) data[n, m, :] = _pix # self.h5_tfp = self.h5_results_grp.create_dataset('tfp', data=_arr, dtype=np.float32) return h5_path
def __init__(self, location): self.location = location # initialise experimental variables and data # self.spectra_long = loadibw(os.path.join(location, "spec2d.ibw"))['wave']['wData'].T self.wavelength_long = loadibw(os.path.join(location, "wavelength.ibw"))['wave']['wData'] self.step = np.linspace(0, self.spectra_long.shape[0], self.spectra_long.shape[0]) try: self.dual_pol = True self.spectra_trans = loadibw(os.path.join(location, "spec2d_t.ibw"))['wave']['wData'].T self.wavelength_trans = loadibw(os.path.join(location, "wavelength_t.ibw"))['wave']['wData'] except: self.dual_pol = False self.displacement = loadibw(os.path.join(location, "displacement.ibw"))['wave']['wData'] self.current = loadibw(os.path.join(location, "current.ibw"))['wave']['wData'] self.conductance = loadibw(os.path.join(location, "conductance.ibw"))['wave']['wData'] self.force_y = loadibw(os.path.join(location, "psd_y.ibw"))['wave']['wData'] self.force_x = loadibw(os.path.join(location, "psd_x.ibw"))['wave']['wData'] self.scan_n = int(os.path.basename(location).rsplit("_", 1)[1]) # add analysis variables # self.analysed = 0 self.stoc = 0 self.energy_long = np.array([]) if self.dual_pol: self.energy_trans = np.array([]) # scale data if necessary # self.scale_data() # analyse data # self.analyse_data()
def __init__(self, location): self.location = location # get alignment data # try: self.amplitude, self.x, self.y = load_itx('alignment_scan_fr.itx', location) self.phase, self.x, self.y = load_itx('alignment_scan_ftheta.itx', location) except IOError: raise IOError #self.amplitude = loadibw(os.path.join(location, "alignment_scan_fr.ibw"))['wave']['wData'].T #self.phase = loadibw(os.path.join(location, "alignment_scan_ftheta.ibw"))['wave']['wData'].T #self.x = loadibw(os.path.join(location, "wavelength.ibw"))['wave']['wData'] #self.y = 0 # get alignment variables # params = load_parameters(self.location) self.params = params self.set = int(params['alignment_set']) self.voltage = float(params['voltage']) self.position = float(params['init_pos_a']) self.time = params['time_stamp'] self.scan_n = int(os.path.basename(location).rsplit("_", 1)[1]) self.scan_size = 1000*float(params['scan_size']) self.scan_step = 1000*float(params['scan_step']) # analysis variables # self.amplitude_x0 = 0 self.amplitude_y0 = 0 self.amplitude_x_fwhm = 0 self.amplitude_y_fwhm = 0 self.phase_x0 = 0 self.phase_y0 = 0 self.phase_x_fwhm = 0 self.phase_y_fwhm = 0 # analysis arrays # # from igor - w_coef[0] = {z0, a0, x0, sigx, y0, sigy, corr} # self.amplitude_params = loadibw(os.path.join(location, 'fr_w_coef.ibw'))['wave']['wData'] self.amplitude_errors = loadibw(os.path.join(location, 'fr_w_sigma.ibw'))['wave']['wData'] self.amplitude_params = np.array([self.amplitude_params[1], self.amplitude_params[2], self.amplitude_params[4], self.amplitude_params[3], self.amplitude_params[5]]) self.amplitude_fit = gaussian(*self.amplitude_params) self.phase_params = loadibw(os.path.join(location, 'ftheta_w_coef.ibw'))['wave']['wData'] self.phase_errors = loadibw(os.path.join(location, 'ftheta_w_sigma.ibw'))['wave']['wData'] self.phase_params = np.array([self.phase_params[1], self.phase_params[2], self.phase_params[4], self.phase_params[3], self.phase_params[5]]) self.phase_fit = gaussian(*self.phase_params)
def load_tf(self, tf_path, excitation_path, remove_dc=False): ''' Process transfer function and broadband excitation from supplied file This function does not check shape or length ''' tf = loadibw(tf_path)['wave']['wData'] exc = loadibw(excitation_path)['wave']['wData'] self.tf = np.mean(tf, axis=1) self.TF = np.fft.fftshift(np.fft.fft(self.tf)) if remove_dc: self.TF[int(len(tf) / 2)] = 0 self.exc = np.mean(exc, axis=1) self.EXC = np.fft.fftshift(np.fft.fft(self.exc))
def load_parameters(location): parameters = loadibw(os.path.join(location, 'parameters.ibw'))['wave']['wData'] parameters = parameters.flatten() key, values = np.split(parameters, 2) params = {} for k, v in zip(key, values): params[k] = v return params
def signal(path, skiprows=1): """ Loads .ibw or ASCII files and return it as a numpy.ndarray. Parameters ---------- path : string Path to signal file. Returns ------- signal_array : (n_points, n_signals) array_like 2D real-valued signal array loaded from given .ibw file. """ # Get the path and check what the extension is. ext = splitext(path)[1] if ext.lower() == '.ibw': signal_array = loadibw(path)['wave']['wData'] # Load data. elif ext.lower() == '.txt': signal_array = loadtxt(path, skiprows=skiprows) else: print "Unrecognized file type!" sys.exit(0) signal_array.flags.writeable = True # Make array writable. return signal_array
def excitation_scale(self, exc_path, exc_params): """ Generates the excitation waveform based on the input ibw. Scaled to exc_params This process is to compensate for the Gage card having a limited input voltage range. :param exc_path: .ibw path containing the applied DDS excitation to the cantilever from the experiment :type exc_path: string :param exc_params: Specifies parameters for excitation waveform. Relevant keys are ac (in V), dc (in V), phase (in radians), and frequency (in Hz). The default is None, implying an excitation waveform of magnitude 1V, with period 1/drive_freq, and 0 DC offset. example : exc_params = {'ac': 3, 'dc': 3} for 3 Vdc and 3Vac excitation :type exc_params: dict """ exc_raw = loadibw(exc_path)['wave']['wData'].mean(axis=1) exc_raw *= 10 # resistor divider exc_raw = (exc_raw - exc_raw.min()) / (exc_raw.max() - exc_raw.min()) exc_raw = (exc_raw - 0.5) * 2 # scaled -1 to 1 exc_raw *= exc_params['ac'] exc_raw += exc_params['dc'] self.exc_wfm = exc_raw return
def load_pfmloop_from_binary(path, return_meta_data=False): """ loads data from binary file (from asylum research) into a numpy array Returns: dict({'label':(numpy array) imgdata} ---- path: str return_meta_data: bool - True returns (dict({'label':(numpy array) imgdata}, meta_data) meta_data (dict) -> {ScanLines:(str)... etc} The complete list of included keys in meta_data is given here: ['ScanSize', 'FastScanSize', 'SlowScanSize', 'ScanRate', 'XOffset', 'YOffset', 'PointsLines', 'ScanPoints', 'ScanLines', 'ScanAngle', 'ImagingMode', 'InvOLS', 'SpringConstant', 'AmpInvOLS', 'Amp2Invols', 'FastRatio', 'SlowRatio', 'TopLine', 'BottomLine', 'ScanMode', 'NapMode', 'FMapScanTime', 'FMapScanPoints', 'FMapScanLines', 'FMapXYVelocity', 'FMapBookWise', 'Channel1DataType', 'DataTypeSum', 'PhaseOffset', 'PhaseOffset1', 'NapPhaseOffset', 'VoltageParm', 'NapParms', 'PreScanSetting', 'OrcaOffset', 'OrcaOffset2', 'UserIn0Gain', 'UserIn0Offset', 'UserIn1Gain', 'UserIn1Offset', 'UserIn2Gain', 'UserIn2Offset', 'LateralGain', 'LateralOffset', 'OrcaGain', 'OrcaGain2', 'FastMapScanRate', 'FastMapZRate', 'Real Parms', 'Initial Parms', 'Initial ScanSize', 'Initial FastScanSize', 'Initial SlowScanSize', 'Initial ScanRate', 'ScanSpeed', 'Initial XOffset', 'Initial YOffset', 'Initial ScanPoints', 'Initial ScanLines', 'RoundFactor', 'IntegralGain', 'ProportionalGain', 'Initial ScanAngle', 'ScanAngleFactor', 'AmplitudeSetpointVolts', 'AmplitudeSetpointMeters', 'DriveAmplitude', 'DriveFrequency', 'SweepWidth', 'SlowScanEnabled', 'DeflectionSetpointVolts', 'DeflectionSetpointMeters', 'DeflectionSetpointNewtons', 'Initial ImagingMode', 'MaxScanSize', 'Initial InvOLS', 'Initial SpringConstant', 'DisplaySpringConstant', 'ScanStateChanged', 'ScanDown', 'XLVDTSens', 'YLVDTSens', 'ZLVDTSens', 'XLVDTOffset', 'YLVDTOffset', 'ZLVDTOffset', 'YIgain', 'YPgain', 'XIgain', 'XPgain', 'LastScan', 'XPiezoSens', 'YPiezoSens', 'ZPiezoSens', 'XDriveOffset', 'YDriveOffset', 'SweepPoints', 'SecretGain', 'YSgain', 'XSgain', 'DIsplayLVDTTraces', 'Initial PhaseOffset', 'BaseSuffix', 'SaveImage', 'ParmChange', 'ADCgain', 'OldADCgain', 'OldScanSize', 'OldYOffset', 'OldXOffset', 'ZIgain', 'ZPgain', 'ZSgain', 'Initial AmpInvOLS', 'UpdateCounter', 'DoMunge', 'XMungeAlpha', 'YMungeAlpha', 'ZMungeAlpha', 'StartHeadTemp', 'StartScannerTemp', 'Has1xACDeflGain', 'DontChangeXPT', 'LowNoise', 'ScreenRatio', 'XDriftRate', 'YDriftRate', 'XDriftTotal', 'YDriftTotal', 'DriftBIts', 'DriftCount', 'Setpoint', 'Initial FastRatio', 'Initial SlowRatio', 'Initial TopLine', 'Initial BottomLine', 'ScanStatus', 'Is1DPlus', 'DelayUpdate', 'MarkerRatio', 'StartLineCount', 'OldAmplitudeSetpointVolts', 'OldDeflectionSetPointVolts', 'Initial ScanMode', 'Interpolate', 'TipVoltage', 'SurfaceVoltage', 'FreqIgain', 'FreqPgain', 'FreqSgain', 'Initial OrcaGain', 'FreqGainOn', 'Initial UserIn0Gain', 'Initial UserIn1Gain', 'Initial UserIn2Gain', 'Initial LateralGain', 'IsBipolar', 'FrequencyHack', 'MagneticField', 'DriveGainOn', 'DriveIGain', 'DrivePGain', 'DriveSGain', 'Initial UserIn0Offset', 'Initial UserIn1Offset', 'Initial UserIn2Offset', 'Initial LateralOffset', 'LastImage', 'ZoomSize', 'ZoomXOffset', 'ZoomYOffset', 'User0Voltage', 'User1Voltage', 'ExtendedZ', 'DriveAmplitude1', 'DriveFrequency1', 'SweepWidth1', 'Initial PhaseOffset1', 'Initial Amp2InvOLS', 'Initial VoltageParm', 'MicroscopeID', 'CapacitanceSens', 'CapacitanceOffset', 'CapPhaseOffset', 'TipBiasOffset', 'TipHeaterOffset', 'SurfaceBiasOffset', 'UseCantHolder', 'CurrentCantHolder', 'HasClickRing', 'XScanDirection', 'YScanDirection', 'SaveImageCount', 'SaveImageLines', 'Initial OrcaGain2', 'UpdateSlowWave', 'FBFilterBW', 'CurrentSetpointAmps', 'CurrentSetpointVolts', 'OldCurrentSetpointVolts', 'OldCurrentSetpointAmps', 'HasFM', 'LastScanWithdraw', 'HasLaserRelay', 'ToggleLaserRelay', 'Decimation', 'DARTIGain', 'DARTPGain', 'SampleHolder', 'ManualSampleHolder', 'CypherXPTLock', 'XPTLock', 'LogFeedback', 'ARSysScanBusy', 'SimpleControls', 'Initial PointsLines', 'FreeAirAmplitude', 'FreeAirPhase', 'FreeAirDeflection', 'FreeAirDriveAmplitude', 'ContinualRetune', 'ForceFilter', 'TemperatureSens', 'TemperatureOffset', 'OffsetBehavior', 'InputRange', 'XLVDTSensSlope', 'YLVDTSensSlope', 'XLVDTSensIntercept', 'YLVDTSensIntercept', 'HaveWeKilledTheProgressBar', 'Initial PreScanSetting', 'ImageFrameTime', 'FBFilterSelectivity', 'HasDriveChoke', 'DriveChokeOn', 'CFCWFOS', 'SkewAngle', 'ContinualRetuneTime', 'DRTimeStamp', 'CRTimeStamp', 'Cypher15VPower', 'HasBlueDrive', 'BlueDriveOn', 'blueDriveOffset', 'blueDriveMaxAmplitude', 'bDDriveAmplitude', 'bDDriveAmplitude1', 'bDDiffEfficiencyV', 'BackPackIn0Gain', 'BackPackIn0Offset', 'BackPackIn1Gain', 'BackPackIn1Offset', 'BackPackIn2Gain', 'BackPackIn2Offset', 'BackPackIn3Gain', 'BackPackIn3Offset', 'BackPackIn4Gain', 'BackPackIn4Offset', 'bdReCalibrateTime', 'bdMotorError', 'ScanModeGUI', 'FastMapSetpointVolts', 'FastMapSetpointNewtons', 'OldFastMapSetpointVolts', 'OldFastMapSetpointNewtons', 'Initial FastMapZRate', 'FastMapAmplitude', 'FastMapFBMethod', 'FastMapFBPhase', 'FastMapFBWindow', 'FastMapAmpSetpointVolts', 'FastMapAmpSetpointMeters', 'FastMapIndex', 'QueueProgress', 'QueueEstimate', 'QueueExpand', 'FastMapIGain', 'Initial FastMapScanRate', 'FastMapBaseLine', 'blueThermOn', 'FastMapScanPoints', 'FastMapScanLines', 'FastMapOptScanPoints', 'FastMapOptScanLines', 'FreqDGain', 'DriveDGain', 'ImageSaveExpand', 'Saturated', 'FrameCount', 'SinusoidalOn', 'StartHeaterTemp', 'StartHeaterHumidity', 'MicroscopeModel', 'BlueDriveDissipationInWatts', 'NapIntegralGain', 'NapProportionalGain', 'NapDeflectionSetpointVolts', 'NapAmplitudeSetpointVolts', 'NapDissipationSetpointVolts', 'NapFrequencySetPointHz', 'NapCurrentSetpointAmps', 'NapDriveAmplitude', 'NapDriveFrequency', 'NapDriveAmplitude1', 'NapDriveFrequency1', 'NapTipVoltage', 'NapSurfaceVoltage', 'NapUser0Voltage', 'NapUser1Voltage', 'NapHeight', 'NapStartHeight', 'NapTime', 'PotentialIGain', 'PotentialPGain', 'PotentialGainOn', 'ElectricTune', 'NapCurrentSetpointVolts', 'PotentialLoopLimit', 'ClosedNap', 'NapZIGain', 'NapZPGain', 'AutoNapZGain', 'bDNapDriveAmplitude', 'bDNapDriveAmplitude1', 'Channel2DataType', 'Channel3DataType', 'Channel4DataType', 'Channel5DataType', 'Channel6DataType', 'Channel7DataType', 'Channel8DataType', 'UserCalcFunc', 'UserCalcBFunc', 'FastMap1DataType', 'FastMap2DataType', 'FastMap3DataType', 'FastMap4DataType', 'FastMapCapture', 'InA', 'InB', 'InFast', 'InAOffset', 'InBOffset', 'InFastOffset', 'OutXMod', 'OutYMod', 'OutZMod', 'FilterIn', 'BNCOut0', 'BNCOut1', 'BNCOut2', 'PogoOut', 'Chip', 'Shake', 'Input.Z.Filter.Freq', 'Input.X.Filter.Freq', 'Input.Y.Filter.Freq', 'Input.A.Filter.Freq', 'Input.B.Filter.Freq', 'Input.Fast.Filter.Freq', 'Lockin.0.Filter.Freq', 'Lockin.1.Filter.Freq', 'Sample Rate', 'ThermalDC', 'ThermalQ', 'ThermalFrequency', 'ThermalWhiteNoise', 'ScaleLog', 'FitWidth', 'ThermalSamples', 'ThermalCounter', 'SectionSamples', 'SectionCounter', 'DoThermal', 'ThermalResolution', 'ThermalZoom', 'DoCantTune', 'ZoomCounter', 'AutoTuneLow', 'AutoTuneHigh', 'TargetVoltage', 'TargetPercent', 'CheckTuneTraces', 'ButtonTime', 'ShowThermalFit', 'AppendThermalBit', 'TuneQ', 'TuneGain', 'TunePeakResult', 'TuneFreqResult', 'TuneQResult', 'ThermalSamplesLimit', 'TuneFeedback', 'TuneDDSOutput', 'TipVoltCenter', 'TipVoltWidth', 'ThermalFrequencyRange', 'AutoTuneLimit', 'AutoTuneLow1', 'AutoTuneHigh1', 'TargetVoltage1', 'TargetPercent1', 'DualACMode', 'WhichACMode', 'BackwardsTune', 'TuneCaptureRate', 'TuneTime', 'TuneFilter', 'iDriveOn', 'FrequencyRatio', 'DFRTFrequencyCenter', 'DFRTFrequencyWidth', 'DFRTOn', 'ThermalCenter', 'ThermalWidth', 'DFWMAMT', 'LastXPos', 'LastYPos', 'PFMFrequencyLimit', 'TuneLockin', 'TipHeaterDrive', 'AdjustSpringConstant', 'DrawThermalFit', 'LateralTune', 'ThermalTemperature', 'UseCypherThermal', 'UseCypherMultiThread', 'Illumination', 'ARCZ', 'TuneAngle', 'IsDefaultFrequency', 'TargetAmplitude', 'TargetPhase', 'LossTanAmp1', 'LossTanPhase1', 'LossTanAmp2', 'LossTanPhase2', 'LossTanFreq1', 'LossTanFreq2', 'LossTanQ1', 'LossTanQ2', 'SecondFrequency', 'TryFitAgain', 'HighFrequencyMode', 'ThermalLever', 'DoSader', 'CustomLeverLength', 'CustomLeverWidth', 'CustomLeverFrequency', 'ResFreq1', 'ResFreq2', 'GetStartedRoughness', 'GetStartedOn', 'GSGainGain', 'GSSetpointPercent', 'GSHardness', 'GSLeverRange', 'GetStartedMorePanel', 'GSUseManualThermal', 'GSMotorHeight', 'GSStickySample', 'GSDateTime', 'YourVariablesStartHere', 'DARTAnalysisImage', 'DARTAmplitude1Label', 'DARTAmplitude2Label', 'DARTPhase1Label', 'DARTPhase2Label', 'DARTFrequency1Label', 'Log File', 'Date', 'Time', 'Seconds', 'UserCalcUnit', 'UserIn0Unit', 'UserIn1Unit', 'UserIn2Unit', 'LateralUnit', 'ARUserPanelName', 'UserIn0Name', 'UserIn1Name', 'UserIn2Name', 'UserCalcName', 'UserIn0Ab', 'UserIn1Ab', 'UserIn2Ab', 'UserCalcAb', 'UserIn0Force', 'UserIn1Force', 'UserIn2Force', 'UserCalcForce', 'SaveForce', 'LastSaveImage', 'LastSaveForce', 'NavLoadPath', 'LastNavLoadPath', 'UserCalcBUnit', 'UserCalcBName', 'UserCalcBForce', 'UserCalcBAb', 'BackPackIn0Unit', 'BackPackIn0Name', 'BackPackIn0Ab', 'BackPackIn0Force', 'BackPackIn1Unit', 'BackPackIn1Name', 'BackPackIn1Ab', 'BackPackIn1Force', 'BackPackIn2Unit', 'BackPackIn2Name', 'BackPackIn2Ab', 'BackPackIn2Force', 'BackPackIn3Unit', 'BackPackIn3Name', 'BackPackIn3Ab', 'BackPackIn3Force', 'BackPackIn4Unit', 'BackPackIn4Name', 'BackPackIn4Ab', 'BackPackIn4Force', 'DetectorSum', 'XSensor', 'YSensor', 'ZSensor', 'DDSAmplitude0', 'DDSDCOffset0', 'DDSFrequency0', 'DDSFrequencyOffset0', 'DDSPhaseOffset0', 'DDSAmplitude1', 'DDSFrequency1', 'DDSPhaseOffset1', 'Amplitude', 'Phase', 'Inputi', 'Inputq', 'Inputi1', 'Inputq1', 'Count', 'Count2', 'Potential', 'Amplitude1', 'Phase1', 'DDSQGain0', 'DDSQAngle0', 'DDSFrequencyOffset1', 'Deflection', 'Lateral', 'Frequency', 'LockIn', 'Height', 'DeflectionValue', 'TipBias', 'DartAmp', 'VerDate', 'Version', 'XopVersion', 'OSVersion', 'IgorFileVersion', 'BaseName', 'SkewAngleRead', 'ImageNote', 'TipSerialNumber', 'Planefit 0', 'PlanefitOrder 0', 'FlattenOrder 0', 'Planefit Offset 0', 'Planefit X Slope 0', 'Planefit Y Slope 0', 'Flatten Offsets 0', 'Flatten Slopes 0', 'Display Offset 0', 'Display Range 0', 'ColorMap 0', 'Planefit 1', 'PlanefitOrder 1', 'FlattenOrder 1', 'Planefit Offset 1', 'Planefit X Slope 1', 'Planefit Y Slope 1', 'Display Offset 1', 'Display Range 1', 'ColorMap 1', 'Planefit 2', 'PlanefitOrder 2', 'FlattenOrder 2', 'Planefit Offset 2', 'Planefit X Slope 2', 'Planefit Y Slope 2', 'Display Offset 2', 'Display Range 2', 'ColorMap 2', 'Planefit 3', 'PlanefitOrder 3', 'FlattenOrder 3', 'Planefit Offset 3', 'Planefit X Slope 3', 'Planefit Y Slope 3', 'Display Offset 3', 'Display Range 3', 'ColorMap 3', 'Planefit 4', 'PlanefitOrder 4', 'FlattenOrder 4', 'Planefit Offset 4', 'Planefit X Slope 4', 'Planefit Y Slope 4', 'Display Offset 4', 'Display Range 4', 'ColorMap 4', 'Planefit 5', 'PlanefitOrder 5', 'FlattenOrder 5', 'Planefit Offset 5', 'Planefit X Slope 5', 'Planefit Y Slope 5', 'Display Offset 5', 'Display Range 5', 'ColorMap 5', 'EndHeadTemp', 'EndScannerTemp', 'EndHeaterTemp', 'EndHeaterHumidity'] """ data = loadibw(path) list_of_metadata = str(data['wave']['note']).replace("b'", "").split( '\\r') #clean up binary meta_data = dict() for x in list_of_metadata: spl = x.split(': ') try: meta_data.update({'{}'.format(spl[0]): spl[1]}) except IndexError: try: spl = x.split(':') meta_data.update({'{}'.format(spl[0]): spl[1]}) except: pass for x in data['wave']['labels']: if len(x) > 1: labels = x[1:] labels = [ str(label).replace("b'", "").replace("'", "") for label in labels ] out = dict() for ijk, label in enumerate(labels): try: imgdata = data['wave']['wData'][:, ijk] except IndexError: raise IndexError( 'label count does not match data count. i.e. imgdata does not have data for each label (is this file a pfm loop??)' ) out.update({label: imgdata}) if return_meta_data: return out, meta_data else: return out
def load_image_from_binary(path, return_meta_data=True): """ Loads data from binary file (from asylum research) into a dict of numpy arrays. args: path (str): Path to the data. return_meta_data (bool): Return meta data, i.e. scan size etc. returns: (dict): Key labels image type, value is numpy array of img data. """ data = loadibw(path) list_of_metadata = str(data['wave']['note']).replace("b'", "").split( '\\r') #clean up binary meta_data = dict() for x in list_of_metadata: spl = x.split(': ') try: meta_data.update({'{}'.format(spl[0]): spl[1]}) except IndexError: try: spl = x.split(':') meta_data.update({'{}'.format(spl[0]): spl[1]}) except: pass for x in data['wave']['labels']: if len(x) > 1: labels = x[1:] labels = [ str(label).replace("b'", "").replace("'", "") for label in labels ] out = dict() for ijk, label in enumerate(labels): try: imgdata = data['wave']['wData'][:, :, ijk] except IndexError: raise IndexError( 'label count does not match data count. i.e. imgdata does not have data for each label (is this file a pfm loop??)' ) out.update({label: imgdata}) #out = pd.DataFrame(out, index = [0]) if return_meta_data: return out, meta_data else: return out
def __init__(self, parent, instance): # initialise experimental variables and data # self.instance = instance self.parent = parent self.location = os.path.join(parent, "time_resolved_data") self.scan_n = os.path.basename(parent).rsplit("_", 1)[1] self.spectra_long = loadibw( os.path.join(self.location, "qc_spec_" + instance + ".ibw"))['wave']['wData'].T self.wavelength_long = loadibw( os.path.join(self.location, "qc_spec_" + instance + "_wavelength.ibw"))['wave']['wData'] self.spectra_time = loadibw( os.path.join(self.location, "qc_spec_" + instance + "_time.ibw"))['wave']['wData'] self.spectra_time = self.spectra_time[:-6] self.current = loadibw( os.path.join(self.location, "qc_trace_" + instance + ".ibw"))['wave']['wData'] self.conductance = loadibw( os.path.join(self.location, "qcg_trace_" + instance + ".ibw"))['wave']['wData'] self.force_y = loadibw( os.path.join(self.location, "qc_force_" + instance + ".ibw"))['wave']['wData'] self.dso_time = np.linspace(0, 20e-3, len(self.conductance)) # add analysis variables # self.energy_long = np.array([]) # scale data if necessary # self.scale_data()
def __init__(self, location): self.location = location # initialise experimental variables and data # self.spectra_long = loadibw(os.path.join( location, "spec2d.ibw"))['wave']['wData'].T self.wavelength_long = loadibw(os.path.join( location, "wavelength.ibw"))['wave']['wData'] self.step = np.linspace(0, self.spectra_long.shape[0], self.spectra_long.shape[0]) try: self.dual_pol = True self.spectra_trans = loadibw(os.path.join( location, "spec2d_t.ibw"))['wave']['wData'].T self.wavelength_trans = loadibw( os.path.join(location, "wavelength_t.ibw"))['wave']['wData'] except: self.dual_pol = False self.displacement = loadibw(os.path.join( location, "displacement.ibw"))['wave']['wData'] self.current = loadibw(os.path.join(location, "current.ibw"))['wave']['wData'] self.conductance = loadibw(os.path.join( location, "conductance.ibw"))['wave']['wData'] self.force_y = loadibw(os.path.join(location, "psd_y.ibw"))['wave']['wData'] self.force_x = loadibw(os.path.join(location, "psd_x.ibw"))['wave']['wData'] self.scan_n = int(os.path.basename(location).rsplit("_", 1)[1]) # add analysis variables # self.analysed = 0 self.stoc = 0 self.energy_long = np.array([]) if self.dual_pol: self.energy_trans = np.array([]) # scale data if necessary # self.scale_data() # analyse data # self.analyse_data()
def excitation_phase(self, exc_path, exc_params={}, phase_range=[-pi, pi]): """ Generates the excitation waveform based on the input ibw. Calculates phase and runs self.excitation until they match. This process is to compensate for the Gage card having a limited input voltage range. Returns ------- self.exc_wfm :param exc_path: .ibw path containing the applied DDS excitation to the cantilever from the experiment :type exc_path: string :param exc_params: Specifies parameters for excitation waveform. Relevant keys are ac (in V), dc (in V), phase (in radians), and frequency (in Hz). The default is None, implying an excitation waveform of magnitude 1V, with period 1/drive_freq, and 0 DC offset. :type exc_params: dict, optional :param phase_range: The start and stop phases to check :type phase_range: list, shape 2, optional """ phase_test = np.arange(phase_range[0], phase_range[1], 0.1) exc_raw = loadibw(exc_path)['wave']['wData'] exc_raw = exc_raw[:, 10] # pick a random slice for p in phase_test: self.excitation(exc_params, p) _pke = np.argmax(self.exc_wfm[:50:1]) _pki = np.argmax(exc_raw[:50:1]) if _pke == _pki: print('Done matching phase', p) plt.figure() plt.plot(self.exc_wfm[:50], 'r') plt.plot(exc_raw[:50] * 100, 'b') break return
def ibw2dict(filename): """Extract the contents of an *ibw to a dict""" data = loadibw(filename) wave = data['wave'] wave_h = wave['wave_header'] dim = wave_h['nDim'][0:2] scale_values = wave_h['sfA'][0:2] start_values = wave_h['sfB'][0:2] end_values = start_values + np.multiply(dim, scale_values) # Get the labels and tidy them up into a list labels = list(map(bytes.decode, flatten(wave['labels']))) # Get the notes and process them into a dict notes = process_notes(wave['note']) # Get the data numpy array and convert to a simple list and then to a numpy array properly shaped Data = np.nan_to_num(wave['wData']).tolist() wData = np.array(Data).reshape(dim[0], dim[1]) E_axis = np.linspace(start_values[0], end_values[0], dim[0]) A_axis = np.linspace(start_values[1], end_values[1], dim[1]) # Get the filename from the file - warn if it differs fname = wave['wave_header']['bname'].decode() input_fname = os.path.splitext(os.path.basename(filename))[0] if input_fname != fname: print("Warning: stored filename differs from input file name") print("Input filename: {}".format(input_fname)) print("Stored filename: {}".format(str(fname) + " (.ibw)")) return { "filename": fname, "dimensions": dim, "E_axis": E_axis, "A_axis": A_axis, "labels": labels, "notes": notes, "data": wData }
def ibw2dict(filename): """Extract the contents of an *ibw to a dict""" data = loadibw(filename) wave = data['wave'] # Get the labels and tidy them up into a list labels = list(map(bytes.decode, util.flatten(wave['labels']))) # Get the notes and process them into a dict notes = util.process_notes(wave['note']) # Get the data numpy array and convert to a simple list wData = np.nan_to_num(wave['wData']).tolist() # Get the filename from the file - warn if it differs fname = wave['wave_header']['bname'].decode() input_fname = os.path.splitext(os.path.basename(filename))[0] if input_fname != fname: print("Warning: stored filename differs from input file name") print("Input filename: {}".format(input_fname)) print("Stored filename: {}".format(str(fname) + " (.ibw)")) return {"filename": fname, "labels": labels, "notes": notes, "data": wData}
def signal(path, skiprows=0): """ Loads .ibw or ASCII files and return it as a numpy.ndarray. :param path: Path to signal file. :type path: string :param skiprows: :type skiprows: int, optional :returns: 2D real-valued signal array loaded from given .ibw file. :rtype: (n_points, n_signals) array_like """ # Get the path and check what the extension is. ext = splitext(path)[1] if ext.lower() == '.ibw': signal_array = loadibw(path)['wave']['wData'] # Load data. elif ext.lower() == '.txt': signal_array = loadtxt(path, skiprows=skiprows) else: print("Unrecognized file type!") sys.exit(0) try: signal_array.flags.writeable = True # Make array writable. except: pass return signal_array
def __init__(self, parent, instance): # initialise experimental variables and data # self.instance = instance self.parent = parent self.location = os.path.join(parent, "time_resolved_data") self.scan_n = os.path.basename(parent).rsplit("_", 1)[1] self.spectra_long = loadibw(os.path.join(self.location, "qc_spec_"+instance+".ibw"))['wave']['wData'].T self.wavelength_long = loadibw(os.path.join(self.location, "qc_spec_"+instance+"_wavelength.ibw"))['wave']['wData'] self.spectra_time = loadibw(os.path.join(self.location, "qc_spec_"+instance+"_time.ibw"))['wave']['wData'] self.spectra_time = self.spectra_time[:-6] self.current = loadibw(os.path.join(self.location, "qc_trace_"+instance+".ibw"))['wave']['wData'] self.conductance = loadibw(os.path.join(self.location, "qcg_trace_"+instance+".ibw"))['wave']['wData'] self.force_y = loadibw(os.path.join(self.location, "qc_force_"+instance+".ibw"))['wave']['wData'] self.dso_time = np.linspace(0, 20e-3, len(self.conductance)) # add analysis variables # self.energy_long = np.array([]) # scale data if necessary # self.scale_data()
def AutoDetect(FileName, Opt): """ Attempt to autodetect the instrument used to collect the image Currently supports the Zeiss Merlin V0.2 0.1 - Orig 0.2 - Asylum AFM added """ if Opt.FExt == ".ibw": # file is igor if Opt.Machine != "Asylum AFM": Opt.Machine = "Asylum AFM" # avoid race condition in parallel loop RawData = loadibw(FileName)['wave'] Labels = RawData['labels'][2] Labels = [i.decode("utf-8") for i in Labels] # make it strings # Need to add a selector here for future height/phase AFMIndex = [i for i, s in enumerate(Labels) if Opt.AFMLayer in s] #they index from 1???? AFMIndex = AFMIndex[0] - 1 # fix that quick imarray = RawData['wData'][:, :, AFMIndex] #slow scan is column in original data # AFM data has to be leveled :( TArray = imarray.transpose( ) # necessary so that slow scan Y and fast scan is X EG afm tip goes along row > < then down to next row etc if Opt.AFMLevel == 1: #median leveling MeanSlow = imarray.mean( axis=0) # this calculates the mean of each slow scan row Mean = imarray.mean() # mean of everything MeanOffset = MeanSlow - Mean # determine the offsets imfit = imarray - MeanOffset # adjust the image elif Opt.AFMLevel == 2: # median of dif leveling DMean = np.diff(TArray, axis=0).mean(axis=1) # calc the 1st order diff from one row to next. Then average these differences DMean = np.insert( DMean, 0, 0) # the first row we don't want to adjust so pop in a 0 imfit = imarray - DMean elif Opt.AFMLevel == 3: # Polynomial leveling imfit = np.zeros(imarray.shape) FastInd = np.arange(imarray.shape[0]) # this is 0 - N rows for SlowInd in np.arange( imarray.shape[1]): # for each column eg slowscan axis Slow = imarray[:, SlowInd] PCoef = np.polyfit(FastInd, Slow, Opt.AFMPDeg) POffset = np.polyval(PCoef, FastInd) imfit[:, SlowInd] = imarray[:, SlowInd] - POffset else: imfit = imarray #Brightness/Contrast RESET needed for denoising. Need to figure out how to keep track of this? add an opt? # imfit = imfit - imfit.min() # imfit = imfit*255/imfit.max() if Opt.NmPP != RawData['wave_header']['sfA'][0] * 1e9: Opt.NmPP = RawData['wave_header']['sfA'][ 0] * 1e9 # hopefully avoid issues with parallel RawData.clear() imarray = imfit else: im = Image.open(FileName) if im.mode != "P": im = im.convert(mode='P') print( "Image was not in the original format, and has been converted back to grayscale. Consider using the original image." ) imarray = np.array(im) SkimFile = open(FileName, 'rb') MetaF = exifread.process_file(SkimFile) SkimFile.close() try: Opt.FInfo = str(MetaF['Image Tag 0x8546'].values) Opt.NmPP = float(Opt.FInfo[17:30]) * 10**9 Opt.Machine = "Merlin" except: pass # if Opt.NmPP!=0: # print("Instrument was autodetected as %s, NmPP is %f \n" % (Opt.Machine ,Opt.NmPP) ) # else: # print("Instrument was not detected, and NmPP was not set. Please set NmPP and rerun") return (imarray)
def __init__(self, file_path): with OpenFromAny(file_path, 'rb') as f: file = loadibw(f) if file['version'] != 5: raise RuntimeError('Only IBW version 5 is supported!') self.data = file['wave'] # the first two labels are of x and y axis. we cannot read those self._channel_names = [channel.decode() for channel in self.data['labels'][2][1:]] self._default_channel = 0 # # Read physical sizes from file, since all data # has already been loaded, we can calculate it here # height_data = self.data['wData'] # TODO is it always like this? assert len(height_data.shape) == 3, \ "We expect all channels being coded in to one wave and all are " \ "2D. This is not true somehow, cannot proceed." nx, ny, num_channels = height_data.shape # ensure that there are not too many channel names self._channel_names = self._channel_names[:num_channels] # add channel names for all channels without name no_name_idx = 1 while len(self._channel_names) < num_channels: self._channel_names.append("no name ({})".format(no_name_idx)) no_name_idx += 1 # # Decode units # def decode_unit_entry(u): return u.tobytes().partition(b'\0')[0].decode('latin-1') data_unit = decode_unit_entry(self.data['wave_header']['dataUnits']) x_unit = decode_unit_entry(self.data['wave_header']['dimUnits'][0]) y_unit = decode_unit_entry(self.data['wave_header']['dimUnits'][1]) # the following is not necessary, we could handle different units by # rescaling, however I'll leave it like this for now, print some # message so we know what to do if a file occurs which does not fulfill # this assumption assert data_unit == x_unit == y_unit, \ "So far, data units and dimension units must be all the same. " +\ "data unit: '{}', x unit: '{}', y unit: '{}'".format(data_unit, x_unit, y_unit) # An empty unit should be None if data_unit == '': data_unit = None self._data_unit = data_unit # # Decode sizes # sfA = self.data['wave_header']['sfA'] self._physical_sizes = (nx * sfA[0], ny * sfA[1]) # Comment in C header file on these fields: Index value for element e # of dimension d = sfA[d]*e + sfB[d]. sfB is left out here, because we # are interested in the width and height, not the absolute offsets. # # Build channel information # self._channels = [ ChannelInfo(self, i, name=cn, dim=2, nb_grid_pts=(nx, ny), physical_sizes=self._physical_sizes, unit=self._data_unit, height_scale_factor=1) for i, cn in enumerate(self._channel_names)]
def ibw2stdout(filename): '''Dump the contents of an *.ibw to stdout''' data = loadibw(filename) util.pprint(data)
def load_tf(self, tf_path, tf_excitation_path=[], remove_dc=False, adjust_tf_length=False): ''' Process transfer function and broadband excitation from supplied file This function does not check shape or length If no tf_excitation_path is provided, this will generate one via SciPy chirp :param tf_path: :type tf_path: str :param tf_excitation_path: :type tf_excitation_path: list :param remove_dc: Removes the DC peak from the FFT :type remove_dc: bool, optional :param adjust_tf_length: :type adjust_tf_length: bool, optional ''' # Load the response if isinstance(tf_path, str): tf = loadibw(tf_path)['wave']['wData'] else: tf = tf_path self.tf = tf if len(tf.shape) > 1: self.tf = np.mean(tf, axis=1) # Load the broadband excitation file, or create one if tf_excitation_path: if isinstance(tf_excitation_path, str): tf_exc = loadibw(tf_excitation_path)['wave']['wData'] else: tf_exc = tf_excitation_path else: tf_exc = gen_chirp(sampling_rate=self.sampling_rate, length=self.tf.shape / self.sampling_rate) if remove_dc: self.TF[int(len(tf) / 2)] = 0 self.tf_exc = tf_exc if len(tf_exc.shape) > 1: self.tf_exc = np.mean(tf_exc, axis=1) if adjust_tf_length: if self.n_points > len(self.tf): self.tf = np.pad(self.tf, (0, self.n_points - len(self.tf))) elif self.n_points < len(self.tf): self.tf = self.tf[:self.n_points] self.TF = np.fft.fftshift(np.fft.fft(self.tf)) self.TF_EXC = np.fft.fftshift(np.fft.fft(self.tf_exc)) self.tf_f_ax = np.linspace(-self.sampling_rate / 2, self.sampling_rate / 2, num=self.tf.shape[0])
def load_ringdown(data_files, parm_dict, h5_path, verbose=False, loadverbose=True, average=True, mirror=False): """ Generates the HDF5 file given path to files_list and parameters dictionary Creates a Datagroup FFtrEFM_Group with a single dataset in chunks Parameters ---------- data_files : list List of the \*.ibw files to be invidually scanned parm_dict : dict Scan parameters to be saved as attributes h5_path : string Path to H5 file on disk verbose : bool, optional Display outputs of each function or not loadverbose : Boolean (optional) Whether to print any simple "loading Line X" statements for feedback mirror : bool, optional Flips the ibw signal if acquired during a retrace, so data match the topography pixel-to-pixel Returns ------- h5_path: str The filename path to the H5 file created """ # e.g. if a 16000 point signal with 2000 averages and 10 pixels # (10MHz sampling of a 1.6 ms long signal=16000, 200 averages per pixel) # parm_dict['pnts_per_pixel'] = 200 (# signals at each pixel) # ['pnts_per_avg'] = 16000 (# pnts per signal, called an "average") # ['pnts_per_line'] = 2000 (# signals in each line) num_rows = parm_dict['num_rows'] num_cols = parm_dict['num_cols'] # The signals are hard-coded in the AFM software as 800 points long # Therefore, we can calculate pnts_per_pixel etc from the first file signal = loadibw(data_files[0])['wave']['wData'] # Load data. parm_dict['pnts_per_pixel'] = int(signal.shape[0] / (800 * num_cols)) parm_dict['pnts_per_avg'] = 800 # hard-coded in our AFM software parm_dict['total_time'] = 16e-3 # hard-coded in our AFM software if 'AMPINVOLS' not in parm_dict: parm_dict.update({'AMPINVOLS': 100e-9}) pnts_per_avg = parm_dict['pnts_per_avg'] orig_pnts_per_pixel = parm_dict['pnts_per_pixel'] if average: parm_dict['pnts_per_pixel'] = 1 parm_dict['pnts_per_line'] = num_cols pnts_per_pixel = parm_dict['pnts_per_pixel'] pnts_per_line = parm_dict['pnts_per_line'] hdf = h5py.File(h5_path) try: rd_group = hdf.file.create_group('RD_Group') except: rd_group = usid.hdf_utils.create_indexed_group(hdf.file['/'], 'RD_Group') pos_desc = [Dimension('X', 'm', np.linspace(0, parm_dict['FastScanSize'], num_cols * pnts_per_pixel)), Dimension('Y', 'm', np.linspace(0, parm_dict['SlowScanSize'], num_rows))] ds_pos_ind, ds_pos_val = build_ind_val_dsets(pos_desc, is_spectral=False, verbose=verbose) spec_desc = [Dimension('Time', 's', np.linspace(0, parm_dict['total_time'], pnts_per_avg))] ds_spec_inds, ds_spec_vals = build_ind_val_dsets(spec_desc, is_spectral=True) for p in parm_dict: rd_group.attrs[p] = parm_dict[p] rd_group.attrs['pnts_per_line'] = num_cols # to change number of pnts in a line h5_rd = usid.hdf_utils.write_main_dataset(rd_group, # parent HDF5 group (num_rows * num_cols * pnts_per_pixel, pnts_per_avg), # shape of Main dataset 'Ringdown', # Name of main dataset 'Amplitude', # Physical quantity contained in Main dataset 'nm', # Units for the physical quantity pos_desc, # Position dimensions spec_desc, # Spectroscopic dimensions dtype=np.float32, # data type / precision compression='gzip', main_dset_attrs=parm_dict) # Cycles through the remaining files. This takes a while (~few minutes) for k, num in zip(data_files, np.arange(0, len(data_files))): if loadverbose: fname = k.replace('/', '\\') print('####', fname.split('\\')[-1], '####') fname = str(num).rjust(4, '0') signal = loadibw(k)['wave']['wData'] signal = np.reshape(signal.T, [num_cols * orig_pnts_per_pixel, pnts_per_avg]) if average: pixels = np.split(signal, num_cols, axis=0) signal = np.vstack([np.mean(p, axis=0) for p in pixels]) signal *= parm_dict['AMPINVOLS'] if mirror: h5_rd[num_cols * pnts_per_pixel * num: num_cols * pnts_per_pixel * (num + 1), :] = np.flipud(signal[:, :]) else: h5_rd[num_cols * pnts_per_pixel * num: num_cols * pnts_per_pixel * (num + 1), :] = signal[:, :] if verbose == True: usid.hdf_utils.print_tree(hdf.file, rel_paths=True) return h5_rd
from igor.record.folder import FolderStartRecord, FolderEndRecord from igor.record.variables import VariablesRecord from igor.record.wave import WaveRecord import glob import matplotlib import matplotlib.pyplot as plt fig1 = plt.figure(figsize=(12, 6), dpi=80) curr = fig1.add_subplot(111) fig2 = plt.figure(figsize=(12, 6), dpi=80) volt = fig2.add_subplot(111) filename = 'B95_Ch0_IDRest_107.ibw' for filename in glob.glob("B95*.ibw"): data = loadibw(filename) pprint(data) print data['version'] print data['wave']['wData'] if 'Ch0' in filename: curr.plot(data['wave']['wData']) if 'Ch3' in filename: volt.plot(data['wave']['wData']) plt.show()