diff --git a/@HEKA_Importer/HEKA_FileFormat/FileFormat_2x90/AmplTreeFile_v9.txt b/@HEKA_Importer/HEKA_FileFormat/FileFormat_2x90/AmplTreeFile_v9.txt new file mode 100644 index 0000000..778f417 --- /dev/null +++ b/@HEKA_Importer/HEKA_FileFormat/FileFormat_2x90/AmplTreeFile_v9.txt @@ -0,0 +1,258 @@ + + PatchMaster v2.74, 28-Nov-2014 + + SizeByte = 1; + SizeChar = 1; + SizeEnum = 1; + SizeBoolean = 1; + SizeInt16 = 2; + SizeCard16 = 2; + SizeSet16 = 2; + SizeInt32 = 4; + SizeCard32 = 4; + SizeReal = 4; + SizeLongReal = 8; + + String8Size = 8; + String32Size = 32; + + StimParams = 10; + StimParamChars = 320; + + RootLevel = 0; + StimulationLevel = 1; + ChannelLevel = 2; + StimSegmentLevel = 3; + + + (* + CompressionMode : Specifies how to the data + -> meaning of bits: + bit 0 (CompReal) -> high = store as real + low = store as int16 + bit 1 (CompMean) -> high = use mean + low = use single sample + bit 2 (CompFilter) -> high = use digital filter + *) + + (* + StimToDacID : Specifies how to convert the Segment "Voltage" to + the actual voltage sent to the DAC + -> meaning of bits: + bit 0 (UseStimScale) -> use StimScale + bit 1 (UseRelative) -> relative to Vmemb + bit 2 (UseFileTemplate) -> use file template + bit 3 (UseForLockIn) -> use for LockIn computation + bit 4 (UseForWavelength) + bit 5 (UseScaling) + bit 6 (UseForChirp) + bit 7 (UseForImaging) + bit 14 (UseReserved) + bit 15 (UseReserved) + *) + + SegmentClass = ( SegmentConstant, + SegmentRamp, + SegmentContinuous, + SegmentConstSine, + SegmentSquarewave, + SegmentChirpwave ); + + IncrementModeType = ( ModeInc, + ModeDec, + ModeIncInterleaved, + ModeDecInterleaved, + ModeAlternate, + ModeLogInc, + ModeLogDec, + ModeLogIncInterleaved, + ModeLogDecInterleaved, + ModeLogAlternate ); + + ExtTriggerType = ( TrigNone, + TrigSeries, + TrigSweep, + TrigSweepNoLeak ); + + AmplModeType = ( AnyAmplMode, + VCAmplMode, + CCAmplMode, + IDensityMode ); + + AutoRangingType = ( AutoRangingOff, + AutoRangingPeak, + AutoRangingMean, + AutoRangingRelSeg ); + + AdcType = ( AdcOff, + Analog, + Digitals, + Digital, + AdcVirtual ); + + LeakStoreType = ( LNone, + LStoreAvg, + LStoreEach, + LNoStore ); + + LeakHoldType = ( Labs, + Lrel, + LabsLH, + LrelLH ); + + BreakType = ( NoBreak, + BreakPos, + BreakNeg ); + + LeakCompType = ( LeakCompSoft, + LeakCompHard ); + + SegStoreType = ( SegNoStore, + SegStore, + SegStoreStart, + SegStoreEnd ); + + + (* StimSegmentRecord = RECORD *) + seMark = 0; (* INT32 *) + seClass = 4; (* BYTE *) + seStoreKind = 5; (* BYTE *) + seVoltageIncMode = 6; (* BYTE *) + seDurationIncMode = 7; (* BYTE *) + seVoltage = 8; (* LONGREAL *) + seVoltageSource = 16; (* INT32 *) + seDeltaVFactor = 20; (* LONGREAL *) + seDeltaVIncrement = 28; (* LONGREAL *) + seDuration = 36; (* LONGREAL *) + seDurationSource = 44; (* INT32 *) + seDeltaTFactor = 48; (* LONGREAL *) + seDeltaTIncrement = 56; (* LONGREAL *) + seFiller1 = 64; (* INT32 *) + seCRC = 68; (* CARD32 *) + seScanRate = 72; (* LONGREAL *) + StimSegmentRecSize = 80; (* = 10 * 8 *) + + (* ChannelRecord = RECORD *) + chMark = 0; (* INT32 *) + chLinkedChannel = 4; (* INT32 *) + chCompressionFactor = 8; (* INT32 *) + chYUnit = 12; (* String8Type *) + chAdcChannel = 20; (* INT16 *) + chAdcMode = 22; (* BYTE *) + chDoWrite = 23; (* BOOLEAN *) + stLeakStore = 24; (* BYTE *) + chAmplMode = 25; (* BYTE *) + chOwnSegTime = 26; (* BOOLEAN *) + chSetLastSegVmemb = 27; (* BOOLEAN *) + chDacChannel = 28; (* INT16 *) + chDacMode = 30; (* BYTE *) + chHasLockInSquare = 31; (* BYTE *) + chRelevantXSegment = 32; (* INT32 *) + chRelevantYSegment = 36; (* INT32 *) + chDacUnit = 40; (* String8Type *) + chHolding = 48; (* LONGREAL *) + chLeakHolding = 56; (* LONGREAL *) + chLeakSize = 64; (* LONGREAL *) + chLeakHoldMode = 72; (* BYTE *) + chLeakAlternate = 73; (* BOOLEAN *) + chAltLeakAveraging = 74; (* BOOLEAN *) + chLeakPulseOn = 75; (* BOOLEAN *) + chStimToDacID = 76; (* SET16 *) + chCompressionMode = 78; (* SET16 *) + chCompressionSkip = 80; (* INT32 *) + chDacBit = 84; (* INT16 *) + chHasLockInSine = 86; (* BOOLEAN *) + chBreakMode = 87; (* BYTE *) + chZeroSeg = 88; (* INT32 *) + chStimSweep = 92; (* INT32 *) + chSine_Cycle = 96; (* LONGREAL *) + chSine_Amplitude = 104; (* LONGREAL *) + chLockIn_VReversal = 112; (* LONGREAL *) + chChirp_StartFreq = 120; (* LONGREAL *) + chChirp_EndFreq = 128; (* LONGREAL *) + chChirp_MinPoints = 136; (* LONGREAL *) + chSquare_NegAmpl = 144; (* LONGREAL *) + chSquare_DurFactor = 152; (* LONGREAL *) + chLockIn_Skip = 160; (* INT32 *) + chPhoto_MaxCycles = 164; (* INT32 *) + chPhoto_SegmentNo = 168; (* INT32 *) + chLockIn_AvgCycles = 172; (* INT32 *) + chImaging_RoiNo = 176; (* INT32 *) + chChirp_Skip = 180; (* INT32 *) + chChirp_Amplitude = 184; (* LONGREAL *) + chPhoto_Adapt = 192; (* BYTE *) + chSine_Kind = 193; (* BYTE *) + chChirp_PreChirp = 194; (* BYTE *) + chSine_Source = 195; (* BYTE *) + chSquare_NegSource = 196; (* BYTE *) + chSquare_PosSource = 197; (* BYTE *) + chChirp_Kind = 198; (* BYTE *) + chChirp_Source = 199; (* BYTE *) + chDacOffset = 200; (* LONGREAL *) + chAdcOffset = 208; (* LONGREAL *) + chTraceMathFormat = 216; (* BYTE *) + chHasChirp = 217; (* BOOLEAN *) + chSquare_Kind = 218; (* BYTE *) + chFiller1 = 219; (* ARRAY[0..5] OF CHAR *) + chSquare_BaseIncr = 224; (* LONGREAL *) + chSquare_Cycle = 232; (* LONGREAL *) + chSquare_PosAmpl = 240; (* LONGREAL *) + chCompressionOffset = 248; (* INT32 *) + chPhotoMode = 252; (* INT32 *) + chBreakLevel = 256; (* LONGREAL *) + chTraceMath = 264; (* String128Type *) + chFiller2 = 392; (* INT32 *) + chCRC = 396; (* CARD32 *) + ChannelRecSize = 400; (* = 50 * 8 *) + + (* StimulationRecord = RECORD *) + stMark = 0; (* INT32 *) + stEntryName = 4; (* String32Type *) + stFileName = 36; (* String32Type *) + stAnalName = 68; (* String32Type *) + stDataStartSegment = 100; (* INT32 *) + stDataStartTime = 104; (* LONGREAL *) + stSampleInterval = 112; (* LONGREAL *) + stSweepInterval = 120; (* LONGREAL *) + stLeakDelay = 128; (* LONGREAL *) + stFilterFactor = 136; (* LONGREAL *) + stNumberSweeps = 144; (* INT32 *) + stNumberLeaks = 148; (* INT32 *) + stNumberAverages = 152; (* INT32 *) + stActualAdcChannels = 156; (* INT32 *) + stActualDacChannels = 160; (* INT32 *) + stExtTrigger = 164; (* BYTE *) + stNoStartWait = 165; (* BOOLEAN *) + stUseScanRates = 166; (* BOOLEAN *) + stNoContAq = 167; (* BOOLEAN *) + stHasLockIn = 168; (* BOOLEAN *) + stOldStartMacKind = 169; (* CHAR *) + stOldEndMacKind = 170; (* BOOLEAN *) + stAutoRange = 171; (* BYTE *) + stBreakNext = 172; (* BOOLEAN *) + stIsExpanded = 173; (* BOOLEAN *) + stLeakCompMode = 174; (* BOOLEAN *) + stHasChirp = 175; (* BOOLEAN *) + stOldStartMacro = 176; (* String32Type *) + stOldEndMacro = 208; (* String32Type *) + sIsGapFree = 240; (* BOOLEAN *) + sHandledExternally = 241; (* BOOLEAN *) + stFiller1 = 242; (* BOOLEAN *) + stFiller2 = 243; (* BOOLEAN *) + stCRC = 244; (* CARD32 *) + StimulationRecSize = 248; (* = 31 * 8 *) + + (* RootRecord = RECORD *) + roVersion = 0; (* INT32 *) + roMark = 4; (* INT32 *) + roVersionName = 8; (* String32Type *) + roMaxSamples = 40; (* INT32 *) + roFiller1 = 44; (* INT32 *) + (* StimParams = 10 *) + (* StimParamChars = 320 *) + roParams = 48; (* ARRAY[0..9] OF LONGREAL *) + roParamText = 128; (* ARRAY[0..9],[0..31]OF CHAR *) + roReserved = 448; (* String128Type *) + roFiller2 = 576; (* INT32 *) + roCRC = 580; (* CARD32 *) + RootRecSize = 584; (* = 73 * 8 *) diff --git a/@HEKA_Importer/HEKA_FileFormat/FileFormat_2x90/AnalysisFile_v9.txt b/@HEKA_Importer/HEKA_FileFormat/FileFormat_2x90/AnalysisFile_v9.txt new file mode 100644 index 0000000..1f68b0a --- /dev/null +++ b/@HEKA_Importer/HEKA_FileFormat/FileFormat_2x90/AnalysisFile_v9.txt @@ -0,0 +1,280 @@ + + PatchMaster v2.74, 27-Dec-2014 + + SizeByte = 1; + SizeChar = 1; + SizeEnum = 1; + SizeBoolean = 1; + SizeInt16 = 2; + SizeCard16 = 2; + SizeSet16 = 2; + SizeInt32 = 4; + SizeCard32 = 4; + SizeReal = 4; + SizeLongReal = 8; + + String8Size = 8; + String32Size = 32; + String64Size = 64; + MaxGraphs = 12; + + RootLevel = 0; + MethodLevel = 1; + FunctionLevel = 2; + + FunctionType = ( SweepCountAbsc, (* general *) + TimeAbsc, + TimerAbsc, + RealtimeAbsc, + SegAmplitude, (* X segment property *) + SegDuration, + ScanRateAbsc, + ExtremumMode, (* Y analysis *) + MaximumMode, + MinimumMode, + MeanMode, + IntegralMode, + VarianceMode, + SlopeMode, + TimeToExtrMode, + AnodicChargeMode, (* potentiostat *) + CathodChargeMode, + CSlowMode, (* potmaster: spare *) + RSeriesMode, (* potmaster: spare *) + UserParam1Mode, + UserParam2Mode, + LockInCMMode, (* lock-in *) + LockInGMMode, + LockInGSMode, + SeriesTime, (* misk *) + StimulusMode, + SegmentTimeAbs, + OpEquationMode, (* math *) + ConstantMode, + OperatorPlusMode, + OperatorMinusMode, + OperatorMultMode, + OperatorDivMode, + OperatorAbsMode, + OperatorLogMode, + OperatorSqrMode, + OperatorInvMode, + OperatorInvLogMode, + OperatorInvSqrMode, + TraceMode, (* trace *) + QMode, + InvTraceMode, + InvQMode, + LnTraceMode, + LnQMode, + LogTraceMode, + LogQMode, + TraceXaxisMode, + FreqMode, (* spectra *) + DensityMode, + HistoAmplMode, (* histogram *) + HistoBinsMode, + OnlineIndex, + ExtrAmplMode, + SegmentTimeRel, + CellPotential, (* potmaster: OCP *) + SealResistance, (* potmaster: ElectrodeArea *) + RsValue, (* potmaster: spare *) + GLeak, (* potmaster: spare *) + MConductance, (* potmaster: spare *) + Temperature, + PipettePressure, (* potmaster: spare *) + InternalSolution, + ExternalSolution, + DigitalIn, + OperatorBitInMode, + ReversalMode, + LockInPhase, + LockInFreq, + TotMeanMode, (* obsolete: replaced by MeanMode + CursorKind *) + DiffMode, + IntSolValue, + ExtSolValue, + OperatorAtanMode, + OperatorInvAtanMode, + TimeToMinMode, + TimeToMaxMode, + TimeToThreshold, + TraceEquationMode, + ThresholdAmpl, + XposMode, + YposMode, + ZposMode, + TraceCountMode, + AP_Baseline, + AP_MaximumAmpl, + AP_MaximumTime, + AP_MinimumAmpl, + AP_MinimumTime, + AP_RiseTime1Dur, + AP_RiseTime1Slope, + AP_RiseTime1Time, + AP_RiseTime2Dur, + AP_RiseTime2Slope, + AP_RiseTime2Time, + AP_Tau, + MatrixXindexMode, + MatrixYindexMode, + YatX_Mode, + ThresholdCount, + SECM_3Dx, + SECM_3Dy, + InterceptMode, + MinAmplMode, + MaxAmplMode, + TauMode ); + + TicDirectionType = ( TicLeft, TicRight, TicBoth ); + + ScaleType = ( ScaleFixed, ScaleSeries, ScaleSweeps ); + + AxisLevelType = ( Min, Zero, Max ); + + AxisTypeType = ( ScaleLinear, + ScaleLog, + ScaleInverse, + ScaleSqrt, + ScaleSquare ); + + MarkerKindType = ( MarkerPoint, + MarkerPlus, + MarkerStar, + MarkerDiamond, + MarkerX, + MarkerSquare ); + + GraphWindowType = ( Win0, Win1, Win2 ); + + NormalizeType = ( NormalizeNone, NormalizeMax, NormalizeMinMax ); + + CursorType = ( Cursor_Segment, (* cursor relative to segment *) + Cursor_Trace ); (* cursor relative to trace *) + + BaselineType = ( Baseline_Zero, (* baseline relative to zero *) + Baseline_Cursors, (* baseline = intersection with cursors *) + Baseline_Auto ); (* baseline = intersection with cursors *) + + SearchDirectionType = ( Search_All, + Search_Positive, + Search_Negative ); + + + (* FunctionRecord = RECORD *) + fnMark = 0; (* INT32 *) + fnName = 4; (* String32Size *) + fnUnit = 36; (* String8Size *) + fnLeftOperand = 44; (* INT16 *) + fnRightOperand = 46; (* INT16 *) + fnLeftBound = 48; (* LONGREAL *) + fnRightBound = 56; (* LONGREAL *) + fnConstant = 64; (* LONGREAL *) + fnXSegmentOffset = 72; (* INT32 *) + fnYSegmentOffset = 76; (* INT32 *) + fnTcEnumarator = 80; (* INT16 *) + fnFunction = 82; (* BYTE *) + fnDoNotebook = 83; (* BOOLEAN *) + fnNoFit = 84; (* BOOLEAN *) + fnNewName = 85; (* BOOLEAN *) + fnTargetValue = 86; (* INT16 *) + fnCursorKind = 88; (* BYTE *) + fnTcKind1 = 89; (* 3 BYTE *) + fnTcKind2 = 90; (* 3 BYTE *) + fnCursorSource = 91; (* BYTE *) + fnCRC = 92; (* CARD32 *) + fnEquation = 96; (* String64Size *) + fnBaselineMode = 160; (* BYTE *) + fnSearchDirection = 161; (* BYTE *) + fnSourceValue = 162; (* INT16 *) + fnCursorAnker = 164; (* INT16 *) + fnSpare1 = 165; (* INT16 *) + FunctionRecSize = 168; (* = 21 * 8 *) + + + (* ScalingRecord = RECORD *) + scMinValue = 0; (* LONGREAL *) + scMaxValue = 8; (* LONGREAL *) + scGridFactor = 16; (* LONGREAL *) + scTicLength = 24; (* INT16 *) + scTicNumber = 26; (* INT16 *) + scTicDirection = 28; (* BYTE *) + scAxisLevel = 29; (* BYTE *) + scAxisType = 30; (* BYTE *) + scScaleMode = 31; (* BYTE *) + scNoUnit = 32; (* BOOLEAN *) + scObsolete = 33; (* BOOLEAN *) + scZeroLine = 34; (* BOOLEAN *) + scGrid = 35; (* BOOLEAN *) + scNice = 36; (* BOOLEAN *) + scLabel = 37; (* BOOLEAN *) + scCentered = 38; (* BOOLEAN *) + scIncludeZero = 39; (* BOOLEAN *) + ScalingRecSize = 40; (* = 5 * 8 *) + + + (* EntryRecord = RECORD *) + enXWave = 0; (* INT16 *) + enYWave = 2; (* INT16 *) + enMarkerSize = 4; (* INT16 *) + enMarkerColorRed = 6; (* CARD16 *) + enMarkerColorGreen = 8; (* CARD16 *) + enMarkerColorBlue = 10; (* CARD16 *) + enMarkerKind = 12; (* BYTE *) + enEActive = 13; (* BOOLEAN *) + enLine = 14; (* BOOLEAN *) + enTraceColor = 15; (* BOOLEAN *) + EntryRecSize = 16; (* = 2 * 8 *) + + + (* GraphRecord = RECORD *) + grGActive = 0; (* BOOLEAN *) + grOverlay = 1; (* BOOLEAN *) + grWrap = 2; (* CHAR *) + grOvrlSwp = 3; (* BOOLEAN *) + grNormalize = 4; (* BYTE *) + grSpare1 = 5; (* BYTE *) + grSpare2 = 6; (* BYTE *) + grSpare3 = 7; (* BYTE *) + grXScaling = 8; (* ScalingRecord; *) + grYScaling = 48; (* ScalingRecord *) + grEntry0 = 88; (* EntryRecSize *) + grEntry1 = 104; (* EntryRecSize *) + grEntry2 = 120; (* EntryRecSize *) + grEntry3 = 136; (* EntryRecSize *) + GraphRecSize = 152; (* = 19 * 8 *) + + + (* MethodRecord = RECORD *) + oaMark = 0; (* INT32 *) + oaEntryName = 4; (* String32Size *) + oaSharedXWin1 = 36; (* BOOLEAN *) + oaSharedXWin2 = 37; (* BOOLEAN *) + oa1 = 38; (* BOOLEAN *) + oa2 = 39; (* BOOLEAN *) + oaGraph0 = 40; (* MaxGraphs * GraphRecSize = 1824 *) + oa3 = 1864; (* INT32 *) + oaCRC = 1868; (* CARD32 *) + oaHeaders = 1872; (* MaxGraphs * String32Size = 384 *) + oaLastXmin = 2256; (* MaxGraphs * LONGREAL = 96 *) + oaLastXmax = 2352; (* MaxGraphs * LONGREAL = 96 *) + oaLastYmin = 2448; (* MaxGraphs * LONGREAL = 96 *) + oaLastYmax = 2544; (* MaxGraphs * LONGREAL = 96 *) + MethodRecSize = 2640; (* = 330 * 8 *) + + + (* RootRecord = RECORD *) + roVersion = 0; (* INT32 *) + roMark = 4; (* INT32 *) + roVersionName = 8; (* String32Size *) + roObsolete = 40; (* BYTE *) (* was StimControl *) + roMaxTraces = 41; (* CHAR *) + roWinDefined = 42; (* BOOLEAN *) + rt1 = 43; (* BYTE *) + roCRC = 44; (* CARD32 *) + roWinNr = 48; (* MaxFileGraphs *) + rt2 = 60; (* INT32 *) + RootRecSize = 64; (* = 6 * 8 *) diff --git a/@HEKA_Importer/HEKA_FileFormat/FileFormat_2x90/DataFile_v9.txt b/@HEKA_Importer/HEKA_FileFormat/FileFormat_2x90/DataFile_v9.txt new file mode 100644 index 0000000..1c0ebaa --- /dev/null +++ b/@HEKA_Importer/HEKA_FileFormat/FileFormat_2x90/DataFile_v9.txt @@ -0,0 +1,125 @@ + + PatchMaster v2.74, 21-Jan-2014 + +1. Data File Types + +There are 4 types of data files: + + - the oldest files where the raw data start at the very beginning + (e.g. converted "PULSE" datafiles) + - the older files where the first 4 byte were "DATA", followed by raw data + - the new files with the empty "bundle" header => signature is "DAT1" + - the new files with the filled "bundle" header => signature is "DAT2" + - note that in "bundle" header the 4 bytes following the signature + are zero! + + +2. Structure of "bundle" Header + +The "bundle" header has the following structure: + + (* BundleHeader = RECORD *) + oSignature = 0; (* ARRAY[0..7] OF CHAR *) + oVersion = 8; (* ARRAY[0..31] OF CHAR *) + oTime = 40; (* LONGREAL *) + oItems = 48; (* INT32 *) + oIsLittleEndian = 52; (* BOOLEAN *) + oReserved = 53; (* ARRAY[0..10] OF CHAR *) + oBundleItems = 64; (* ARRAY[0..11] OF BundleItem *) + BundleHeaderSize = 256; (* = 32 * 8 *) + + (* BundleItem = RECORD *) + oStart = 0; (* INT32 *) + oLength = 4; (* INT32 *) + oExtension = 8; (* ARRAY[0..7] OF CHAR *) + BundleItemSize = 16; (* = 2 * 8 *) + + + Signature is "DAT1" or "DAT2", see above. + "DAT1" signals an empty or invalid BundleHeader + "DAT2" signals a valid BundleHeader + + Version contains the text version of the PatchMaster writing the file + + Time is the date and time of last modification + + Items is the number of valid BundleItem elements + + IsLittleEndian is the endian flag: Windows=TRUE, MacOS=FALSE + + BundleItems is an array of BundleItem, each containing: + "oStart" tells at which offset the respective sub-file starts + "oLength" tells the number of bytes of that file + "oExtension" tells the filename extension of the file. One can + recognize the described file by its filename extension. + + Typically, the following indices are used: + raw data file: ".dat" = 0; + Pulsed Tree file: ".pul" = 1; + PGF Tree file: ".pgf" = 2; + Amplifier file: ".amp" = 3; (* EPC/N only *) + Solution file: ".sol" = 4; (* when storing solutions only *) + Notebook file: ".txt" = 5; (* auto store only *) + reserved: = 6; + Marker file: ".mrk" = 7; + Method file: ".mth" = 8; + Analysis file: ".onl" = 9; + + +3. Structure of Trace Data + +3.1. General + + Trace data are described by the parameters of the "TraceRecord", see Document + "PulsedFileFormat_v9.txt". + + Specifically: + TrData offset [in bytes] into the data file + TrDataPoints number of data points + TrDataKind defines the format: int16, int32, real32, real64 + TrDataScaler scaling factor from raw format to IUPAC units: + ampere, volt, meter, second, etc. + TrInterleaveSize interleave block size [in bytes] + TrInterleaveSkip distance [in bytes] to the next interleave block + TrInterleaveSkip distance [in bytes] from beginning of an interleave block + to the beginning of the following interleaved block + +3.2. Interleaving + + TrInterleaveSize is typically zero, denoting that the data are stored as one + contiguous block. For long continuous acquisitions interleaving is required. + In that case, TrInterleaveSize defines the size [in bytes] of one data block + and TrInterleaveSkip defines how many bytes are to be skipped from beginning + of one block to beginning of the next data block. + + Example: + - TrInterleaveSize = 1000 + - TrInterleaveSkip = 3000 + + | Start of trace data at TrData into data file + V + <- 1000 bytes -------><- 2000 bytes ----------------------><- 1000 bytes -------> + 1. block of trace (data blocks of other traces) 2. block of trace + <- 3000 bytes --------------------------------------------><- ... + + +3.3. "start segment" and "non-stored" Segments + + - "start segment" + If stDataStartSegment > 0 : + Any data originating from a segment before the stDataStartSegment segment, + is not stored, nor any data between the start of stDataStartSegment segment and + stDataStartTime. + + - "non-stored" data + Additionally, any data originating from a segment with seDoStore = false is not stored. + + +4. How to get V-membrane/I-membrane of a Trace + +4.1. Get the stimulus channel which defined the appropriate stimulus pattern. That channel is the one having the index chLinkedChannel. An exception is a LockIn trace. +The chLinkedChannel channel is the parent LockIn current trace, and its chLinkedChannel +is the actual channel defining the appropriate stimulus pattern. + +4.2. The field "Holding" of the chLinkedChannel channel contains now V-membrane/ +I-membrane of the trace. diff --git a/@HEKA_Importer/HEKA_FileFormat/FileFormat_2x90/DataFormat_v9.doc b/@HEKA_Importer/HEKA_FileFormat/FileFormat_2x90/DataFormat_v9.doc new file mode 100644 index 0000000..243b0c2 Binary files /dev/null and b/@HEKA_Importer/HEKA_FileFormat/FileFormat_2x90/DataFormat_v9.doc differ diff --git a/@HEKA_Importer/HEKA_FileFormat/FileFormat_2x90/FileFormat.txt b/@HEKA_Importer/HEKA_FileFormat/FileFormat_2x90/FileFormat.txt new file mode 100644 index 0000000..aba604c --- /dev/null +++ b/@HEKA_Importer/HEKA_FileFormat/FileFormat_2x90/FileFormat.txt @@ -0,0 +1,632 @@ + + PatchMaster v2.74, 30-Sep-2014 + +(************************************************************************ + +PatchMaster generates multiple files when you create a data file. They +can be combined into a "bundle" file, if requested. The bundle file format +is described in the document "DataFile_v9.txt". +The files are: + + 1. The data file itself (file with file extension ".dat"). + This raw data file is a continuous data stream. + + 2. The "pul" file, containing acquisition parameters, such as gain, + capacitance, etc. The pointer to the data stored in the raw data + file is also stored in this file. + The information is stored in the "Tree" format described below. + + 3. The "pgf" file, containing the stimulus templates. + The information is stored in the "Tree" format described below. + + 5. The "sol" file containing the solution data base. + The information is stored in the "Tree" format described below. + + 6. The "onl" file containing the stored online analysis methods. + The information is stored in the "Tree" format described below. + + 7. The "mth" file containing the applied acquisition methods. + The format is described in the file "MethodFile_v9.txt". + + 8. The "mrk" file containing the markers. + The information is stored in the "Tree" format described below. + + 9. The optional "amp" file, when a multiple amplifier is used. + It contains the multiple amplifier settings and solutions. + The information is stored in the "Tree" format described below. + + 10. The optional "ana" file with the analysis results created by + FitMaster. + The information is stored in the "Tree" format described below. + +The descriptions of the variables, their names and meanings, and their +respective record offsets are described in the following files: + AmplTreeFile_v9.txt + DataFile_v9.txt + DataFormat_v9.doc + FileFormat.txt + MarkerFile_v9.txt + MethodFile_v9.txt + Online_v9.txt + PulsedFile_v9.txt + SolutionsFile_v9.txt + StimFile_v9.txt + TimeFormat.txt + + +The following is a description of the "Tree" format. Following the +description of the "Tree" format a source code listing is enclosed. +That program shows how to scan and load a "Tree" file. It can be +compiled and executed by the PowerMod environment. The source code +is commented and can easily be translated to other languages. + +The idea behind the "Tree" format is that it allows extending the +information stored in a file without braking the older file format. +Thus, newer program versions can load files created by older program +versions and vice versa without requiring any file conversions. This +approach is presently (in 1995) working since more than 10 years +across many program versions. + +An example tree can be diagrammed as follows: + + Level 0 Record (Root) + Level 1 Record 1 + Level 2 Record 1.1 + Level 3 Record 1.1.1 + Level 3 Record 1.1.2 + Level 2 Record 1.2 + Level 1 Record 2 + Level 2 Record 2.1 + Level 3 Record 2.1.1 + Level 2 Record 2.2 + Level 3 Record 2.2.1 + Level 3 Record 2.2.2 + Level 3 Record 2.2.3 + Level 3 Record 2.2.4 + Level 1 Record 3 + +There is only ever one record of level 0, the root record. The above +tree has four levels, the root (level 0), levels 1 and 2, and the leaf +nodes (level 3). + +The format of a tree stored to a file is as follows: + + 1) Magic number : 054726565H + 2) Number of levels + 3) Level sizes, one per level + 4) Tree records, top down, left-to-right. Each record has the format: + A) Record contents + B) Number of children + +All of the values (except the record contents) are INT32 values, i.e., +32-bit (4 bytes) values. + +The "Tree" format is based on proposals from Stefan Heinemann, +Erwin Neher, and Walter Stuehmer. + +WARNING: Never assume you know the record sizes. The record sizes may + have changed, e.g., because the file has been created by an + older program version which used fewer fields than it is + currently using. You MUST use the record sizes stored in the + files themselves, otherwise you are asking for BIG troubles! + + +The trace data are stored in the data file as follows: + + first trace + -> at offset "Data" + -> having "DataPoints" samples + -> to be scaled with "DataFactor1" + + leak trace, if "Leak" = TRUE + -> at offset (Data + 2*DataPoints) + -> having "DataPoints" samples + -> to be scaled with "DataFactor1" + + second trace, if "SecondTrace" = TRUE + -> at offset: + (Data + 2*DataPoints), if no leak + (Data + 4*DataPoints), if leak present + -> having "DataPoints" samples + -> to be scaled with "DataFactor2" + +notes about stored trace data: +- it is stored "Leak Subtracted" +- but not "Zero Subtracted" +- add the leak to get the "non subtracted" trace +- subtract "ZeroCurrent" from the scaled trace to get the "Zero Subtracted" trace + +notes about the second trace: +- stored without "Leak Subtraction" +- stored without "Zero Subtraction" + +************************************************************************) + + +MODULE FileFormat; + +FROM SYSTEM IMPORT ADR, ADDRESS, BYTE, LONG, SHORT; +FROM SYSTEMp1 IMPORT INT32, ADDADR; + +IMPORT Alert, FileSelect, IOBytes, IOFiles, Strings, TermIO, Buffer; + + +(* + * MagicNumber - This is a special value used as a prefix for a tree + * stored to a file. The value contains the four byte values of the + * characters 'Tree' in order. + * + * SwappedMagicNumber - This is the MagicNumber written by a CPU + * which used the opposite byte ordering. + *) + +CONST + MagicNumber = 054726565H; (* i.e. "Tree" in ASCII *) + SwappedMagicNumber = 065657254H; (* i.e. "eerT" in ASCII *) + + +(* + * SwappedInt32 - Swaps the byte of a 32 bit long variable. + *) + +PROCEDURE SwappedInt32( Value : INT32 ): INT32; +VAR + Source, + Target : POINTER TO ARRAY[0..3] OF BYTE; + Result : INT32; +BEGIN + Source := ADR( Value ); + Target := ADR( Result ); + Target^[0] := Source^[3]; + Target^[1] := Source^[2]; + Target^[2] := Source^[1]; + Target^[3] := Source^[0]; + RETURN Result; +END SwappedInt32; + + +(* + * LoadOneRecord + * + * Loads one data block. + * All "TermIO" statements are for demonstration purpose only. + * + * The variables are + * Stream : the file handle to the open file + * FileSize : the number of bytes the data block has in the + * file. + * MemorySize : the byte length of the memory block where the + * data is going to be stored. + * WhereToStore : the address of where the data block is going + * to be stored. + * + * The procedure returns TRUE, if it encountered no errors. + *) + +PROCEDURE LoadOneRecord( + Stream : IOFiles.FileHandleType; + FileSize : LONGINT; + MemorySize : LONGINT; + WhereToStore : ADDRESS ) + : BOOLEAN; + +VAR + Excess : LONGINT; + FileBytes : LONGINT; + +BEGIN + + (* Here we load the next block of data into memory. + * + * First, we have to compare the number of bytes we can load from the file + * with the bytes of allocated memory for that record. + * + * There are 3 possibilities: + * 1. The size of the allocated memory ("MemorySize") equals the number + * of bytes of the data block in the file ("FileSize"). Thus, we can + * load the complete block. + * 2. There are fewer bytes in the file than we expect. This can occur, + * e.g., when the file has been written by an earlier version which + * used fewer parameters than the present one. In this case, we would + * have to zero out those fields which are not filled with data from + * the file. + * 3. There are more bytes in the file than we expect. This can happen, + * when the program which created that tree file was using more + * parameters than we presently know of. In that case, we would load + * only as much byte as we had reserved RAM for. + *) + + Excess := MemorySize - FileSize; + + IF Excess = 0D THEN + (* The file record has as many bytes as there is space in RAM *) + + FileBytes := MemorySize; + + ELSIF Excess < 0D THEN + (* The file record has more many bytes than there is space in RAM. + * Load only as many bytes as there is space in RAM. + *) + + FileBytes := MemorySize; + + ELSE (* i.e., Excess > 0D *) + (* The file record has fewer bytes than there is space in RAM. + * Load only as many bytes as there are in the file. + *) + + FileBytes := FileSize; + + (* Do not forget to clear the remaining fields which are not going + * to be filled from the file. + *) + + Buffer.Set( ADDADR( WhereToStore, FileSize ), Excess, 0 ); + + END (* IF *); + + RETURN IOBytes.Read( Stream, FileBytes, WhereToStore ); + +END LoadOneRecord; + + +(* + * LoadOneLevel + * + * Processes the loading of one data block from a "Tree", and all + * its "children". + * All "TermIO" statements are for demonstration purpose only. + * + * The variables are + * Stream : the file handle to the open file + * Sizes : the array containing the level sizes + * Levels : the number of levels in the tree + * NeedsByteSwap : the flag telling, whether byte-swapping is needed + * Level : the actual tree level to load + * IsFirst : a flag telling, whether it is the first child + * loaded. This is only required for text output! + * Position : the variable containing the position in the file. + * + * The procedure returns TRUE, if it encountered no errors. + *) + +PROCEDURE LoadOneLevel( + VAR Stream : IOFiles.FileHandleType; + VAR Sizes : ARRAY OF INT32; + VAR Levels : LONGINT; + NeedsByteSwap : BOOLEAN; + Level : LONGINT; + IsFirst : BOOLEAN; + VAR Position : LONGINT ) + : BOOLEAN; + +VAR + Count : INT32; + Size : LONGINT; + Children : LONGINT; + i : INTEGER; + WriteInfo : BOOLEAN; + +BEGIN + + WriteInfo := IsFirst OR ( Level < Levels ); + + IF WriteInfo THEN + FOR i := 1 TO SHORT( Level ) DO + TermIO.WriteString( ' ' ); + END; (* FOR *) + TermIO.WriteString( 'level: ' ); + TermIO.WriteInt( Level, 0 ); + TermIO.WriteString( '; file offset: ' ); + TermIO.WriteInt( Position, 0 ); + END; (* IF *) + + + (* Here would normally be the code which loads the next block of data + * somewhere into memory. In the present example, we just skip the bytes + * containing these data. + * + * In case we would load the data block from the file, we would call the + * following procedure: + + IF NOT + LoadOneRecord( Stream, Sizes[SHORT(Level)], MemorySize, WhereToStore ) + THEN + Alert.IOError( '7-Error' ); + RETURN FALSE; + END; + + (* If byte-swapping is required, we would now have to swap the bytes of all + fields in the loaded record! + *) + + IF NeedsByteSwap THEN ( go and swap the record fields ... ) END; + + * End of code we would call. + *) + + + (* Increase the file pointer by "Sizes[Level]" bytes and set the file position + * just beyond the next data block: + *) + + INC( Position, Sizes[SHORT(Level)] ); + + IF NOT + IOBytes.SetPosition( Stream, IOFiles.FromStart, Position ) + THEN + Alert.IOError( '8-Error' ); + RETURN FALSE; + END; + + + (* The next 4 bytes contain the number of children of the present level. *) + + Size := SIZE( INT32 ); + + IF NOT IOBytes.Read( Stream, Size, ADR(Count) ) THEN + Alert.IOError( '9-Error' ); + RETURN FALSE; + END; + + (* The file pointer increased by 4 bytes: *) + INC( Position, 4 ); + + (* And we swap the bytes, if needed: *) + + IF NeedsByteSwap THEN Count := SwappedInt32( Count ); END; + + IF WriteInfo THEN + TermIO.WriteString( '; children: ' ); + TermIO.WriteInt( Count, 0 ); + TermIO.WriteLn; + END; (* IF *) + + + (* Now, we can proceed to load all the children of the present level, + * if there are any: + *) + + INC( Level ); + + Children := 0D; + + IF Level < Levels THEN + + WHILE Children < Count DO + + IF NOT + LoadOneLevel( + Stream, + Sizes, + Levels, + NeedsByteSwap, + Level, + Children = 0D, + Position ) + THEN + RETURN FALSE; + END; (* IF *) + + INC( Children ); + + END (* WHILE *); + + END (* IF *); + + RETURN TRUE; + +END LoadOneLevel; + + +(* + * LoadTree + * + * Scans a complete Tree. + * All "TermIO" statements are for demonstration purpose only. + * + * The variables are + * Stream : the file handle to the open file + * Sizes : the array is returns the level sizes in the Tree + * on disk. + * Levels : the number of levels in the tree + * NeedsByteSwap : the flag telling, whether byte-swapping is needed + * + * The procedure returns TRUE, if it encountered no errors. + *) + +PROCEDURE LoadTree( + VAR Stream : IOFiles.FileHandleType; + VAR Sizes : ARRAY OF INT32; + VAR Levels : LONGINT; + VAR NeedsByteSwap : BOOLEAN ) + : BOOLEAN; +VAR + Value : INT32; + Position : LONGINT; + Size : LONGINT; + i : INTEGER; + Success : BOOLEAN; + +BEGIN + + (* We start at the beginning of the file. We keep the variable + * "Position" containing the actual position in the file. + *) + + Position := 0D; + + + (* The first 4 bytes should contain the "MagicNumber", see above. + * a variable of type INT32 is a 32-bit long, signed word. + *) + + Size := SIZE( INT32 ); + + IF NOT IOBytes.Read( Stream, Size, ADR(Value) ) THEN + Alert.IOError( '2-Error' ); + RETURN FALSE; + END; + + IF Value = MagicNumber THEN + NeedsByteSwap := FALSE; + ELSIF Value = SwappedMagicNumber THEN + NeedsByteSwap := TRUE; + ELSE + Alert.OK( '3-Error: File does not start with "Tree" !' ); + RETURN FALSE; + END; (* IF *) + + (* The file pointer increased by 4 bytes: *) + INC( Position, 4 ); + + + (* Next we load the number of levels in the Tree, which is stored in the + * next 4 bytes (at offset 4): + *) + + Size := SIZE( INT32 ); + + IF NOT IOBytes.Read( Stream, Size, ADR(Levels) ) THEN + Alert.IOError( '4-Error' ); + RETURN FALSE; + END; + + (* The file pointer increased by 4 bytes: *) + INC( Position, 4 ); + + + (* If the file originates from a platform with opposite byte ordering, + * then we have to swap the bytes: + *) + + IF NeedsByteSwap THEN Levels := SwappedInt32( Levels ); END; + + TermIO.WriteString( ' -> levels: ' ); + TermIO.WriteInt( Levels, 0 ); + + + (* The next bytes contain the sizes of all levels. Thus, there is + * one 4-byte variable for each level, totaling in "Levels" times 4 + * bytes. + * + * First, we check, if the array "Sizes" passed to this procedure is + * large enough to contain all level sizes: + *) + + IF ( Levels <= 0D ) OR ( Levels > LONG(HIGH(Sizes)+1) ) THEN + Alert.OK( '5-Error: number of level either <= 0 or too large!' ); + RETURN FALSE; + END (* IF *); + + + (* Next, we load the "Level Size": *) + + Size := Levels * LONG( SIZE( INT32 ) ); + + IF NOT IOBytes.Read( Stream, Size, ADR(Sizes) ) THEN + Alert.IOError( '6-Error' ); + RETURN FALSE; + END; + + (* The file pointer increased by "Size" bytes: *) + INC( Position, Size ); + + (* And we swap the bytes, if needed: *) + + IF NeedsByteSwap THEN + FOR i := 0 TO SHORT( Levels - 1D ) DO + Sizes[i] := SwappedInt32( Sizes[i] ); + END; (* FOR *) + END; (* IF *) + + TermIO.WriteString( '; sizes: ' ); + FOR i := 0 TO SHORT( Levels - 1D ) DO + TermIO.WriteInt( Sizes[i], 0 ); + IF i < SHORT( Levels - 1D ) THEN + TermIO.WriteString( ', ' ); + END; (* IF *) + END; (* FOR *) + + TermIO.WriteString( '; swap: ' ); + TermIO.WriteBoolean( NeedsByteSwap ); + TermIO.WriteLn; + + + (* Now, the tree data follow. + * We can load them by a recursive procedure: + *) + + Success := + LoadOneLevel( + Stream, + Sizes, + Levels, + NeedsByteSwap, + 0D, + TRUE, + Position ); + + IF Success THEN + TermIO.WriteString( 'total file length: ' ); + TermIO.WriteInt( Position, 0 ); + END; (* IF *) + + TermIO.WriteLn; + TermIO.WriteLn; + + RETURN Success; + +END LoadTree; + + +VAR + FileName : IOFiles.FileNameType; + Stream : IOFiles.FileHandleType; + Sizes : ARRAY[0..9] OF INT32; + Levels : LONGINT; + NeedsByteSwap : BOOLEAN; + Success : BOOLEAN; + Dummy : BOOLEAN; + +BEGIN + + (* Get a filename of a tree file to load: *) + + FileName[0] := 0C; + + IF NOT + FileSelect.Select( + FileName, + '*.*', + FileSelect.ExistingFile, + 'Select the TREE file to scan:' ) + THEN + RETURN; + END; (* IF *) + + TermIO.DoBuffer := TRUE; + TermIO.WriteLn; + TermIO.WriteLine( FileName ); + + + (* Open the file : *) + + IF NOT + IOBytes.Open( FileName, IOFiles.NILEncryption, IOFiles.Read, Stream ) + THEN + Alert.IOError( '1-Error' ); + RETURN; + END; + + + (* Now, load the "Tree" : *) + + Success := LoadTree( Stream, Sizes, Levels, NeedsByteSwap ); + + + (* And, finally, we are done and can close the file. *) + + Dummy := IOBytes.Close( Stream ); + +END FileFormat. \ No newline at end of file diff --git a/@HEKA_Importer/HEKA_FileFormat/FileFormat_2x90/MarkerFile_v9.txt b/@HEKA_Importer/HEKA_FileFormat/FileFormat_2x90/MarkerFile_v9.txt new file mode 100644 index 0000000..0ba8d5e --- /dev/null +++ b/@HEKA_Importer/HEKA_FileFormat/FileFormat_2x90/MarkerFile_v9.txt @@ -0,0 +1,37 @@ + + PatchMaster v2.74, 21-Jan-2014 + + SizeByte = 1; + SizeChar = 1; + SizeEnum = 1; + SizeBoolean = 1; + SizeInt16 = 2; + SizeCard16 = 2; + SizeSet16 = 2; + SizeInt32 = 4; + SizeCard32 = 4; + SizeReal = 4; + SizeLongReal = 8; + + String80Size = 80; + + RootLevel = 0; + MarkerLevel = 1; + + MarkerType = ( MarkerGeneral, + MarkerSolutionIndex, + MarkerSolutionValue ); + + (* MarkerRecord = RECORD *) + MaMarkerTime = 0; (* LONGREAL *) + MaMarkerText = 8; (* String80Type *) + MaMarkerTrace = 88; (* INT32 *) + MaMarkerKind = 92; (* BYTE *) + MaFiller = 93; (* 7 *) + MaCRC = 100; (* CARD32 *) + MarkerRecSize = 104; (* = 13 * 8 *) + + (* RootRecord = RECORD *) + RoVersion = 0; (* INT32 *) + RoCRC = 4; (* CARD32 *) + RootRecSize = 8; (* = 1 * 8 *) \ No newline at end of file diff --git a/@HEKA_Importer/HEKA_FileFormat/FileFormat_2x90/MethodFile_v9.txt b/@HEKA_Importer/HEKA_FileFormat/FileFormat_2x90/MethodFile_v9.txt new file mode 100644 index 0000000..778f417 --- /dev/null +++ b/@HEKA_Importer/HEKA_FileFormat/FileFormat_2x90/MethodFile_v9.txt @@ -0,0 +1,258 @@ + + PatchMaster v2.74, 28-Nov-2014 + + SizeByte = 1; + SizeChar = 1; + SizeEnum = 1; + SizeBoolean = 1; + SizeInt16 = 2; + SizeCard16 = 2; + SizeSet16 = 2; + SizeInt32 = 4; + SizeCard32 = 4; + SizeReal = 4; + SizeLongReal = 8; + + String8Size = 8; + String32Size = 32; + + StimParams = 10; + StimParamChars = 320; + + RootLevel = 0; + StimulationLevel = 1; + ChannelLevel = 2; + StimSegmentLevel = 3; + + + (* + CompressionMode : Specifies how to the data + -> meaning of bits: + bit 0 (CompReal) -> high = store as real + low = store as int16 + bit 1 (CompMean) -> high = use mean + low = use single sample + bit 2 (CompFilter) -> high = use digital filter + *) + + (* + StimToDacID : Specifies how to convert the Segment "Voltage" to + the actual voltage sent to the DAC + -> meaning of bits: + bit 0 (UseStimScale) -> use StimScale + bit 1 (UseRelative) -> relative to Vmemb + bit 2 (UseFileTemplate) -> use file template + bit 3 (UseForLockIn) -> use for LockIn computation + bit 4 (UseForWavelength) + bit 5 (UseScaling) + bit 6 (UseForChirp) + bit 7 (UseForImaging) + bit 14 (UseReserved) + bit 15 (UseReserved) + *) + + SegmentClass = ( SegmentConstant, + SegmentRamp, + SegmentContinuous, + SegmentConstSine, + SegmentSquarewave, + SegmentChirpwave ); + + IncrementModeType = ( ModeInc, + ModeDec, + ModeIncInterleaved, + ModeDecInterleaved, + ModeAlternate, + ModeLogInc, + ModeLogDec, + ModeLogIncInterleaved, + ModeLogDecInterleaved, + ModeLogAlternate ); + + ExtTriggerType = ( TrigNone, + TrigSeries, + TrigSweep, + TrigSweepNoLeak ); + + AmplModeType = ( AnyAmplMode, + VCAmplMode, + CCAmplMode, + IDensityMode ); + + AutoRangingType = ( AutoRangingOff, + AutoRangingPeak, + AutoRangingMean, + AutoRangingRelSeg ); + + AdcType = ( AdcOff, + Analog, + Digitals, + Digital, + AdcVirtual ); + + LeakStoreType = ( LNone, + LStoreAvg, + LStoreEach, + LNoStore ); + + LeakHoldType = ( Labs, + Lrel, + LabsLH, + LrelLH ); + + BreakType = ( NoBreak, + BreakPos, + BreakNeg ); + + LeakCompType = ( LeakCompSoft, + LeakCompHard ); + + SegStoreType = ( SegNoStore, + SegStore, + SegStoreStart, + SegStoreEnd ); + + + (* StimSegmentRecord = RECORD *) + seMark = 0; (* INT32 *) + seClass = 4; (* BYTE *) + seStoreKind = 5; (* BYTE *) + seVoltageIncMode = 6; (* BYTE *) + seDurationIncMode = 7; (* BYTE *) + seVoltage = 8; (* LONGREAL *) + seVoltageSource = 16; (* INT32 *) + seDeltaVFactor = 20; (* LONGREAL *) + seDeltaVIncrement = 28; (* LONGREAL *) + seDuration = 36; (* LONGREAL *) + seDurationSource = 44; (* INT32 *) + seDeltaTFactor = 48; (* LONGREAL *) + seDeltaTIncrement = 56; (* LONGREAL *) + seFiller1 = 64; (* INT32 *) + seCRC = 68; (* CARD32 *) + seScanRate = 72; (* LONGREAL *) + StimSegmentRecSize = 80; (* = 10 * 8 *) + + (* ChannelRecord = RECORD *) + chMark = 0; (* INT32 *) + chLinkedChannel = 4; (* INT32 *) + chCompressionFactor = 8; (* INT32 *) + chYUnit = 12; (* String8Type *) + chAdcChannel = 20; (* INT16 *) + chAdcMode = 22; (* BYTE *) + chDoWrite = 23; (* BOOLEAN *) + stLeakStore = 24; (* BYTE *) + chAmplMode = 25; (* BYTE *) + chOwnSegTime = 26; (* BOOLEAN *) + chSetLastSegVmemb = 27; (* BOOLEAN *) + chDacChannel = 28; (* INT16 *) + chDacMode = 30; (* BYTE *) + chHasLockInSquare = 31; (* BYTE *) + chRelevantXSegment = 32; (* INT32 *) + chRelevantYSegment = 36; (* INT32 *) + chDacUnit = 40; (* String8Type *) + chHolding = 48; (* LONGREAL *) + chLeakHolding = 56; (* LONGREAL *) + chLeakSize = 64; (* LONGREAL *) + chLeakHoldMode = 72; (* BYTE *) + chLeakAlternate = 73; (* BOOLEAN *) + chAltLeakAveraging = 74; (* BOOLEAN *) + chLeakPulseOn = 75; (* BOOLEAN *) + chStimToDacID = 76; (* SET16 *) + chCompressionMode = 78; (* SET16 *) + chCompressionSkip = 80; (* INT32 *) + chDacBit = 84; (* INT16 *) + chHasLockInSine = 86; (* BOOLEAN *) + chBreakMode = 87; (* BYTE *) + chZeroSeg = 88; (* INT32 *) + chStimSweep = 92; (* INT32 *) + chSine_Cycle = 96; (* LONGREAL *) + chSine_Amplitude = 104; (* LONGREAL *) + chLockIn_VReversal = 112; (* LONGREAL *) + chChirp_StartFreq = 120; (* LONGREAL *) + chChirp_EndFreq = 128; (* LONGREAL *) + chChirp_MinPoints = 136; (* LONGREAL *) + chSquare_NegAmpl = 144; (* LONGREAL *) + chSquare_DurFactor = 152; (* LONGREAL *) + chLockIn_Skip = 160; (* INT32 *) + chPhoto_MaxCycles = 164; (* INT32 *) + chPhoto_SegmentNo = 168; (* INT32 *) + chLockIn_AvgCycles = 172; (* INT32 *) + chImaging_RoiNo = 176; (* INT32 *) + chChirp_Skip = 180; (* INT32 *) + chChirp_Amplitude = 184; (* LONGREAL *) + chPhoto_Adapt = 192; (* BYTE *) + chSine_Kind = 193; (* BYTE *) + chChirp_PreChirp = 194; (* BYTE *) + chSine_Source = 195; (* BYTE *) + chSquare_NegSource = 196; (* BYTE *) + chSquare_PosSource = 197; (* BYTE *) + chChirp_Kind = 198; (* BYTE *) + chChirp_Source = 199; (* BYTE *) + chDacOffset = 200; (* LONGREAL *) + chAdcOffset = 208; (* LONGREAL *) + chTraceMathFormat = 216; (* BYTE *) + chHasChirp = 217; (* BOOLEAN *) + chSquare_Kind = 218; (* BYTE *) + chFiller1 = 219; (* ARRAY[0..5] OF CHAR *) + chSquare_BaseIncr = 224; (* LONGREAL *) + chSquare_Cycle = 232; (* LONGREAL *) + chSquare_PosAmpl = 240; (* LONGREAL *) + chCompressionOffset = 248; (* INT32 *) + chPhotoMode = 252; (* INT32 *) + chBreakLevel = 256; (* LONGREAL *) + chTraceMath = 264; (* String128Type *) + chFiller2 = 392; (* INT32 *) + chCRC = 396; (* CARD32 *) + ChannelRecSize = 400; (* = 50 * 8 *) + + (* StimulationRecord = RECORD *) + stMark = 0; (* INT32 *) + stEntryName = 4; (* String32Type *) + stFileName = 36; (* String32Type *) + stAnalName = 68; (* String32Type *) + stDataStartSegment = 100; (* INT32 *) + stDataStartTime = 104; (* LONGREAL *) + stSampleInterval = 112; (* LONGREAL *) + stSweepInterval = 120; (* LONGREAL *) + stLeakDelay = 128; (* LONGREAL *) + stFilterFactor = 136; (* LONGREAL *) + stNumberSweeps = 144; (* INT32 *) + stNumberLeaks = 148; (* INT32 *) + stNumberAverages = 152; (* INT32 *) + stActualAdcChannels = 156; (* INT32 *) + stActualDacChannels = 160; (* INT32 *) + stExtTrigger = 164; (* BYTE *) + stNoStartWait = 165; (* BOOLEAN *) + stUseScanRates = 166; (* BOOLEAN *) + stNoContAq = 167; (* BOOLEAN *) + stHasLockIn = 168; (* BOOLEAN *) + stOldStartMacKind = 169; (* CHAR *) + stOldEndMacKind = 170; (* BOOLEAN *) + stAutoRange = 171; (* BYTE *) + stBreakNext = 172; (* BOOLEAN *) + stIsExpanded = 173; (* BOOLEAN *) + stLeakCompMode = 174; (* BOOLEAN *) + stHasChirp = 175; (* BOOLEAN *) + stOldStartMacro = 176; (* String32Type *) + stOldEndMacro = 208; (* String32Type *) + sIsGapFree = 240; (* BOOLEAN *) + sHandledExternally = 241; (* BOOLEAN *) + stFiller1 = 242; (* BOOLEAN *) + stFiller2 = 243; (* BOOLEAN *) + stCRC = 244; (* CARD32 *) + StimulationRecSize = 248; (* = 31 * 8 *) + + (* RootRecord = RECORD *) + roVersion = 0; (* INT32 *) + roMark = 4; (* INT32 *) + roVersionName = 8; (* String32Type *) + roMaxSamples = 40; (* INT32 *) + roFiller1 = 44; (* INT32 *) + (* StimParams = 10 *) + (* StimParamChars = 320 *) + roParams = 48; (* ARRAY[0..9] OF LONGREAL *) + roParamText = 128; (* ARRAY[0..9],[0..31]OF CHAR *) + roReserved = 448; (* String128Type *) + roFiller2 = 576; (* INT32 *) + roCRC = 580; (* CARD32 *) + RootRecSize = 584; (* = 73 * 8 *) diff --git a/@HEKA_Importer/HEKA_FileFormat/FileFormat_2x90/PulsedFile_v9.txt b/@HEKA_Importer/HEKA_FileFormat/FileFormat_2x90/PulsedFile_v9.txt new file mode 100644 index 0000000..3d02ef9 --- /dev/null +++ b/@HEKA_Importer/HEKA_FileFormat/FileFormat_2x90/PulsedFile_v9.txt @@ -0,0 +1,235 @@ + + PatchMaster v2.74, 22-Sep-2014 + + SizeByte = 1; + SizeChar = 1; + SizeEnum = 1; + SizeBoolean = 1; + SizeInt16 = 2; + SizeCard16 = 2; + SizeSet16 = 2; + SizeInt32 = 4; + SizeCard32 = 4; + SizeReal = 4; + SizeLongReal = 8; + + String8Size = 8; + String32Size = 32; + String80Size = 80; + String400Size = 400; + + ParamDescrSize = 24; + TrMarkerNo = 10; + SwMarkerNo = 4; + SwHoldingNo = 16; + SwUserParamNo = 4; + SeUserParamNo1 = 4; + SeUserParamNo2 = 4; + GrStimParams = 10; + AmplifierStateSize = 400; + ScanParamsSize = 96; + Max_TcKind_M1 = 31; + + SizeStateVersion = 8; + SizeSerialNumber = 8; + SizeCalibDate = 16; + + + RootLevel = 0; + GroupLevel = 1; + SeriesLevel = 2; + SweepLevel = 3; + TraceLevel = 4; + + + LittleEndianBit = 0; + IsLeak = 1; + IsVirtual = 2; + IsImon = 3; + IsVmon = 4; + Clip = 5; + (* + DataKind -> meaning of bits: + - LittleEndianBit => byte sequence + "PowerPC Mac" = cleared + "Windows and Intel Mac" = set + - IsLeak + set if trace is a leak trace + - IsVirtual + set if trace is a virtual trace + - IsImon + -> set if trace was from Imon ADC + -> it flags a trace to be used to + compute LockIn traces from + -> limited to "main" traces, not "leaks"! + - IsVmon + -> set if trace was from Vmon ADC + - Clip + -> set if amplifier of trace was clipping + *) + + RecordingModeType = ( InOut, + OnCell, + OutOut, + WholeCell, + CClamp, + VClamp, + NoMode ); + + DataFormatType = ( int16, + int32, + real32, + real64 ); + + UserParamDescrType = RECORD + Name : String32Type; + Unit : String8Type; + END; (* RECORD *) + + (* AmplifierState = RECORD *) + see definition in AmplTreeFile_v9.txt + + (* LockInParams = RECORD *) + see definition in AmplTreeFile_v9.txt + + (* TraceRecord = RECORD *) + TrMark = 0; (* INT32 *) + TrLabel = 4; (* String32Type *) + TrTraceID = 36; (* INT32 *) + TrData = 40; (* INT32 *) + TrDataPoints = 44; (* INT32 *) + TrInternalSolution = 48; (* INT32 *) + TrAverageCount = 52; (* INT32 *) + TrLeakID = 56; (* INT32 *) + TrLeakTraces = 60; (* INT32 *) + TrDataKind = 64; (* SET16 *) + TrUseXStart = 66; (* BOOLEAN *) + TrTcKind = 67; (* BYTE *) + TrRecordingMode = 68; (* BYTE *) + TrAmplIndex = 69; (* CHAR *) + TrDataFormat = 70; (* BYTE *) + TrDataAbscissa = 71; (* BYTE *) + TrDataScaler = 72; (* LONGREAL *) + TrTimeOffset = 80; (* LONGREAL *) + TrZeroData = 88; (* LONGREAL *) + TrYUnit = 96; (* String8Type *) + TrXInterval = 104; (* LONGREAL *) + TrXStart = 112; (* LONGREAL *) + TrXUnit = 120; (* String8Type *) + TrYRange = 128; (* LONGREAL *) + TrYOffset = 136; (* LONGREAL *) + TrBandwidth = 144; (* LONGREAL *) + TrPipetteResistance = 152; (* LONGREAL *) + TrCellPotential = 160; (* LONGREAL *) + TrSealResistance = 168; (* LONGREAL *) + TrCSlow = 176; (* LONGREAL *) + TrGSeries = 184; (* LONGREAL *) + TrRsValue = 192; (* LONGREAL *) + TrGLeak = 200; (* LONGREAL *) + TrMConductance = 208; (* LONGREAL *) + TrLinkDAChannel = 216; (* INT32 *) + TrValidYrange = 220; (* BOOLEAN *) + TrAdcMode = 221; (* CHAR *) + TrAdcChannel = 222; (* INT16 *) + TrYmin = 224; (* LONGREAL *) + TrYmax = 232; (* LONGREAL *) + TrSourceChannel = 240; (* INT32 *) + TrExternalSolution = 244; (* INT32 *) + TrCM = 248; (* LONGREAL *) + TrGM = 256; (* LONGREAL *) + TrPhase = 264; (* LONGREAL *) + TrDataCRC = 272; (* CARD32 *) + TrCRC = 276; (* CARD32 *) + TrGS = 280; (* LONGREAL *) + TrSelfChannel = 288; (* INT32 *) + TrInterleaveSize = 292; (* INT32 *) + TrInterleaveSkip = 296; (* INT32 *) + TrImageIndex = 300; (* INT32 *) + TrTrMarkers = 304; (* ARRAY[0..9] OF LONGREAL *) + TrSECM_X = 384; (* LONGREAL *) + TrSECM_Y = 392; (* LONGREAL *) + TrSECM_Z = 400; (* LONGREAL *) + TrTrHolding = 408; (* LONGREAL *) + TrTcEnumerator = 416; (* INT32 *) + TrXTrace = 420; (* INT32 *) + TrIntSolValue = 424; (* LONGREAL *) + TrExtSolValue = 432; (* LONGREAL *) + TrIntSolName = 440; (* String32Size *) + TrExtSolName = 472; (* String32Size *) + TrDataPedestal = 504; (* LONGREAL *) + TraceRecSize = 512; (* = 64 * 8 *) + + (* SweepRecord = RECORD *) + SwMark = 0; (* INT32 *) + SwLabel = 4; (* String32Type *) + SwAuxDataFileOffset = 36; (* INT32 *) + SwStimCount = 40; (* INT32 *) + SwSweepCount = 44; (* INT32 *) + SwTime = 48; (* LONGREAL *) + SwTimer = 56; (* LONGREAL *) + SwSwUserParams = 64; (* ARRAY[0..3] OF LONGREAL *) + SwTemperature = 96; (* LONGREAL *) + SwOldIntSol = 104; (* INT32 *) + SwOldExtSol = 108; (* INT32 *) + SwDigitalIn = 112; (* SET16 *) + SwSweepKind = 114; (* SET16 *) + SwDigitalOut = 116; (* SET16 *) + SwFiller1 = 118; (* INT16 *) + SwSwMarkers = 120; (* ARRAY[0..3] OF LONGREAL, see SwMarkersNo *) + SwFiller2 = 152; (* INT32 *) + SwCRC = 156; (* CARD32 *) + SwSwHolding = 160; (* ARRAY[0..15] OF LONGREAL, see SwHoldingNo *) + SweepRecSize = 288; (* = 36 * 8 *) + + (* SeriesRecord = RECORD *) + SeMark = 0; (* INT32 *) + SeLabel = 4; (* String32Type *) + SeComment = 36; (* String80Type *) + SeSeriesCount = 116; (* INT32 *) + SeNumberSweeps = 120; (* INT32 *) + SeAmplStateOffset = 124; (* INT32 *) + SeAmplStateSeries = 128; (* INT32 *) + SeMethodTag = 132; (* INT32 *) + SeTime = 136; (* LONGREAL *) + SePageWidth = 144; (* LONGREAL *) + SeSwUserParamDescr = 152; (* ARRAY[0..3] OF UserParamDescrType = 4*40 *) + SeMethodName = 312; (* String32Type *) + SeSeUserParams1 = 344; (* ARRAY[0..3] OF LONGREAL *) + SeLockInParams = 376; (* SeLockInSize = 96, see "Pulsed.de" *) + SeAmplifierState = 472; (* AmplifierStateSize = 400 *) + SeUsername = 872; (* String80Type *) + SeSeUserParamDescr1 = 952; (* ARRAY[0..3] OF UserParamDescrType = 4*40 *) + SeFiller1 = 1112; (* INT32 *) + SeCRC = 1116; (* CARD32 *) + SeSeUserParams2 = 1120; (* ARRAY[0..3] OF LONGREAL *) + SeSeUserParamDescr2 = 1152; (* ARRAY[0..3] OF UserParamDescrType = 4*40 *) + SeScanParams = 1312; (* ScanParamsSize = 96 *) + SeriesRecSize = 1408; (* = 176 * 8 *) + + (* GroupRecord = RECORD *) + GrMark = 0; (* INT32 *) + GrLabel = 4; (* String32Size *) + GrText = 36; (* String80Size *) + GrExperimentNumber = 116; (* INT32 *) + GrGroupCount = 120; (* INT32 *) + GrCRC = 124; (* CARD32 *) + GrMatrixWidth = 128; (* LONGREAL *) + GrMatrixHeight = 136; (* LONGREAL *) + GroupRecSize = 144; (* = 18 * 8 *) + + (* RootRecord = RECORD *) + RoVersion = 0; (* INT32 *) + RoMark = 4; (* INT32 *) + RoVersionName = 8; (* String32Type *) + RoAuxFileName = 40; (* String80Type *) + RoRootText = 120; (* String400Type *) + RoStartTime = 520; (* LONGREAL *) + RoMaxSamples = 528; (* INT32 *) + RoCRC = 532; (* CARD32 *) + RoFeatures = 536; (* SET16 *) + RoFiller1 = 538; (* INT16 *) + RoFiller2 = 540; (* INT32 *) + RoTcEnumerator = 544; (* ARRAY[0..Max_TcKind_M1] OF INT16 *) + RoTcKind = 608; (* ARRAY[0..Max_TcKind_M1] OF INT8 *) + RootRecSize = 640; (* = 80 * 8 *) + diff --git a/@HEKA_Importer/HEKA_FileFormat/FileFormat_2x90/SolutionsFile_v9.txt b/@HEKA_Importer/HEKA_FileFormat/FileFormat_2x90/SolutionsFile_v9.txt new file mode 100644 index 0000000..ee855a0 --- /dev/null +++ b/@HEKA_Importer/HEKA_FileFormat/FileFormat_2x90/SolutionsFile_v9.txt @@ -0,0 +1,41 @@ + + PatchMaster v2.60, 24-Jan-2011 + + To find the solution belonging to a Trace locate that Solution record with a + SoNumber value equal to the solution value stored in Trace.InternalSolution + and Trace.ExternalSolution. + + SizeInt16 = 2; + SizeInt32 = 4; + SizeReal = 4; + ChemicalNameSize = 30; + SolutionNameSize = 80; + + RootLevel = 0; + SolutionLevel = 1; + ChemicalLevel = 2; + + (* ChemicalRecord = RECORD *) + ChConcentration = 0; (* REAL *) + ChName = 4; (* ChemicalNameSize *) + ChSpare1 = 34; (* INT16 *) + ChCRC = 36; (* CARD32 *) + ChemicalSize = 40; + + (* SolutionRecord = RECORD *) + SoNumber = 0; (* INT32 *) + SoName = 4; (* SolutionNameSize *) + SoNumeric = 84; (* REAL *) + SoNumericName = 88; (* ChemicalNameSize *) + SopH = 118; (* REAL *) + SopHCompound = 122; (* ChemicalNameSize *) + SoOsmol = 152; (* REAL *) + SoCRC = 156; (* CARD32 *) + SolutionSize = 160; + + (* RootRecord = RECORD *) + RoVersion = 0; (* INT16 *) + RoDataBaseName = 2; (* SolutionNameSize *) + RoSpare1 = 82; (* INT16 *) + RoCRC = 84; (* CARD32 *) + RootSize = 88; diff --git a/@HEKA_Importer/HEKA_FileFormat/FileFormat_2x90/StimFile_v9.txt b/@HEKA_Importer/HEKA_FileFormat/FileFormat_2x90/StimFile_v9.txt new file mode 100644 index 0000000..2d9518a --- /dev/null +++ b/@HEKA_Importer/HEKA_FileFormat/FileFormat_2x90/StimFile_v9.txt @@ -0,0 +1,259 @@ + + PatchMaster v2.74, 28-Nov-2014 + + SizeByte = 1; + SizeChar = 1; + SizeEnum = 1; + SizeBoolean = 1; + SizeInt16 = 2; + SizeCard16 = 2; + SizeSet16 = 2; + SizeInt32 = 4; + SizeCard32 = 4; + SizeReal = 4; + SizeLongReal = 8; + + String8Size = 8; + String32Size = 32; + + StimParams = 10; + StimParamChars = 320; + + RootLevel = 0; + StimulationLevel = 1; + ChannelLevel = 2; + StimSegmentLevel = 3; + + + (* + CompressionMode : Specifies how to the data + -> meaning of bits: + bit 0 (CompReal) -> high = store as real + low = store as int16 + bit 1 (CompMean) -> high = use mean + low = use single sample + bit 2 (CompFilter) -> high = use digital filter + *) + + (* + StimToDacID : Specifies how to convert the Segment "Voltage" to + the actual voltage sent to the DAC + -> meaning of bits: + bit 0 (UseStimScale) -> use StimScale + bit 1 (UseRelative) -> relative to Vmemb + bit 2 (UseFileTemplate) -> use file template + bit 3 (UseForLockIn) -> use for LockIn computation + bit 4 (UseForWavelength) + bit 5 (UseScaling) + bit 6 (UseForChirp) + bit 7 (UseForImaging) + bit 14 (UseReserved) + bit 15 (UseReserved) + *) + + SegmentClass = ( SegmentConstant, + SegmentRamp, + SegmentContinuous, + SegmentConstSine, + SegmentSquarewave, + SegmentChirpwave ); + + IncrementModeType = ( ModeInc, + ModeDec, + ModeIncInterleaved, + ModeDecInterleaved, + ModeAlternate, + ModeLogInc, + ModeLogDec, + ModeLogIncInterleaved, + ModeLogDecInterleaved, + ModeLogAlternate ); + + ExtTriggerType = ( TrigNone, + TrigSeries, + TrigSweep, + TrigSweepNoLeak ); + + AmplModeType = ( AnyAmplMode, + VCAmplMode, + CCAmplMode, + IDensityMode ); + + AutoRangingType = ( AutoRangingOff, + AutoRangingPeak, + AutoRangingMean, + AutoRangingRelSeg ); + + AdcType = ( AdcOff, + Analog, + Digitals, + Digital, + AdcVirtual ); + + LeakStoreType = ( LNone, + LStoreAvg, + LStoreEach, + LNoStore ); + + LeakHoldType = ( Labs, + Lrel, + LabsLH, + LrelLH ); + + BreakType = ( NoBreak, + BreakPos, + BreakNeg ); + + LeakCompType = ( LeakCompSoft, + LeakCompHard ); + + SegStoreType = ( SegNoStore, + SegStore, + SegStoreStart, + SegStoreEnd ); + + + (* StimSegmentRecord = RECORD *) + seMark = 0; (* INT32 *) + seClass = 4; (* BYTE *) + seStoreKind = 5; (* BYTE *) + seVoltageIncMode = 6; (* BYTE *) + seDurationIncMode = 7; (* BYTE *) + seVoltage = 8; (* LONGREAL *) + seVoltageSource = 16; (* INT32 *) + seDeltaVFactor = 20; (* LONGREAL *) + seDeltaVIncrement = 28; (* LONGREAL *) + seDuration = 36; (* LONGREAL *) + seDurationSource = 44; (* INT32 *) + seDeltaTFactor = 48; (* LONGREAL *) + seDeltaTIncrement = 56; (* LONGREAL *) + seFiller1 = 64; (* INT32 *) + seCRC = 68; (* CARD32 *) + seScanRate = 72; (* LONGREAL *) + StimSegmentRecSize = 80; (* = 10 * 8 *) + + (* ChannelRecord = RECORD *) + chMark = 0; (* INT32 *) + chLinkedChannel = 4; (* INT32 *) + chCompressionFactor = 8; (* INT32 *) + chYUnit = 12; (* String8Type *) + chAdcChannel = 20; (* INT16 *) + chAdcMode = 22; (* BYTE *) + chDoWrite = 23; (* BOOLEAN *) + stLeakStore = 24; (* BYTE *) + chAmplMode = 25; (* BYTE *) + chOwnSegTime = 26; (* BOOLEAN *) + chSetLastSegVmemb = 27; (* BOOLEAN *) + chDacChannel = 28; (* INT16 *) + chDacMode = 30; (* BYTE *) + chHasLockInSquare = 31; (* BYTE *) + chRelevantXSegment = 32; (* INT32 *) + chRelevantYSegment = 36; (* INT32 *) + chDacUnit = 40; (* String8Type *) + chHolding = 48; (* LONGREAL *) + chLeakHolding = 56; (* LONGREAL *) + chLeakSize = 64; (* LONGREAL *) + chLeakHoldMode = 72; (* BYTE *) + chLeakAlternate = 73; (* BOOLEAN *) + chAltLeakAveraging = 74; (* BOOLEAN *) + chLeakPulseOn = 75; (* BOOLEAN *) + chStimToDacID = 76; (* SET16 *) + chCompressionMode = 78; (* SET16 *) + chCompressionSkip = 80; (* INT32 *) + chDacBit = 84; (* INT16 *) + chHasLockInSine = 86; (* BOOLEAN *) + chBreakMode = 87; (* BYTE *) + chZeroSeg = 88; (* INT32 *) + chStimSweep = 92; (* INT32 *) + chSine_Cycle = 96; (* LONGREAL *) + chSine_Amplitude = 104; (* LONGREAL *) + chLockIn_VReversal = 112; (* LONGREAL *) + chChirp_StartFreq = 120; (* LONGREAL *) + chChirp_EndFreq = 128; (* LONGREAL *) + chChirp_MinPoints = 136; (* LONGREAL *) + chSquare_NegAmpl = 144; (* LONGREAL *) + chSquare_DurFactor = 152; (* LONGREAL *) + chLockIn_Skip = 160; (* INT32 *) + chPhoto_MaxCycles = 164; (* INT32 *) + chPhoto_SegmentNo = 168; (* INT32 *) + chLockIn_AvgCycles = 172; (* INT32 *) + chImaging_RoiNo = 176; (* INT32 *) + chChirp_Skip = 180; (* INT32 *) + chChirp_Amplitude = 184; (* LONGREAL *) + chPhoto_Adapt = 192; (* BYTE *) + chSine_Kind = 193; (* BYTE *) + chChirp_PreChirp = 194; (* BYTE *) + chSine_Source = 195; (* BYTE *) + chSquare_NegSource = 196; (* BYTE *) + chSquare_PosSource = 197; (* BYTE *) + chChirp_Kind = 198; (* BYTE *) + chChirp_Source = 199; (* BYTE *) + chDacOffset = 200; (* LONGREAL *) + chAdcOffset = 208; (* LONGREAL *) + chTraceMathFormat = 216; (* BYTE *) + chHasChirp = 217; (* BOOLEAN *) + chSquare_Kind = 218; (* BYTE *) + chFiller1 = 219; (* ARRAY[0..5] OF CHAR *) + + chSquare_BaseIncr = 224; (* LONGREAL *) + chSquare_Cycle = 232; (* LONGREAL *) + chSquare_PosAmpl = 240; (* LONGREAL *) + chCompressionOffset = 248; (* INT32 *) + chPhotoMode = 252; (* INT32 *) + chBreakLevel = 256; (* LONGREAL *) + chTraceMath = 264; (* String128Type *) + chFiller2 = 392; (* INT32 *) + chCRC = 396; (* CARD32 *) + ChannelRecSize = 400; (* = 50 * 8 *) + + (* StimulationRecord = RECORD *) + stMark = 0; (* INT32 *) + stEntryName = 4; (* String32Type *) + stFileName = 36; (* String32Type *) + stAnalName = 68; (* String32Type *) + stDataStartSegment = 100; (* INT32 *) + stDataStartTime = 104; (* LONGREAL *) + stSampleInterval = 112; (* LONGREAL *) + stSweepInterval = 120; (* LONGREAL *) + stLeakDelay = 128; (* LONGREAL *) + stFilterFactor = 136; (* LONGREAL *) + stNumberSweeps = 144; (* INT32 *) + stNumberLeaks = 148; (* INT32 *) + stNumberAverages = 152; (* INT32 *) + stActualAdcChannels = 156; (* INT32 *) + stActualDacChannels = 160; (* INT32 *) + stExtTrigger = 164; (* BYTE *) + stNoStartWait = 165; (* BOOLEAN *) + stUseScanRates = 166; (* BOOLEAN *) + stNoContAq = 167; (* BOOLEAN *) + stHasLockIn = 168; (* BOOLEAN *) + stOldStartMacKind = 169; (* CHAR *) + stOldEndMacKind = 170; (* BOOLEAN *) + stAutoRange = 171; (* BYTE *) + stBreakNext = 172; (* BOOLEAN *) + stIsExpanded = 173; (* BOOLEAN *) + stLeakCompMode = 174; (* BOOLEAN *) + stHasChirp = 175; (* BOOLEAN *) + stOldStartMacro = 176; (* String32Type *) + stOldEndMacro = 208; (* String32Type *) + sIsGapFree = 240; (* BOOLEAN *) + sHandledExternally = 241; (* BOOLEAN *) + stFiller1 = 242; (* BOOLEAN *) + stFiller2 = 243; (* BOOLEAN *) + stCRC = 244; (* CARD32 *) + StimulationRecSize = 248; (* = 31 * 8 *) + + (* RootRecord = RECORD *) + roVersion = 0; (* INT32 *) + roMark = 4; (* INT32 *) + roVersionName = 8; (* String32Type *) + roMaxSamples = 40; (* INT32 *) + roFiller1 = 44; (* INT32 *) + (* StimParams = 10 *) + (* StimParamChars = 320 *) + roParams = 48; (* ARRAY[0..9] OF LONGREAL *) + roParamText = 128; (* ARRAY[0..9],[0..31]OF CHAR *) + roReserved = 448; (* String128Type *) + roFiller2 = 576; (* INT32 *) + roCRC = 580; (* CARD32 *) + RootRecSize = 584; (* = 73 * 8 *) diff --git a/@HEKA_Importer/HEKA_FileFormat/FileFormat_2x90/TimeFormat.txt b/@HEKA_Importer/HEKA_FileFormat/FileFormat_2x90/TimeFormat.txt new file mode 100644 index 0000000..2082bdb --- /dev/null +++ b/@HEKA_Importer/HEKA_FileFormat/FileFormat_2x90/TimeFormat.txt @@ -0,0 +1,80 @@ + + PatchMaster v2.90 + +Time is stored as seconds from 01-Jan-1990. +To convert the stored time into a string, proceed as follows: + +MacOS + JanFirst1990 - The number of seconds between 1/1/1904 (Apple's + beginning of time) and 1/1/1990, the beginning of + time for PowerMod's environment. + + JanFirst1990 = 1580970496.0; + MacTime = (int)( StoredTime - JanFirst1990 ); + + Pass MacTime to the API function DateTimeUtils.SecondsToDate + to convert it to a string + +Windows + Windows uses 01-Jan-1601 as its starting point in calculating dates. + + Pass StoredTime to the function PatchMasterSecondsToFileTime or + PatchMasterSecondsToDate below to convert it to a standard Windows + format. + +#define MAC_BASE 9561652096.0 +#define HIGH_DWORD 4294967296.0 +#define JanFirst1990 1580970496.0 + +// Function PatchMasterSecondsToFileTime +// Convert seconds to FILETIME. +// In converting double to DWORD we must be carefull because the +// double will first be converted to a signed int. +// Do the operations modulo 2^31. +// Get the next bit from the high DWORD and then shift high DWORD +// throwing away the highest bit. + +void PatchMasterSecondsToFileTime( double time, FILETIME* file_time ) +{ + time -= JanFirst1990; + + if (time < 0.0) + time += HIGH_DWORD; + + time += MAC_BASE; + + time *= 10000000.0; + + file_time->dwHighDateTime = (DWORD) (time / (HIGH_DWORD / 2.0)); + + file_time->dwLowDateTime = (DWORD) + (time - (double) file_time->dwHighDateTime * (HIGH_DWORD / 2.0)); + + file_time->dwLowDateTime |= ((file_time->dwHighDateTime & 1) << 31); + + file_time->dwHighDateTime >>= 1; +} + +void PatchMasterSecondsToDate( double storedTime, SYSTEMTIME* system_time ) +{ + FILETIME file_time; + PatchMasterSecondsToFileTime( storedTime, &file_time ); + FileTimeToSystemTime( &file_time, system_time ); +} + + +Example 1: applied to the root date of "DemoV9Bundle.dat": +1. RootTime = 221667551 +2. subtract JanFirst1990 time = 221667551 - 1580970496 = -1359302944 +3. is it < 0 ? + yes => add HIGH_DWORD time = -1359302944 + 4294967296 = 2935664351 +4. add correction for Windows time = 2935664351 + 9561652096 = 12497316447 +5. convert to date date = 09-Jan-1997 + +Example 2: applied to the root date of "Malcom.dat": +1. RootTime = 4922414972 +2. subtract JanFirst1990 time = 4922414972 - 1580970496 = 3341444476 +3. is it < 0 ? + no +4. add correction for Windows time = 3341444476 + 9561652096 = 12903096572 +5. convert to date date = 19-Nov-2009 \ No newline at end of file diff --git a/@HEKA_Importer/HEKA_FileFormat/FileFormat_v1000/AmplTreeFile_v1000.txt b/@HEKA_Importer/HEKA_FileFormat/FileFormat_v1000/AmplTreeFile_v1000.txt new file mode 100644 index 0000000..5fe3544 --- /dev/null +++ b/@HEKA_Importer/HEKA_FileFormat/FileFormat_v1000/AmplTreeFile_v1000.txt @@ -0,0 +1,220 @@ + + PatchMaster v2.90.4, Patchmaster Next + + SizeByte = 1; + SizeChar = 1; + SizeEnum = 1; + SizeBoolean = 1; + SizeInt16 = 2; + SizeCard16 = 2; + SizeSet16 = 2; + SizeInt32 = 4; + SizeCard32 = 4; + SizeReal = 4; + SizeLongReal = 8; + + String8Size = 8; + String32Size = 32; + + + RootLevel = 0; + SeriesLevel = 1; + StateLevel = 2; + + + AmplifierType = ( Epc7Ampl, + Epc8Ampl, + Epc9Ampl, + Epc10Ampl, + Epc10PlusAmpl ); + + ADBoardType = ( ITC16Board, + ITC18Board, + LIH1600Board ); + + Modes = ( TestMode, + VCMode, + CCMode, + NoMode => (* AmplifierState is invalid *) ); + + + (* AmplifierState = RECORD *) + sStateVersion = 0; (* 8 = SizeStateVersion *) + sCurrentGain = 8; (* LONGREAL *) + sF2Bandwidth = 16; (* LONGREAL *) + sF2Frequency = 24; (* LONGREAL *) + sRsValue = 32; (* LONGREAL *) + sRsFraction = 40; (* LONGREAL *) + sGLeak = 48; (* LONGREAL *) + sCFastAmp1 = 56; (* LONGREAL *) + sCFastAmp2 = 64; (* LONGREAL *) + sCFastTau = 72; (* LONGREAL *) + sCSlow = 80; (* LONGREAL *) + sGSeries = 88; (* LONGREAL *) + sVCStimDacScale = 96; (* LONGREAL *) + sCCStimScale = 104; (* LONGREAL *) + sVHold = 112; (* LONGREAL *) + sLastVHold = 120; (* LONGREAL *) + sVpOffset = 128; (* LONGREAL *) + sVLiquidJunction = 136; (* LONGREAL *) + sCCIHold = 144; (* LONGREAL *) + sCSlowStimVolts = 152; (* LONGREAL *) + sCCTrackVHold = 160; (* LONGREAL *) + sTimeoutCSlow = 168; (* LONGREAL *) + sSearchDelay = 176; (* LONGREAL *) + sMConductance = 184; (* LONGREAL *) + sMCapacitance = 192; (* LONGREAL *) + sSerialNumber = 200; (* 8 = SizeSerialNumber *) + + sE9Boards = 208; (* INT16 *) + sCSlowCycles = 210; (* INT16 *) + sIMonAdc = 212; (* INT16 *) + sVMonAdc = 214; (* INT16 *) + + sMuxAdc = 216; (* INT16 *) + sTestDac = 218; (* INT16 *) + sStimDac = 220; (* INT16 *) + sStimDacOffset = 222; (* INT16 *) + + sMaxDigitalBit = 224; (* INT16 *) + sHasCFastHigh = 226; (* BYTE *) + sCFastHigh = 227; (* BYTE *) + sHasBathSense = 228; (* BYTE *) + sBathSense = 229; (* BYTE *) + sHasF2Bypass = 230; (* BYTE *) + sF2Mode = 231; (* BYTE *) + + sAmplKind = 232; (* BYTE *) + sIsEpc9N = 233; (* BYTE *) + sADBoard = 234; (* BYTE *) + sBoardVersion = 235; (* BYTE *) + sActiveE9Board = 236; (* BYTE *) + sMode = 237; (* BYTE *) + sRange = 238; (* BYTE *) + sF2Response = 239; (* BYTE *) + + sRsOn = 240; (* BYTE *) + sCSlowRange = 241; (* BYTE *) + sCCRange = 242; (* BYTE *) + sCCGain = 243; (* BYTE *) + sCSlowToTestDac = 244; (* BYTE *) + sStimPath = 245; (* BYTE *) + sCCTrackTau = 246; (* BYTE *) + sWasClipping = 247; (* BYTE *) + + sRepetitiveCSlow = 248; (* BYTE *) + sLastCSlowRange = 249; (* BYTE *) + sOld1 = 250; (* BYTE *) + sCanCCFast = 251; (* BYTE *) + sCanLowCCRange = 252; (* BYTE *) + sCanHighCCRange = 253; (* BYTE *) + sCanCCTracking = 254; (* BYTE *) + sHasVmonPath = 255; (* BYTE *) + + sHasNewCCMode = 256; (* BYTE *) + sSelector = 257; (* CHAR *) + sHoldInverted = 258; (* BYTE *) + sAutoCFast = 259; (* BYTE *) + sAutoCSlow = 260; (* BYTE *) + sHasVmonX100 = 261; (* BYTE *) + sTestDacOn = 262; (* BYTE *) + sQMuxAdcOn = 263; (* BYTE *) + + sImon1Bandwidth = 264; (* LONGREAL *) + sStimScale = 272; (* LONGREAL *) + + sGain = 280; (* BYTE *) + sFilter1 = 281; (* BYTE *) + sStimFilterOn = 282; (* BYTE *) + sRsSlow = 283; (* BYTE *) + sOld2 = 284; (* BYTE *) + sCCCFastOn = 285; (* BYTE *) + sCCFastSpeed = 286; (* BYTE *) + sF2Source = 287; (* BYTE *) + + sTestRange = 288; (* BYTE *) + sTestDacPath = 289; (* BYTE *) + sMuxChannel = 290; (* BYTE *) + sMuxGain64 = 291; (* BYTE *) + sVmonX100 = 292; (* BYTE *) + sIsQuadro = 293; (* BYTE *) + sF1Mode = 294; (* BYTE *) + sOld3 = 295; (* BYTE *) + + sStimFilterHz = 296; (* LONGREAL *) + sRsTau = 304; (* LONGREAL *) + sDacToAdcDelay = 312; (* LONGREAL *) + sInputFilterTau = 320; (* LONGREAL *) + sOutputFilterTau = 328; (* LONGREAL *) + sVmonFactor = 336; (* LONGREAL *) + sCalibDate = 344; (* 16 = SizeCalibDate *) + sVmonOffset = 360; (* LONGREAL *) + + sEEPROMKind = 368; (* BYTE *) + sVrefX2 = 369; (* BYTE *) + sHasVrefX2AndF2Vmon = 370; (* BYTE *) + sSpare1 = 371; (* BYTE *) + sSpare2 = 372; (* BYTE *) + sSpare3 = 373; (* BYTE *) + sSpare4 = 374; (* BYTE *) + sSpare5 = 375; (* BYTE *) + + sCCStimDacScale = 376; (* LONGREAL *) + sVmonFiltBandwidth = 384; (* LONGREAL *) + sVmonFiltFrequency = 392; (* LONGREAL *) + AmplifierStateSize = 400; (* = 50 * 8 *) + + + (* LockInParams = RECORD *) + loExtCalPhase = 0; (* LONGREAL *) + loExtCalAtten = 8; (* LONGREAL *) + loPLPhase = 16; (* LONGREAL *) + loPLPhaseY1 = 24; (* LONGREAL *) + loPLPhaseY2 = 32; (* LONGREAL *) + loUsedPhaseShift = 40; (* LONGREAL *) + loUsedAttenuation = 48; (* LONGREAL *) + loSpare = 56; (* LONGREAL *) + loExtCalValid = 64; (* BOOLEAN *) + loPLPhaseValid = 65; (* BOOLEAN *) + loLockInMode = 66; (* BYTE *) + loCalMode = 67; (* BYTE *) + loSpares = 68; (* remaining *) + LockInParamsSize = 96; + + + (* AmplStateRecord = RECORD *) + AmMark = 0; (* INT32 *) + AmStateCount = 4; (* INT32 *) + AmStateVersion = 8; (* CHAR *) + AmFiller1 = 9; (* BYTE *) + AmFiller2 = 10; (* BYTE *) + AmFiller3 = 11; (* BYTE *) + AmFiller4 = 12; (* INT32 *) + AmLockInParams = 16; (* LockInParamsSize = 96 *) + AmAmplifierState = 112; (* AmplifierStateSize = 400 *) + AmIntSol = 512; (* INT32 *) + AmExtSol = 516; (* INT32 *) + AmFiller5 = 520; (* spares: 36 bytes *) + AmCRC = 556; (* CARD32 *) + StateRecSize = 560; (* = 70 * 8 *) + + (* SeriesRecord = RECORD *) + SeMark = 0; (* INT32 *) + SeSeriesCount = 4; (* INT32 *) + SeFiller1 = 8; (* INT32 *) + SeCRC = 12; (* CARD32 *) + SeriesRecSize = 16; (* = 2 * 8 *) + + (* RootRecord = RECORD *) + RoVersion = 0; (* INT32 *) + RoMark = 4; (* INT32 *) + RoVersionName = 8; (* String32Type *) + RoAmplifierName = 40; (* String32Type *) + RoAmplifier = 72; (* CHAR *) + RoADBoard = 73; (* CHAR *) + RoCreator = 74; (* CHAR *) + RoFiller1 = 75; (* BYTE *) + RoCRC = 76; (* CARD32 *) + RootRecSize = 80; (* = 10 * 8 *) + (* END RootRecord *) + diff --git a/@HEKA_Importer/HEKA_FileFormat/FileFormat_v1000/AnalysisFile_v11.txt b/@HEKA_Importer/HEKA_FileFormat/FileFormat_v1000/AnalysisFile_v11.txt new file mode 100644 index 0000000..ec317c8 --- /dev/null +++ b/@HEKA_Importer/HEKA_FileFormat/FileFormat_v1000/AnalysisFile_v11.txt @@ -0,0 +1,318 @@ + + PatchMaster v2.90.4 / Patchmaster Next + + SizeByte = 1; + SizeChar = 1; + SizeEnum = 1; + SizeBoolean = 1; + SizeInt16 = 2; + SizeCard16 = 2; + SizeSet16 = 2; + SizeInt32 = 4; + SizeCard32 = 4; + SizeReal = 4; + SizeLongReal = 8; + + String8Size = 8; + String32Size = 32; + String64Size = 64; + MaxGraphs = 12; + + RootLevel = 0; + MethodLevel = 1; + FunctionLevel = 2; + + FunctionType = ( SweepCountAbsc, (* general *) + TimeAbsc, + TimerAbsc, + RealtimeAbsc, + + SegAmplitude, (* X segment property *) + SegDuration, + ScanRateAbsc, + + ExtremumMode, (* Y analysis *) + MaximumMode, + MinimumMode, + MeanMode, + IntegralMode, + VarianceMode, + SlopeMode, + TimeToExtrMode, + AnodicChargeMode, (* potentiostat *) + CathodChargeMode, + + (* patch clamp *) + CSlowMode, (* potmaster: spare *) + RSeriesMode, (* potmaster: spare *) + UserParam1Mode, + UserParam2Mode, + + LockInCMMode, (* lock-in *) + LockInGMMode, + LockInGSMode, + + SeriesTime, (* misk *) + StimulusMode, + SegmentTimeAbs, + + OpEquationMode, (* math *) + ConstantMode, + OperatorPlusMode, + OperatorMinusMode, + OperatorMultMode, + OperatorDivMode, + OperatorAbsMode, + OperatorLogMode, + OperatorSqrMode, + OperatorInvMode, + OperatorInvLogMode, + OperatorInvSqrMode, + + TraceMode, (* trace *) + QMode, + InvTraceMode, + InvQMode, + LnTraceMode, + LnQMode, + LogTraceMode, + LogQMode, + TraceXaxisMode, + + FreqMode, (* spectra *) + DensityMode, + + HistoAmplMode, (* histogram *) + HistoBinsMode, + + OnlineIndex, + ExtrAmplMode, + SegmentTimeRel, + + (* remaning trace parameters *) + CellPotential, (* potmaster: OCP *) + SealResistance, (* potmaster: ElectrodeArea *) + RsValue, (* potmaster: spare *) + GLeak, (* potmaster: spare *) + MConductance, (* potmaster: spare *) + + Temperature, (* sweep parameters *) + PipettePressure, (* potmaster: spare *) + InternalSolution, + ExternalSolution, + DigitalIn, + + OperatorBitInMode, + ReversalMode, + LockInPhase, + LockInFreq, + TotMeanMode, (* obsolete: replaced by MeanMode + CursorKind *) + DiffMode, + IntSolValue, + ExtSolValue, + OperatorAtanMode, + OperatorInvAtanMode, + + TimeToMinMode, + TimeToMaxMode, + TimeToThreshold, + + TraceEquationMode, + ThresholdAmpl, + + XposMode, + YposMode, + ZposMode, + + TraceCountMode, + + AP_Baseline, + AP_MaximumAmpl, + AP_MaximumTime, + AP_MinimumAmpl, + AP_MinimumTime, + AP_RiseTime1Dur, + AP_RiseTime1Slope, + AP_RiseTime1Time, + AP_RiseTime2Dur, + AP_RiseTime2Slope, + AP_RiseTime2Time, + AP_Tau, + + MatrixXindexMode, + MatrixYindexMode, + YatX_Mode, + ThresholdCount, + SECM_3Dx, + SECM_3Dy, + InterceptMode, + MinAmplMode, + MaxAmplMode, + TauMode, + ZeroOffset, + LockInAmpl, + + UserParam3Mode, + UserParam4Mode, + UserParam5Mode, + UserParam6Mode, + UserParam7Mode, + UserParam8Mode, + UserParam9Mode, + UserParam10Mode + ); + + TicDirectionType = ( TicLeft, TicRight, TicBoth ); + + ScaleType = ( ScaleFixed, ScaleSeries, ScaleSweeps ); + + AxisLevelType = ( Min, Zero, Max ); + + AxisTypeType = ( ScaleLinear, + ScaleLog, + ScaleInverse, + ScaleSqrt, + ScaleSquare ); + + MarkerKindType = ( MarkerPoint, + MarkerPlus, + MarkerStar, + MarkerDiamond, + MarkerX, + MarkerSquare ); + + GraphWindowType = ( Win0, Win1, Win2 ); + + NormalizeType = ( NormalizeNone, NormalizeMax, NormalizeMinMax ); + + CursorType = ( Cursor_Segment, (* cursor relative to segment *) + Cursor_Trace ); (* cursor relative to trace *) + + BaselineType = ( Baseline_Zero, (* baseline relative to zero *) + Baseline_Cursors, (* baseline = intersection with cursors *) + Baseline_Auto ); (* baseline = intersection with cursors *) + + SearchDirectionType = ( Search_All, + Search_Positive, + Search_Negative ); + + + (* FunctionRecord = RECORD *) + fnMark = 0; (* INT32 *) + fnName = 4; (* String32Size *) + fnUnit = 36; (* String8Size *) + fnLeftOperand = 44; (* INT16 *) + fnRightOperand = 46; (* INT16 *) + fnLeftBound = 48; (* LONGREAL *) + fnRightBound = 56; (* LONGREAL *) + fnConstant = 64; (* LONGREAL *) + fnXSegmentOffset = 72; (* INT32 *) + fnYSegmentOffset = 76; (* INT32 *) + fnTcEnumarator = 80; (* INT16 *) + fnFunction = 82; (* BYTE *) + fnDoNotebook = 83; (* BOOLEAN *) + fnNoFit = 84; (* BOOLEAN *) + fnNewName = 85; (* BOOLEAN *) + fnTargetValue = 86; (* INT16 *) + fnCursorKind = 88; (* BYTE *) + fnTcKind1 = 89; (* 3 BYTE *) + fnTcKind2 = 90; (* 3 BYTE *) + fnCursorSource = 91; (* BYTE *) + fnCRC = 92; (* CARD32 *) + fnEquation = 96; (* String64Size *) + fnBaselineMode = 160; (* BYTE *) + fnSearchDirection = 161; (* BYTE *) + fnSourceValue = 162; (* INT16 *) + fnCursorAnker = 164; (* INT16 *) + fnSpare1 = 165; (* INT16 *) + FunctionRecSize = 168; (* = 21 * 8 *) + + + (* ScalingRecord = RECORD *) + scMinValue = 0; (* LONGREAL *) + scMaxValue = 8; (* LONGREAL *) + scGridFactor = 16; (* LONGREAL *) + scTicLength = 24; (* INT16 *) + scTicNumber = 26; (* INT16 *) + scTicDirection = 28; (* BYTE *) + scAxisLevel = 29; (* BYTE *) + scAxisType = 30; (* BYTE *) + scScaleMode = 31; (* BYTE *) + scNoUnit = 32; (* BOOLEAN *) + scObsolete = 33; (* BOOLEAN *) + scZeroLine = 34; (* BOOLEAN *) + scGrid = 35; (* BOOLEAN *) + scNice = 36; (* BOOLEAN *) + scLabel = 37; (* BOOLEAN *) + scCentered = 38; (* BOOLEAN *) + scIncludeZero = 39; (* BOOLEAN *) + ScalingRecSize = 40; (* = 5 * 8 *) + + + (* EntryRecord = RECORD *) + enXWave = 0; (* INT16 *) + enYWave = 2; (* INT16 *) + enMarkerSize = 4; (* INT16 *) + enMarkerColorRed = 6; (* CARD16 *) + enMarkerColorGreen = 8; (* CARD16 *) + enMarkerColorBlue = 10; (* CARD16 *) + enMarkerKind = 12; (* BYTE *) + enEActive = 13; (* BOOLEAN *) + enLine = 14; (* BOOLEAN *) + enTraceColor = 15; (* BOOLEAN *) + EntryRecSize = 16; (* = 2 * 8 *) + + + (* GraphRecord = RECORD *) + grGActive = 0; (* BOOLEAN *) + grOverlay = 1; (* BOOLEAN *) + grWrap = 2; (* CHAR *) + grOvrlSwp = 3; (* BOOLEAN *) + grNormalize = 4; (* BYTE *) + grSort = 5; (* BOOLEAN *) + grSpare1 = 6; (* BYTE *) + grSpare2 = 7; (* BYTE *) + grXScaling = 8; (* ScalingRecord; *) + grYScaling = 48; (* ScalingRecord *) + grEntry0 = 88; (* EntryRecSize *) + grEntry1 = 104; (* EntryRecSize *) + grEntry2 = 120; (* EntryRecSize *) + grEntry3 = 136; (* EntryRecSize *) + GraphRecSize = 152; (* = 19 * 8 *) + + + (* MethodRecord = RECORD *) + oaMark = 0; (* INT32 *) + oaEntryName = 4; (* String32Size *) + oaSharedXWin1 = 36; (* BOOLEAN *) + oaSharedXWin2 = 37; (* BOOLEAN *) + oa1 = 38; (* BOOLEAN *) + oa2 = 39; (* BOOLEAN *) + oaGraph0 = 40; (* MaxFileGraphs * GraphRecSize = 1824 *) + oa3 = 1864; (* INT32 *) + oaCRC = 1868; (* CARD32 *) + oaHeaders = 1872; (* MaxFileGraphs * String32Size = 384 *) + oaLastXmin = 2256; (* MaxFileGraphs * LONGREAL = 96 *) + oaLastXmax = 2352; (* MaxFileGraphs * LONGREAL = 96 *) + oaLastYmin = 2448; (* MaxFileGraphs * LONGREAL = 96 *) + oaLastYmax = 2544; (* MaxFileGraphs * LONGREAL = 96 *) + MethodRecSize = 2640; (* = 330 * 8 *) + + + (* RootRecord = RECORD *) + (* + NOTE: The "Version" field must be at offset zero in the file + while the "Mark" field must be at offset zero in RAM! + *) + roVersion = 0; (* INT32 *) + roMark = 4; (* INT32 *) + roVersionName = 8; (* String32Size *) + roObsolete = 40; (* BYTE *) (* was StimControl *) + roMaxTraces = 41; (* CHAR *) + roWinDefined = 42; (* BOOLEAN *) + rt1 = 43; (* BYTE *) + roCRC = 44; (* CARD32 *) + roWinNr = 48; (* MaxFileGraphs *) + rt2 = 60; (* INT32 *) + RootRecSize = 64; (* = 6 * 8 *) + diff --git a/@HEKA_Importer/HEKA_FileFormat/FileFormat_v1000/DataFile_v1000.txt b/@HEKA_Importer/HEKA_FileFormat/FileFormat_v1000/DataFile_v1000.txt new file mode 100644 index 0000000..05f8ca9 --- /dev/null +++ b/@HEKA_Importer/HEKA_FileFormat/FileFormat_v1000/DataFile_v1000.txt @@ -0,0 +1,127 @@ + + Patchmaster Next / PatchMaster v2.90.4 30-Oct-2018 + +1. Data File Types + +There are 4 types of .dat files: + + - the oldest files where the raw data start at the very beginning + (e.g. converted "PULSE" datafiles) + - the older files where the first 4 byte were "DATA", followed by raw data + - the new files with the empty "bundle" header => signature is "DAT1" + - the new files with the filled "bundle" header => signature is "DAT2" + - note that in "bundle" header the 4 bytes following the signature + are zero! + + +2. Structure of "bundle" Header + +The "bundle" header has the following structure: + + (* BundleHeader = RECORD *) + oSignature = 0; (* ARRAY[0..7] OF CHAR *) + oVersion = 8; (* ARRAY[0..31] OF CHAR *) + oTime = 40; (* LONGREAL *) + oItems = 48; (* INT32 *) + oIsLittleEndian = 52; (* BOOLEAN *) + oReserved = 53; (* ARRAY[0..10] OF CHAR *) + oBundleItems = 64; (* ARRAY[0..11] OF BundleItem *) + BundleHeaderSize = 256; (* = 32 * 8 *) + + (* BundleItem = RECORD *) + oStart = 0; (* INT32 *) + oLength = 4; (* INT32 *) + oExtension = 8; (* ARRAY[0..7] OF CHAR *) + BundleItemSize = 16; (* = 2 * 8 *) + + + Signature is "DAT1" or "DAT2", see above. + "DAT1" signals an empty or invalid BundleHeader + "DAT2" signals a valid BundleHeader + + Version contains the text version of the PatchMaster writing the file + + Time is the date and time of last modification + + Items is the number of valid BundleItem elements + + IsLittleEndian is the endian flag: Windows=TRUE, MacOS=FALSE + + BundleItems is an array of BundleItem, each containing: + "oStart" tells at which offset the respective sub-file starts + "oLength" tells the number of bytes of that file + "oExtension" tells the filename extension of the file. One can + recognize the described file by its filename extension. + + Typically, the following indices are used: + raw data file: ".dat" = 0; + Pulsed Tree file: ".pul" = 1; + PGF Tree file: ".pgf" = 2; + Amplifier file: ".amp" = 3; + Solution file: ".sol" = 4; (* when storing solutions only *) + Notebook file: ".txt" = 5; (* auto store only *) + reserved: = 6; + Marker file: ".mrk" = 7; + Method file: ".mth" = 8; + Analysis file: ".onl" = 9; + + +3. Structure of Trace Data + +3.1. General + + Trace data are described by the parameters of the "TraceRecord", see Document + "PulsedFileFormat_v1000.txt". + + Specifically: + TrData offset [in bytes] into the data file + TrDataPoints number of data points + TrDataKind defines the format: int16, int32, real32, real64 + TrDataScaler scaling factor from raw format to IUPAC units: + ampere, volt, meter, second, etc. + TrInterleaveSize interleave block size [in bytes] + TrInterleaveSkip distance [in bytes] to the next interleave block + TrInterleaveSkip distance [in bytes] from beginning of an interleave block + to the beginning of the following interleaved block + +3.2. Interleaving + + TrInterleaveSize is typically zero, denoting that the data are stored as one + contiguous block. For long continuous acquisitions interleaving is required. + In that case, TrInterleaveSize defines the size [in bytes] of one data block + and TrInterleaveSkip defines how many bytes are to be skipped from beginning + of one block to beginning of the next data block. + + Example: + - TrInterleaveSize = 1000 + - TrInterleaveSkip = 3000 + + | Start of trace data at TrData into data file + V + <- 1000 bytes -------><- 2000 bytes ----------------------><- 1000 bytes -------> + 1. block of trace (data blocks of other traces) 2. block of trace + <- 3000 bytes --------------------------------------------><- ... + + +3.3. "start segment" and "non-stored" Segments + + - "start segment" + If stDataStartSegment > 0 : + Any data originating from a segment before the stDataStartSegment segment, + is not stored, nor any data between the start of stDataStartSegment segment and + stDataStartTime. + + - "non-stored" data + Additionally, any data originating from a segment with seDoStore = false is not + stored. + + +4. How to get V-membrane/I-membrane of a Trace + +4.1. Get the stimulus channel which defined the appropriate stimulus pattern. That channel is the one having the index chLinkedChannel. An exception is a LockIn trace. +The chLinkedChannel channel is the parent LockIn current trace, and its chLinkedChannel +is the actual channel defining the appropriate stimulus pattern. + +4.2. The field "Holding" of the chLinkedChannel channel contains now V-membrane/ +I-membrane of the trace. + diff --git a/@HEKA_Importer/HEKA_FileFormat/FileFormat_v1000/DataFormat_v1000.doc b/@HEKA_Importer/HEKA_FileFormat/FileFormat_v1000/DataFormat_v1000.doc new file mode 100644 index 0000000..eeff94c Binary files /dev/null and b/@HEKA_Importer/HEKA_FileFormat/FileFormat_v1000/DataFormat_v1000.doc differ diff --git a/@HEKA_Importer/HEKA_FileFormat/FileFormat_v1000/FileFormat.txt b/@HEKA_Importer/HEKA_FileFormat/FileFormat_v1000/FileFormat.txt new file mode 100644 index 0000000..bb8b903 --- /dev/null +++ b/@HEKA_Importer/HEKA_FileFormat/FileFormat_v1000/FileFormat.txt @@ -0,0 +1,631 @@ + + PatchMaster v2.90.4, Patchmaster Next + +(************************************************************************ + +PatchMaster generates multiple files when you create a data file. They +can be combined into a "bundle" file, if requested. The bundle file format +is described in the document "DataFile_v9.txt". +The files are: + + 1. The data file itself (file with file extension ".dat"). + This raw data file is a continuous data stream. + + 2. The "pul" file, containing acquisition parameters, such as gain, + capacitance, etc. The pointer to the data stored in the raw data + file is also stored in this file. + The information is stored in the "Tree" format described below. + + 3. The "pgf" file, containing the stimulus templates. + The information is stored in the "Tree" format described below. + + 5. The "sol" file containing the solution data base. + The information is stored in the "Tree" format described below. + + 6. The "onl" file containing the stored online analysis methods. + The information is stored in the "Tree" format described below. + + 7. The "mth" file containing the applied acquisition methods. + The format is described in the file "MethodFile_v9.txt". + + 8. The "mrk" file containing the markers. + The information is stored in the "Tree" format described below. + + 9. The "amp" file contains the amplifier settings and solutions. + The information is stored in the "Tree" format described below. + + 10. The optional "ana" file with the analysis results created by + FitMaster. + The information is stored in the "Tree" format described below. + +The descriptions of the variables, their names and meanings, and their +respective record offsets are described in the following files: + AmplTreeFile_v1000.txt + DataFile_v1000.txt + DataFormat_v1000.doc + FileFormat.txt + MarkerFile_v9.txt + MethodFile_v9.txt + Analysis_v11.txt + PulsedFile_v1000.txt + SolutionsFile_v1000.txt + StimFile_v1000.txt + TimeFormat.txt + + +The following is a description of the "Tree" format. Following the +description of the "Tree" format a source code listing is enclosed. +That program shows how to scan and load a "Tree" file. It can be +compiled and executed by the PowerMod environment. The source code +is commented and can easily be translated to other languages. + +The idea behind the "Tree" format is that it allows extending the +information stored in a file without braking the older file format. +Thus, newer program versions can load files created by older program +versions and vice versa without requiring any file conversions. This +approach is presently (in 1995) working since more than 10 years +across many program versions. + +An example tree can be diagrammed as follows: + + Level 0 Record (Root) + Level 1 Record 1 + Level 2 Record 1.1 + Level 3 Record 1.1.1 + Level 3 Record 1.1.2 + Level 2 Record 1.2 + Level 1 Record 2 + Level 2 Record 2.1 + Level 3 Record 2.1.1 + Level 2 Record 2.2 + Level 3 Record 2.2.1 + Level 3 Record 2.2.2 + Level 3 Record 2.2.3 + Level 3 Record 2.2.4 + Level 1 Record 3 + +There is only ever one record of level 0, the root record. The above +tree has four levels, the root (level 0), levels 1 and 2, and the leaf +nodes (level 3). + +The format of a tree stored to a file is as follows: + + 1) Magic number : 054726565H + 2) Number of levels + 3) Level sizes, one per level + 4) Tree records, top down, left-to-right. Each record has the format: + A) Record contents + B) Number of children + +All of the values (except the record contents) are INT32 values, i.e., +32-bit (4 bytes) values. + +The "Tree" format is based on proposals from Stefan Heinemann, +Erwin Neher, and Walter Stuehmer. + +WARNING: Never assume you know the record sizes. The record sizes may + have changed, e.g., because the file has been created by an + older program version which used fewer fields than it is + currently using. You MUST use the record sizes stored in the + files themselves, otherwise you are asking for BIG troubles! + + +The trace data are stored in the data file as follows: + + first trace + -> at offset "Data" + -> having "DataPoints" samples + -> to be scaled with "DataFactor1" + + leak trace, if "Leak" = TRUE + -> at offset (Data + 2*DataPoints) + -> having "DataPoints" samples + -> to be scaled with "DataFactor1" + + second trace, if "SecondTrace" = TRUE + -> at offset: + (Data + 2*DataPoints), if no leak + (Data + 4*DataPoints), if leak present + -> having "DataPoints" samples + -> to be scaled with "DataFactor2" + +notes about stored trace data: +- it is stored "Leak Subtracted" +- but not "Zero Subtracted" +- add the leak to get the "non subtracted" trace +- subtract "ZeroCurrent" from the scaled trace to get the "Zero Subtracted" trace + +notes about the second trace: +- stored without "Leak Subtraction" +- stored without "Zero Subtraction" + +************************************************************************) + + +MODULE FileFormat; + +FROM SYSTEM IMPORT ADR, ADDRESS, BYTE, LONG, SHORT; +FROM SYSTEMp1 IMPORT INT32, ADDADR; + +IMPORT Alert, FileSelect, IOBytes, IOFiles, Strings, TermIO, Buffer; + + +(* + * MagicNumber - This is a special value used as a prefix for a tree + * stored to a file. The value contains the four byte values of the + * characters 'Tree' in order. + * + * SwappedMagicNumber - This is the MagicNumber written by a CPU + * which used the opposite byte ordering. + *) + +CONST + MagicNumber = 054726565H; (* i.e. "Tree" in ASCII *) + SwappedMagicNumber = 065657254H; (* i.e. "eerT" in ASCII *) + + +(* + * SwappedInt32 - Swaps the byte of a 32 bit long variable. + *) + +PROCEDURE SwappedInt32( Value : INT32 ): INT32; +VAR + Source, + Target : POINTER TO ARRAY[0..3] OF BYTE; + Result : INT32; +BEGIN + Source := ADR( Value ); + Target := ADR( Result ); + Target^[0] := Source^[3]; + Target^[1] := Source^[2]; + Target^[2] := Source^[1]; + Target^[3] := Source^[0]; + RETURN Result; +END SwappedInt32; + + +(* + * LoadOneRecord + * + * Loads one data block. + * All "TermIO" statements are for demonstration purpose only. + * + * The variables are + * Stream : the file handle to the open file + * FileSize : the number of bytes the data block has in the + * file. + * MemorySize : the byte length of the memory block where the + * data is going to be stored. + * WhereToStore : the address of where the data block is going + * to be stored. + * + * The procedure returns TRUE, if it encountered no errors. + *) + +PROCEDURE LoadOneRecord( + Stream : IOFiles.FileHandleType; + FileSize : LONGINT; + MemorySize : LONGINT; + WhereToStore : ADDRESS ) + : BOOLEAN; + +VAR + Excess : LONGINT; + FileBytes : LONGINT; + +BEGIN + + (* Here we load the next block of data into memory. + * + * First, we have to compare the number of bytes we can load from the file + * with the bytes of allocated memory for that record. + * + * There are 3 possibilities: + * 1. The size of the allocated memory ("MemorySize") equals the number + * of bytes of the data block in the file ("FileSize"). Thus, we can + * load the complete block. + * 2. There are fewer bytes in the file than we expect. This can occur, + * e.g., when the file has been written by an earlier version which + * used fewer parameters than the present one. In this case, we would + * have to zero out those fields which are not filled with data from + * the file. + * 3. There are more bytes in the file than we expect. This can happen, + * when the program which created that tree file was using more + * parameters than we presently know of. In that case, we would load + * only as much byte as we had reserved RAM for. + *) + + Excess := MemorySize - FileSize; + + IF Excess = 0D THEN + (* The file record has as many bytes as there is space in RAM *) + + FileBytes := MemorySize; + + ELSIF Excess < 0D THEN + (* The file record has more many bytes than there is space in RAM. + * Load only as many bytes as there is space in RAM. + *) + + FileBytes := MemorySize; + + ELSE (* i.e., Excess > 0D *) + (* The file record has fewer bytes than there is space in RAM. + * Load only as many bytes as there are in the file. + *) + + FileBytes := FileSize; + + (* Do not forget to clear the remaining fields which are not going + * to be filled from the file. + *) + + Buffer.Set( ADDADR( WhereToStore, FileSize ), Excess, 0 ); + + END (* IF *); + + RETURN IOBytes.Read( Stream, FileBytes, WhereToStore ); + +END LoadOneRecord; + + +(* + * LoadOneLevel + * + * Processes the loading of one data block from a "Tree", and all + * its "children". + * All "TermIO" statements are for demonstration purpose only. + * + * The variables are + * Stream : the file handle to the open file + * Sizes : the array containing the level sizes + * Levels : the number of levels in the tree + * NeedsByteSwap : the flag telling, whether byte-swapping is needed + * Level : the actual tree level to load + * IsFirst : a flag telling, whether it is the first child + * loaded. This is only required for text output! + * Position : the variable containing the position in the file. + * + * The procedure returns TRUE, if it encountered no errors. + *) + +PROCEDURE LoadOneLevel( + VAR Stream : IOFiles.FileHandleType; + VAR Sizes : ARRAY OF INT32; + VAR Levels : LONGINT; + NeedsByteSwap : BOOLEAN; + Level : LONGINT; + IsFirst : BOOLEAN; + VAR Position : LONGINT ) + : BOOLEAN; + +VAR + Count : INT32; + Size : LONGINT; + Children : LONGINT; + i : INTEGER; + WriteInfo : BOOLEAN; + +BEGIN + + WriteInfo := IsFirst OR ( Level < Levels ); + + IF WriteInfo THEN + FOR i := 1 TO SHORT( Level ) DO + TermIO.WriteString( ' ' ); + END; (* FOR *) + TermIO.WriteString( 'level: ' ); + TermIO.WriteInt( Level, 0 ); + TermIO.WriteString( '; file offset: ' ); + TermIO.WriteInt( Position, 0 ); + END; (* IF *) + + + (* Here would normally be the code which loads the next block of data + * somewhere into memory. In the present example, we just skip the bytes + * containing these data. + * + * In case we would load the data block from the file, we would call the + * following procedure: + + IF NOT + LoadOneRecord( Stream, Sizes[SHORT(Level)], MemorySize, WhereToStore ) + THEN + Alert.IOError( '7-Error' ); + RETURN FALSE; + END; + + (* If byte-swapping is required, we would now have to swap the bytes of all + fields in the loaded record! + *) + + IF NeedsByteSwap THEN ( go and swap the record fields ... ) END; + + * End of code we would call. + *) + + + (* Increase the file pointer by "Sizes[Level]" bytes and set the file position + * just beyond the next data block: + *) + + INC( Position, Sizes[SHORT(Level)] ); + + IF NOT + IOBytes.SetPosition( Stream, IOFiles.FromStart, Position ) + THEN + Alert.IOError( '8-Error' ); + RETURN FALSE; + END; + + + (* The next 4 bytes contain the number of children of the present level. *) + + Size := SIZE( INT32 ); + + IF NOT IOBytes.Read( Stream, Size, ADR(Count) ) THEN + Alert.IOError( '9-Error' ); + RETURN FALSE; + END; + + (* The file pointer increased by 4 bytes: *) + INC( Position, 4 ); + + (* And we swap the bytes, if needed: *) + + IF NeedsByteSwap THEN Count := SwappedInt32( Count ); END; + + IF WriteInfo THEN + TermIO.WriteString( '; children: ' ); + TermIO.WriteInt( Count, 0 ); + TermIO.WriteLn; + END; (* IF *) + + + (* Now, we can proceed to load all the children of the present level, + * if there are any: + *) + + INC( Level ); + + Children := 0D; + + IF Level < Levels THEN + + WHILE Children < Count DO + + IF NOT + LoadOneLevel( + Stream, + Sizes, + Levels, + NeedsByteSwap, + Level, + Children = 0D, + Position ) + THEN + RETURN FALSE; + END; (* IF *) + + INC( Children ); + + END (* WHILE *); + + END (* IF *); + + RETURN TRUE; + +END LoadOneLevel; + + +(* + * LoadTree + * + * Scans a complete Tree. + * All "TermIO" statements are for demonstration purpose only. + * + * The variables are + * Stream : the file handle to the open file + * Sizes : the array is returns the level sizes in the Tree + * on disk. + * Levels : the number of levels in the tree + * NeedsByteSwap : the flag telling, whether byte-swapping is needed + * + * The procedure returns TRUE, if it encountered no errors. + *) + +PROCEDURE LoadTree( + VAR Stream : IOFiles.FileHandleType; + VAR Sizes : ARRAY OF INT32; + VAR Levels : LONGINT; + VAR NeedsByteSwap : BOOLEAN ) + : BOOLEAN; +VAR + Value : INT32; + Position : LONGINT; + Size : LONGINT; + i : INTEGER; + Success : BOOLEAN; + +BEGIN + + (* We start at the beginning of the file. We keep the variable + * "Position" containing the actual position in the file. + *) + + Position := 0D; + + + (* The first 4 bytes should contain the "MagicNumber", see above. + * a variable of type INT32 is a 32-bit long, signed word. + *) + + Size := SIZE( INT32 ); + + IF NOT IOBytes.Read( Stream, Size, ADR(Value) ) THEN + Alert.IOError( '2-Error' ); + RETURN FALSE; + END; + + IF Value = MagicNumber THEN + NeedsByteSwap := FALSE; + ELSIF Value = SwappedMagicNumber THEN + NeedsByteSwap := TRUE; + ELSE + Alert.OK( '3-Error: File does not start with "Tree" !' ); + RETURN FALSE; + END; (* IF *) + + (* The file pointer increased by 4 bytes: *) + INC( Position, 4 ); + + + (* Next we load the number of levels in the Tree, which is stored in the + * next 4 bytes (at offset 4): + *) + + Size := SIZE( INT32 ); + + IF NOT IOBytes.Read( Stream, Size, ADR(Levels) ) THEN + Alert.IOError( '4-Error' ); + RETURN FALSE; + END; + + (* The file pointer increased by 4 bytes: *) + INC( Position, 4 ); + + + (* If the file originates from a platform with opposite byte ordering, + * then we have to swap the bytes: + *) + + IF NeedsByteSwap THEN Levels := SwappedInt32( Levels ); END; + + TermIO.WriteString( ' -> levels: ' ); + TermIO.WriteInt( Levels, 0 ); + + + (* The next bytes contain the sizes of all levels. Thus, there is + * one 4-byte variable for each level, totaling in "Levels" times 4 + * bytes. + * + * First, we check, if the array "Sizes" passed to this procedure is + * large enough to contain all level sizes: + *) + + IF ( Levels <= 0D ) OR ( Levels > LONG(HIGH(Sizes)+1) ) THEN + Alert.OK( '5-Error: number of level either <= 0 or too large!' ); + RETURN FALSE; + END (* IF *); + + + (* Next, we load the "Level Size": *) + + Size := Levels * LONG( SIZE( INT32 ) ); + + IF NOT IOBytes.Read( Stream, Size, ADR(Sizes) ) THEN + Alert.IOError( '6-Error' ); + RETURN FALSE; + END; + + (* The file pointer increased by "Size" bytes: *) + INC( Position, Size ); + + (* And we swap the bytes, if needed: *) + + IF NeedsByteSwap THEN + FOR i := 0 TO SHORT( Levels - 1D ) DO + Sizes[i] := SwappedInt32( Sizes[i] ); + END; (* FOR *) + END; (* IF *) + + TermIO.WriteString( '; sizes: ' ); + FOR i := 0 TO SHORT( Levels - 1D ) DO + TermIO.WriteInt( Sizes[i], 0 ); + IF i < SHORT( Levels - 1D ) THEN + TermIO.WriteString( ', ' ); + END; (* IF *) + END; (* FOR *) + + TermIO.WriteString( '; swap: ' ); + TermIO.WriteBoolean( NeedsByteSwap ); + TermIO.WriteLn; + + + (* Now, the tree data follow. + * We can load them by a recursive procedure: + *) + + Success := + LoadOneLevel( + Stream, + Sizes, + Levels, + NeedsByteSwap, + 0D, + TRUE, + Position ); + + IF Success THEN + TermIO.WriteString( 'total file length: ' ); + TermIO.WriteInt( Position, 0 ); + END; (* IF *) + + TermIO.WriteLn; + TermIO.WriteLn; + + RETURN Success; + +END LoadTree; + + +VAR + FileName : IOFiles.FileNameType; + Stream : IOFiles.FileHandleType; + Sizes : ARRAY[0..9] OF INT32; + Levels : LONGINT; + NeedsByteSwap : BOOLEAN; + Success : BOOLEAN; + Dummy : BOOLEAN; + +BEGIN + + (* Get a filename of a tree file to load: *) + + FileName[0] := 0C; + + IF NOT + FileSelect.Select( + FileName, + '*.*', + FileSelect.ExistingFile, + 'Select the TREE file to scan:' ) + THEN + RETURN; + END; (* IF *) + + TermIO.DoBuffer := TRUE; + TermIO.WriteLn; + TermIO.WriteLine( FileName ); + + + (* Open the file : *) + + IF NOT + IOBytes.Open( FileName, IOFiles.NILEncryption, IOFiles.Read, Stream ) + THEN + Alert.IOError( '1-Error' ); + RETURN; + END; + + + (* Now, load the "Tree" : *) + + Success := LoadTree( Stream, Sizes, Levels, NeedsByteSwap ); + + + (* And, finally, we are done and can close the file. *) + + Dummy := IOBytes.Close( Stream ); + +END FileFormat. diff --git a/@HEKA_Importer/HEKA_FileFormat/FileFormat_v1000/MarkerFile_v9.txt b/@HEKA_Importer/HEKA_FileFormat/FileFormat_v1000/MarkerFile_v9.txt new file mode 100644 index 0000000..4474fc5 --- /dev/null +++ b/@HEKA_Importer/HEKA_FileFormat/FileFormat_v1000/MarkerFile_v9.txt @@ -0,0 +1,37 @@ + + PatchMaster v2.90.4, 30-Oct-2018 + + SizeByte = 1; + SizeChar = 1; + SizeEnum = 1; + SizeBoolean = 1; + SizeInt16 = 2; + SizeCard16 = 2; + SizeSet16 = 2; + SizeInt32 = 4; + SizeCard32 = 4; + SizeReal = 4; + SizeLongReal = 8; + + String80Size = 80; + + RootLevel = 0; + MarkerLevel = 1; + + MarkerType = ( MarkerGeneral, + MarkerSolutionIndex, + MarkerSolutionValue ); + + (* MarkerRecord = RECORD *) + MaMarkerTime = 0; (* LONGREAL *) + MaMarkerText = 8; (* String80Type *) + MaMarkerTrace = 88; (* INT32 *) + MaMarkerKind = 92; (* BYTE *) + MaFiller = 93; (* 7 *) + MaCRC = 100; (* CARD32 *) + MarkerRecSize = 104; (* = 13 * 8 *) + + (* RootRecord = RECORD *) + RoVersion = 0; (* INT32 *) + RoCRC = 4; (* CARD32 *) + RootRecSize = 8; (* = 1 * 8 *) diff --git a/@HEKA_Importer/HEKA_FileFormat/FileFormat_v1000/MethodFile_v9.txt b/@HEKA_Importer/HEKA_FileFormat/FileFormat_v1000/MethodFile_v9.txt new file mode 100644 index 0000000..6ee0d26 --- /dev/null +++ b/@HEKA_Importer/HEKA_FileFormat/FileFormat_v1000/MethodFile_v9.txt @@ -0,0 +1,259 @@ + + PatchMaster v2.90.4, Patchmaster Next + + SizeByte = 1; + SizeChar = 1; + SizeEnum = 1; + SizeBoolean = 1; + SizeInt16 = 2; + SizeCard16 = 2; + SizeSet16 = 2; + SizeInt32 = 4; + SizeCard32 = 4; + SizeReal = 4; + SizeLongReal = 8; + + String8Size = 8; + String32Size = 32; + + StimParams = 10; + StimParamChars = 320; + + RootLevel = 0; + StimulationLevel = 1; + ChannelLevel = 2; + StimSegmentLevel = 3; + + + (* + CompressionMode : Specifies how to the data + -> meaning of bits: + bit 0 (CompReal) -> high = store as real + low = store as int16 + bit 1 (CompMean) -> high = use mean + low = use single sample + bit 2 (CompFilter) -> high = use digital filter + *) + + (* + StimToDacID : Specifies how to convert the Segment "Voltage" to + the actual voltage sent to the DAC + -> meaning of bits: + bit 0 (UseStimScale) -> use StimScale + bit 1 (UseRelative) -> relative to Vmemb + bit 2 (UseFileTemplate) -> use file template + bit 3 (UseForLockIn) -> use for LockIn computation + bit 4 (UseForWavelength) + bit 5 (UseScaling) + bit 6 (UseForChirp) + bit 7 (UseForImaging) + bit 14 (UseReserved) + bit 15 (UseReserved) + *) + + SegmentClass = ( SegmentConstant, + SegmentRamp, + SegmentContinuous, + SegmentConstSine, + SegmentSquarewave, + SegmentChirpwave ); + + IncrementModeType = ( ModeInc, + ModeDec, + ModeIncInterleaved, + ModeDecInterleaved, + ModeAlternate, + ModeLogInc, + ModeLogDec, + ModeLogIncInterleaved, + ModeLogDecInterleaved, + ModeLogAlternate ); + + ExtTriggerType = ( TrigNone, + TrigSeries, + TrigSweep, + TrigSweepNoLeak ); + + AmplModeType = ( AnyAmplMode, + VCAmplMode, + CCAmplMode, + IDensityMode ); + + AutoRangingType = ( AutoRangingOff, + AutoRangingPeak, + AutoRangingMean, + AutoRangingRelSeg ); + + AdcType = ( AdcOff, + Analog, + Digitals, + Digital, + AdcVirtual ); + + LeakStoreType = ( LNone, + LStoreAvg, + LStoreEach, + LNoStore ); + + LeakHoldType = ( Labs, + Lrel, + LabsLH, + LrelLH ); + + BreakType = ( NoBreak, + BreakPos, + BreakNeg ); + + LeakCompType = ( LeakCompSoft, + LeakCompHard ); + + SegStoreType = ( SegNoStore, + SegStore, + SegStoreStart, + SegStoreEnd ); + + + (* StimSegmentRecord = RECORD *) + seMark = 0; (* INT32 *) + seClass = 4; (* BYTE *) + seStoreKind = 5; (* BYTE *) + seVoltageIncMode = 6; (* BYTE *) + seDurationIncMode = 7; (* BYTE *) + seVoltage = 8; (* LONGREAL *) + seVoltageSource = 16; (* INT32 *) + seDeltaVFactor = 20; (* LONGREAL *) + seDeltaVIncrement = 28; (* LONGREAL *) + seDuration = 36; (* LONGREAL *) + seDurationSource = 44; (* INT32 *) + seDeltaTFactor = 48; (* LONGREAL *) + seDeltaTIncrement = 56; (* LONGREAL *) + seFiller1 = 64; (* INT32 *) + seCRC = 68; (* CARD32 *) + seScanRate = 72; (* LONGREAL *) + StimSegmentRecSize = 80; (* = 10 * 8 *) + + (* ChannelRecord = RECORD *) + chMark = 0; (* INT32 *) + chLinkedChannel = 4; (* INT32 *) + chCompressionFactor = 8; (* INT32 *) + chYUnit = 12; (* String8Type *) + chAdcChannel = 20; (* INT16 *) + chAdcMode = 22; (* BYTE *) + chDoWrite = 23; (* BOOLEAN *) + stLeakStore = 24; (* BYTE *) + chAmplMode = 25; (* BYTE *) + chOwnSegTime = 26; (* BOOLEAN *) + chSetLastSegVmemb = 27; (* BOOLEAN *) + chDacChannel = 28; (* INT16 *) + chDacMode = 30; (* BYTE *) + chHasLockInSquare = 31; (* BYTE *) + chRelevantXSegment = 32; (* INT32 *) + chRelevantYSegment = 36; (* INT32 *) + chDacUnit = 40; (* String8Type *) + chHolding = 48; (* LONGREAL *) + chLeakHolding = 56; (* LONGREAL *) + chLeakSize = 64; (* LONGREAL *) + chLeakHoldMode = 72; (* BYTE *) + chLeakAlternate = 73; (* BOOLEAN *) + chAltLeakAveraging = 74; (* BOOLEAN *) + chLeakPulseOn = 75; (* BOOLEAN *) + chStimToDacID = 76; (* SET16 *) + chCompressionMode = 78; (* SET16 *) + chCompressionSkip = 80; (* INT32 *) + chDacBit = 84; (* INT16 *) + chHasLockInSine = 86; (* BOOLEAN *) + chBreakMode = 87; (* BYTE *) + chZeroSeg = 88; (* INT32 *) + chStimSweep = 92; (* INT32 *) + chSine_Cycle = 96; (* LONGREAL *) + chSine_Amplitude = 104; (* LONGREAL *) + chLockIn_VReversal = 112; (* LONGREAL *) + chChirp_StartFreq = 120; (* LONGREAL *) + chChirp_EndFreq = 128; (* LONGREAL *) + chChirp_MinPoints = 136; (* LONGREAL *) + chSquare_NegAmpl = 144; (* LONGREAL *) + chSquare_DurFactor = 152; (* LONGREAL *) + chLockIn_Skip = 160; (* INT32 *) + chPhoto_MaxCycles = 164; (* INT32 *) + chPhoto_SegmentNo = 168; (* INT32 *) + chLockIn_AvgCycles = 172; (* INT32 *) + chImaging_RoiNo = 176; (* INT32 *) + chChirp_Skip = 180; (* INT32 *) + chChirp_Amplitude = 184; (* LONGREAL *) + chPhoto_Adapt = 192; (* BYTE *) + chSine_Kind = 193; (* BYTE *) + chChirp_PreChirp = 194; (* BYTE *) + chSine_Source = 195; (* BYTE *) + chSquare_NegSource = 196; (* BYTE *) + chSquare_PosSource = 197; (* BYTE *) + chChirp_Kind = 198; (* BYTE *) + chChirp_Source = 199; (* BYTE *) + chDacOffset = 200; (* LONGREAL *) + chAdcOffset = 208; (* LONGREAL *) + chTraceMathFormat = 216; (* BYTE *) + chHasChirp = 217; (* BOOLEAN *) + chSquare_Kind = 218; (* BYTE *) + chFiller1 = 219; (* ARRAY[0..5] OF CHAR *) + chSquare_BaseIncr = 224; (* LONGREAL *) + chSquare_Cycle = 232; (* LONGREAL *) + chSquare_PosAmpl = 240; (* LONGREAL *) + chCompressionOffset = 248; (* INT32 *) + chPhotoMode = 252; (* INT32 *) + chBreakLevel = 256; (* LONGREAL *) + chTraceMath = 264; (* String128Type *) + chFiller2 = 392; (* INT32 *) + chCRC = 396; (* CARD32 *) + ChannelRecSize = 400; (* = 50 * 8 *) + + (* StimulationRecord = RECORD *) + stMark = 0; (* INT32 *) + stEntryName = 4; (* String32Type *) + stFileName = 36; (* String32Type *) + stAnalName = 68; (* String32Type *) + stDataStartSegment = 100; (* INT32 *) + stDataStartTime = 104; (* LONGREAL *) + stSampleInterval = 112; (* LONGREAL *) + stSweepInterval = 120; (* LONGREAL *) + stLeakDelay = 128; (* LONGREAL *) + stFilterFactor = 136; (* LONGREAL *) + stNumberSweeps = 144; (* INT32 *) + stNumberLeaks = 148; (* INT32 *) + stNumberAverages = 152; (* INT32 *) + stActualAdcChannels = 156; (* INT32 *) + stActualDacChannels = 160; (* INT32 *) + stExtTrigger = 164; (* BYTE *) + stNoStartWait = 165; (* BOOLEAN *) + stUseScanRates = 166; (* BOOLEAN *) + stNoContAq = 167; (* BOOLEAN *) + stHasLockIn = 168; (* BOOLEAN *) + stOldStartMacKind = 169; (* CHAR *) + stOldEndMacKind = 170; (* BOOLEAN *) + stAutoRange = 171; (* BYTE *) + stBreakNext = 172; (* BOOLEAN *) + stIsExpanded = 173; (* BOOLEAN *) + stLeakCompMode = 174; (* BOOLEAN *) + stHasChirp = 175; (* BOOLEAN *) + stOldStartMacro = 176; (* String32Type *) + stOldEndMacro = 208; (* String32Type *) + sIsGapFree = 240; (* BOOLEAN *) + sHandledExternally = 241; (* BOOLEAN *) + stFiller1 = 242; (* BOOLEAN *) + stFiller2 = 243; (* BOOLEAN *) + stCRC = 244; (* CARD32 *) + StimulationRecSize = 248; (* = 31 * 8 *) + + (* RootRecord = RECORD *) + roVersion = 0; (* INT32 *) + roMark = 4; (* INT32 *) + roVersionName = 8; (* String32Type *) + roMaxSamples = 40; (* INT32 *) + roFiller1 = 44; (* INT32 *) + (* StimParams = 10 *) + (* StimParamChars = 320 *) + roParams = 48; (* ARRAY[0..9] OF LONGREAL *) + roParamText = 128; (* ARRAY[0..9],[0..31]OF CHAR *) + roReserved = 448; (* String128Type *) + roFiller2 = 576; (* INT32 *) + roCRC = 580; (* CARD32 *) + RootRecSize = 584; (* = 73 * 8 *) + diff --git a/@HEKA_Importer/HEKA_FileFormat/FileFormat_v1000/PulsedFile_v1000.txt b/@HEKA_Importer/HEKA_FileFormat/FileFormat_v1000/PulsedFile_v1000.txt new file mode 100644 index 0000000..ed8e9ac --- /dev/null +++ b/@HEKA_Importer/HEKA_FileFormat/FileFormat_v1000/PulsedFile_v1000.txt @@ -0,0 +1,240 @@ + + PatchMaster v2.90.4, 30-Oct-2018 + + SizeByte = 1; + SizeChar = 1; + SizeEnum = 1; + SizeBoolean = 1; + SizeInt16 = 2; + SizeCard16 = 2; + SizeSet16 = 2; + SizeInt32 = 4; + SizeCard32 = 4; + SizeReal = 4; + SizeLongReal = 8; + + String8Size = 8; + String32Size = 32; + String80Size = 80; + String400Size = 400; + + ParamDescrSize = 24; + TrMarkerNo = 10; + SwMarkerNo = 4; + SwHoldingNo = 16; + SwUserParamNo = 4; + SeUserParamNo1 = 4; + SeUserParamNo2 = 4; + GrStimParams = 10; + AmplifierStateSize = 400; + ScanParamsSize = 96; + Max_TcKind_M1 = 31; + + SizeStateVersion = 8; + SizeSerialNumber = 8; + SizeCalibDate = 16; + + + RootLevel = 0; + GroupLevel = 1; + SeriesLevel = 2; + SweepLevel = 3; + TraceLevel = 4; + + + LittleEndianBit = 0; + IsLeak = 1; + IsVirtual = 2; + IsImon = 3; + IsVmon = 4; + Clip = 5; + (* + DataKind -> meaning of bits: + - LittleEndianBit => byte sequence + "PowerPC Mac" = cleared + "Windows and Intel Mac" = set + - IsLeak + set if trace is a leak trace + - IsVirtual + set if trace is a virtual trace + - IsImon + -> set if trace was from Imon ADC + -> it flags a trace to be used to + compute LockIn traces from + -> limited to "main" traces, not "leaks"! + - IsVmon + -> set if trace was from Vmon ADC + - Clip + -> set if amplifier of trace was clipping + *) + + RecordingModeType = ( InOut, + OnCell, + OutOut, + WholeCell, + CClamp, + VClamp, + NoMode ); + + DataFormatType = ( int16, + int32, + real32, + real64 ); + + UserParamDescrType = RECORD + Name : String32Type; + Unit : String8Type; + END; (* RECORD *) + + (* AmplifierState = RECORD *) + see definition in AmplTreeFile_v9.txt + + (* LockInParams = RECORD *) + see definition in AmplTreeFile_v9.txt + + (* TraceRecord = RECORD *) + TrMark = 0; (* INT32 *) + TrLabel = 4; (* String32Type *) + TrTraceID = 36; (* INT32 *) + TrData = 40; (* INT32 *) + TrDataPoints = 44; (* INT32 *) + TrInternalSolution = 48; (* INT32 *) + TrAverageCount = 52; (* INT32 *) + TrLeakID = 56; (* INT32 *) + TrLeakTraces = 60; (* INT32 *) + TrDataKind = 64; (* SET16 *) + TrUseXStart = 66; (* BOOLEAN *) + TrTcKind = 67; (* BYTE *) + TrRecordingMode = 68; (* BYTE *) + TrAmplIndex = 69; (* CHAR *) + TrDataFormat = 70; (* BYTE *) + TrDataAbscissa = 71; (* BYTE *) + TrDataScaler = 72; (* LONGREAL *) + TrTimeOffset = 80; (* LONGREAL *) + TrZeroData = 88; (* LONGREAL *) + TrYUnit = 96; (* String8Type *) + TrXInterval = 104; (* LONGREAL *) + TrXStart = 112; (* LONGREAL *) + TrXUnit = 120; (* String8Type *) + TrYRange = 128; (* LONGREAL *) + TrYOffset = 136; (* LONGREAL *) + TrBandwidth = 144; (* LONGREAL *) + TrPipetteResistance = 152; (* LONGREAL *) + TrCellPotential = 160; (* LONGREAL *) + TrSealResistance = 168; (* LONGREAL *) + TrCSlow = 176; (* LONGREAL *) + TrGSeries = 184; (* LONGREAL *) + TrRsValue = 192; (* LONGREAL *) + TrGLeak = 200; (* LONGREAL *) + TrMConductance = 208; (* LONGREAL *) + TrLinkDAChannel = 216; (* INT32 *) + TrValidYrange = 220; (* BOOLEAN *) + TrAdcMode = 221; (* CHAR *) + TrAdcChannel = 222; (* INT16 *) + TrYmin = 224; (* LONGREAL *) + TrYmax = 232; (* LONGREAL *) + TrSourceChannel = 240; (* INT32 *) + TrExternalSolution = 244; (* INT32 *) + TrCM = 248; (* LONGREAL *) + TrGM = 256; (* LONGREAL *) + TrPhase = 264; (* LONGREAL *) + TrDataCRC = 272; (* CARD32 *) + TrCRC = 276; (* CARD32 *) + TrGS = 280; (* LONGREAL *) + TrSelfChannel = 288; (* INT32 *) + TrInterleaveSize = 292; (* INT32 *) + TrInterleaveSkip = 296; (* INT32 *) + TrImageIndex = 300; (* INT32 *) + TrTrMarkers = 304; (* ARRAY[0..9] OF LONGREAL *) + TrSECM_X = 384; (* LONGREAL *) + TrSECM_Y = 392; (* LONGREAL *) + TrSECM_Z = 400; (* LONGREAL *) + TrTrHolding = 408; (* LONGREAL *) + TrTcEnumerator = 416; (* INT32 *) + TrXTrace = 420; (* INT32 *) + TrIntSolValue = 424; (* LONGREAL *) + TrExtSolValue = 432; (* LONGREAL *) + TrIntSolName = 440; (* String32Size *) + TrExtSolName = 472; (* String32Size *) + TrDataPedestal = 504; (* LONGREAL *) + TraceRecSize = 512; (* = 64 * 8 *) + + (* SweepRecord = RECORD *) + SwMark = 0; (* INT32 *) + SwLabel = 4; (* String32Type *) + SwAuxDataFileOffset = 36; (* INT32 *) + SwStimCount = 40; (* INT32 *) + SwSweepCount = 44; (* INT32 *) + SwTime = 48; (* LONGREAL *) + SwTimer = 56; (* LONGREAL *) + SwSwUserParams = 64; (* ARRAY[0..1] OF LONGREAL *) + SwPipPressure = 80; (* LONGREAL *) + SwRMSNoise = 88; (* LONGREAL *) + SwTemperature = 96; (* LONGREAL *) + SwOldIntSol = 104; (* INT32 *) + SwOldExtSol = 108; (* INT32 *) + SwDigitalIn = 112; (* SET16 *) + SwSweepKind = 114; (* SET16 *) + SwDigitalOut = 116; (* SET16 *) + SwFiller1 = 118; (* INT16 *) + SwSwMarkers = 120; (* ARRAY[0..3] OF LONGREAL, see SwMarkersNo *) + SwFiller2 = 152; (* INT32 *) + SwCRC = 156; (* CARD32 *) + SwSwHolding = 160; (* ARRAY[0..15] OF LONGREAL, see SwHoldingNo *) + SwSwUserParamEx = 288; (* ARRAY[0..7] OF LONGREAL *) + SweepRecSize = 352; + + (* SeriesRecord = RECORD *) + SeMark = 0; (* INT32 *) + SeLabel = 4; (* String32Type *) + SeComment = 36; (* String80Type *) + SeSeriesCount = 116; (* INT32 *) + SeNumberSweeps = 120; (* INT32 *) + SeAmplStateFlag = 124; (* INT32 *) // flag > 0 => load local oldAmpState, otherwise load from .amp File. + SeAmplStateRef = 128; (* INT32 *) // ref = 0 => use local oldAmpState + SeMethodTag = 132; (* INT32 *) + SeTime = 136; (* LONGREAL *) + SePageWidth = 144; (* LONGREAL *) + SeUserDescr1 = 152; (* ARRAY[0..1] OF UserParamDescrType = 2*40 *) + SeFiller1 = 232; (* ARRAY[0..1] OF UserParamDescrType = 2*40 *) + SeMethodName = 312; (* String32Type *) + SePhotoParams1 = 344; (* ARRAY[0..3] OF LONGREAL = 4*8 *) + SeOldLockInParams = 376; (* SeOldLockInSize = 96, see "Pulsed.de" *) + SeOldAmpState = 472; (* SeOldAmpState = 400 -> the AmplStateRecord is now stored in the .amp file *) + SeUsername = 872; (* String80Type *) + SePhotoParams2 = 952; (* ARRAY[0..3] OF UserParamDescrType = 4*40 *) + SeFiller1 = 1112; (* INT32 *) + SeCRC = 1116; (* CARD32 *) + SeSeUserParams2 = 1120; (* ARRAY[0..3] OF LONGREAL *) + SeSeUserParamDescr2 = 1152; (* ARRAY[0..3] OF UserParamDescrType = 4*40 *) + SeScanParams = 1312; (* ScanParamsSize = 96 (ElProScan Extension) *) + SeUserDescr2 = 1408; (* ARRAY[0..7] OF UserParamDescrType = 8*40 *) + SeriesRecSize = 1728; + + (* GroupRecord = RECORD *) + GrMark = 0; (* INT32 *) + GrLabel = 4; (* String32Size *) + GrText = 36; (* String80Size *) + GrExperimentNumber = 116; (* INT32 *) + GrGroupCount = 120; (* INT32 *) + GrCRC = 124; (* CARD32 *) + GrMatrixWidth = 128; (* LONGREAL *) + GrMatrixHeight = 136; (* LONGREAL *) + GroupRecSize = 144; (* = 18 * 8 *) + + (* RootRecord = RECORD *) + RoVersion = 0; (* INT32 *) + RoMark = 4; (* INT32 *) + RoVersionName = 8; (* String32Type *) + RoAuxFileName = 40; (* String80Type *) + RoRootText = 120; (* String400Type *) + RoStartTime = 520; (* LONGREAL *) + RoMaxSamples = 528; (* INT32 *) + RoCRC = 532; (* CARD32 *) + RoFeatures = 536; (* SET16 *) + RoFiller1 = 538; (* INT16 *) + RoFiller2 = 540; (* INT32 *) + RoTcEnumerator = 544; (* ARRAY[0..Max_TcKind_M1] OF INT16 *) + RoTcKind = 608; (* ARRAY[0..Max_TcKind_M1] OF INT8 *) + RootRecSize = 640; (* = 80 * 8 *) + diff --git a/@HEKA_Importer/HEKA_FileFormat/FileFormat_v1000/SolutionsFile_v1000.txt b/@HEKA_Importer/HEKA_FileFormat/FileFormat_v1000/SolutionsFile_v1000.txt new file mode 100644 index 0000000..4d3b34a --- /dev/null +++ b/@HEKA_Importer/HEKA_FileFormat/FileFormat_v1000/SolutionsFile_v1000.txt @@ -0,0 +1,41 @@ + + PatchMaster v2.90.4, Patchmaster Next + + To find the solution belonging to a Trace locate that Solution record with a + SoNumber value equal to the solution value stored in Trace.InternalSolution + and Trace.ExternalSolution. + + SizeInt16 = 2; + SizeInt32 = 4; + SizeReal = 4; + ChemicalNameSize = 30; + SolutionNameSize = 80; + + RootLevel = 0; + SolutionLevel = 1; + ChemicalLevel = 2; + + (* ChemicalRecord = RECORD *) + ChConcentration = 0; (* REAL *) + ChName = 4; (* ChemicalNameSize *) + ChSpare1 = 34; (* INT16 *) + ChCRC = 36; (* CARD32 *) + ChemicalSize = 40; + + (* SolutionRecord = RECORD *) + SoNumber = 0; (* INT32 *) + SoName = 4; (* SolutionNameSize *) + SoNumeric = 84; (* REAL *) + SoNumericName = 88; (* ChemicalNameSize *) + SopH = 118; (* REAL *) + SopHCompound = 122; (* ChemicalNameSize *) + SoOsmol = 152; (* REAL *) + SoCRC = 156; (* CARD32 *) + SolutionSize = 160; + + (* RootRecord = RECORD *) + RoVersion = 0; (* INT32 *) + RoDataBaseName = 4; (* SolutionNameSize *) + RoCRC = 84; (* CARD32 *) + RootSize = 88; + diff --git a/@HEKA_Importer/HEKA_FileFormat/FileFormat_v1000/StimFile_v1000.txt b/@HEKA_Importer/HEKA_FileFormat/FileFormat_v1000/StimFile_v1000.txt new file mode 100644 index 0000000..1cd64ef --- /dev/null +++ b/@HEKA_Importer/HEKA_FileFormat/FileFormat_v1000/StimFile_v1000.txt @@ -0,0 +1,260 @@ + + PatchMaster v2.90.4, Patchmaster Next + + SizeByte = 1; + SizeChar = 1; + SizeEnum = 1; + SizeBoolean = 1; + SizeInt16 = 2; + SizeCard16 = 2; + SizeSet16 = 2; + SizeInt32 = 4; + SizeCard32 = 4; + SizeReal = 4; + SizeLongReal = 8; + + String8Size = 8; + String32Size = 32; + + StimParams = 10; + StimParamChars = 320; + + RootLevel = 0; + StimulationLevel = 1; + ChannelLevel = 2; + StimSegmentLevel = 3; + + + (* + CompressionMode : Specifies how to the data + -> meaning of bits: + bit 0 (CompReal) -> high = store as real + low = store as int16 + bit 1 (CompMean) -> high = use mean + low = use single sample + bit 2 (CompFilter) -> high = use digital filter + *) + + (* + StimToDacID : Specifies how to convert the Segment "Voltage" to + the actual voltage sent to the DAC + -> meaning of bits: + bit 0 (UseStimScale) -> use StimScale + bit 1 (UseRelative) -> relative to Vmemb + bit 2 (UseFileTemplate) -> use file template + bit 3 (UseForLockIn) -> use for LockIn computation + bit 4 (UseForWavelength) + bit 5 (UseScaling) + bit 6 (UseForChirp) + bit 7 (UseForImaging) + bit 14 (UseReserved) + bit 15 (UseReserved) + *) + + SegmentClass = ( SegmentConstant, + SegmentRamp, + SegmentContinuous, + SegmentConstSine, + SegmentSquarewave, + SegmentChirpwave ); + + IncrementModeType = ( ModeInc, + ModeDec, + ModeIncInterleaved, + ModeDecInterleaved, + ModeAlternate, + ModeLogInc, + ModeLogDec, + ModeLogIncInterleaved, + ModeLogDecInterleaved, + ModeLogAlternate ); + + ExtTriggerType = ( TrigNone, + TrigSeries, + TrigSweep, + TrigSweepNoLeak ); + + AmplModeType = ( AnyAmplMode, + VCAmplMode, + CCAmplMode, + IDensityMode ); + + AutoRangingType = ( AutoRangingOff, + AutoRangingPeak, + AutoRangingMean, + AutoRangingRelSeg ); + + AdcType = ( AdcOff, + Analog, + Digitals, + Digital, + AdcVirtual ); + + LeakStoreType = ( LNone, + LStoreAvg, + LStoreEach, + LNoStore ); + + LeakHoldType = ( Labs, + Lrel, + LabsLH, + LrelLH ); + + BreakType = ( NoBreak, + BreakPos, + BreakNeg ); + + LeakCompType = ( LeakCompSoft, + LeakCompHard ); + + SegStoreType = ( SegNoStore, + SegStore, + SegStoreStart, + SegStoreEnd ); + + + (* StimSegmentRecord = RECORD *) + seMark = 0; (* INT32 *) + seClass = 4; (* BYTE *) + seStoreKind = 5; (* BYTE *) + seVoltageIncMode = 6; (* BYTE *) + seDurationIncMode = 7; (* BYTE *) + seVoltage = 8; (* LONGREAL *) + seVoltageSource = 16; (* INT32 *) + seDeltaVFactor = 20; (* LONGREAL *) + seDeltaVIncrement = 28; (* LONGREAL *) + seDuration = 36; (* LONGREAL *) + seDurationSource = 44; (* INT32 *) + seDeltaTFactor = 48; (* LONGREAL *) + seDeltaTIncrement = 56; (* LONGREAL *) + seFiller1 = 64; (* INT32 *) + seCRC = 68; (* CARD32 *) + seScanRate = 72; (* LONGREAL *) + StimSegmentRecSize = 80; (* = 10 * 8 *) + + (* ChannelRecord = RECORD *) + chMark = 0; (* INT32 *) + chLinkedChannel = 4; (* INT32 *) + chCompressionFactor = 8; (* INT32 *) + chYUnit = 12; (* String8Type *) + chAdcChannel = 20; (* INT16 *) + chAdcMode = 22; (* BYTE *) + chDoWrite = 23; (* BOOLEAN *) + stLeakStore = 24; (* BYTE *) + chAmplMode = 25; (* BYTE *) + chOwnSegTime = 26; (* BOOLEAN *) + chSetLastSegVmemb = 27; (* BOOLEAN *) + chDacChannel = 28; (* INT16 *) + chDacMode = 30; (* BYTE *) + chHasLockInSquare = 31; (* BYTE *) + chRelevantXSegment = 32; (* INT32 *) + chRelevantYSegment = 36; (* INT32 *) + chDacUnit = 40; (* String8Type *) + chHolding = 48; (* LONGREAL *) + chLeakHolding = 56; (* LONGREAL *) + chLeakSize = 64; (* LONGREAL *) + chLeakHoldMode = 72; (* BYTE *) + chLeakAlternate = 73; (* BOOLEAN *) + chAltLeakAveraging = 74; (* BOOLEAN *) + chLeakPulseOn = 75; (* BOOLEAN *) + chStimToDacID = 76; (* SET16 *) + chCompressionMode = 78; (* SET16 *) + chCompressionSkip = 80; (* INT32 *) + chDacBit = 84; (* INT16 *) + chHasLockInSine = 86; (* BOOLEAN *) + chBreakMode = 87; (* BYTE *) + chZeroSeg = 88; (* INT32 *) + chStimSweep = 92; (* INT32 *) + chSine_Cycle = 96; (* LONGREAL *) + chSine_Amplitude = 104; (* LONGREAL *) + chLockIn_VReversal = 112; (* LONGREAL *) + chChirp_StartFreq = 120; (* LONGREAL *) + chChirp_EndFreq = 128; (* LONGREAL *) + chChirp_MinPoints = 136; (* LONGREAL *) + chSquare_NegAmpl = 144; (* LONGREAL *) + chSquare_DurFactor = 152; (* LONGREAL *) + chLockIn_Skip = 160; (* INT32 *) + chPhoto_MaxCycles = 164; (* INT32 *) + chPhoto_SegmentNo = 168; (* INT32 *) + chLockIn_AvgCycles = 172; (* INT32 *) + chImaging_RoiNo = 176; (* INT32 *) + chChirp_Skip = 180; (* INT32 *) + chChirp_Amplitude = 184; (* LONGREAL *) + chPhoto_Adapt = 192; (* BYTE *) + chSine_Kind = 193; (* BYTE *) + chChirp_PreChirp = 194; (* BYTE *) + chSine_Source = 195; (* BYTE *) + chSquare_NegSource = 196; (* BYTE *) + chSquare_PosSource = 197; (* BYTE *) + chChirp_Kind = 198; (* BYTE *) + chChirp_Source = 199; (* BYTE *) + chDacOffset = 200; (* LONGREAL *) + chAdcOffset = 208; (* LONGREAL *) + chTraceMathFormat = 216; (* BYTE *) + chHasChirp = 217; (* BOOLEAN *) + chSquare_Kind = 218; (* BYTE *) + chFiller1 = 219; (* ARRAY[0..5] OF CHAR *) + chSquare_BaseIncr = 224; (* LONGREAL *) + chSquare_Cycle = 232; (* LONGREAL *) + chSquare_PosAmpl = 240; (* LONGREAL *) + chCompressionOffset = 248; (* INT32 *) + chPhotoMode = 252; (* INT32 *) + chBreakLevel = 256; (* LONGREAL *) + chTraceMath = 264; (* String128Type *) + chFiller2 = 392; (* INT32 *) + chCRC = 396; (* CARD32 *) + ChannelRecSize = 400; (* = 50 * 8 *) + + (* StimulationRecord = RECORD *) + stMark = 0; (* INT32 *) + stEntryName = 4; (* String32Type *) + stFileName = 36; (* String32Type *) + stAnalName = 68; (* String32Type *) + stDataStartSegment = 100; (* INT32 *) + stDataStartTime = 104; (* LONGREAL *) + stSampleInterval = 112; (* LONGREAL *) + stSweepInterval = 120; (* LONGREAL *) + stLeakDelay = 128; (* LONGREAL *) + stFilterFactor = 136; (* LONGREAL *) + stNumberSweeps = 144; (* INT32 *) + stNumberLeaks = 148; (* INT32 *) + stNumberAverages = 152; (* INT32 *) + stActualAdcChannels = 156; (* INT32 *) + stActualDacChannels = 160; (* INT32 *) + stExtTrigger = 164; (* BYTE *) + stNoStartWait = 165; (* BOOLEAN *) + stUseScanRates = 166; (* BOOLEAN *) + stNoContAq = 167; (* BOOLEAN *) + stHasLockIn = 168; (* BOOLEAN *) + stOldStartMacKind = 169; (* CHAR *) + stOldEndMacKind = 170; (* BOOLEAN *) + stAutoRange = 171; (* BYTE *) + stBreakNext = 172; (* BOOLEAN *) + stIsExpanded = 173; (* BOOLEAN *) + stLeakCompMode = 174; (* BOOLEAN *) + stHasChirp = 175; (* BOOLEAN *) + stOldStartMacro = 176; (* String32Type *) + stOldEndMacro = 208; (* String32Type *) + sIsGapFree = 240; (* BOOLEAN *) + sHandledExternally = 241; (* BOOLEAN *) + stFiller1 = 242; (* BOOLEAN *) + stFiller2 = 243; (* BOOLEAN *) + stCRC = 244; (* CARD32 *) + StimulationRecSize = 248; (* = 31 * 8 *) + + (* RootRecord = RECORD *) + roVersion = 0; (* INT32 *) + roMark = 4; (* INT32 *) + roVersionName = 8; (* String32Type *) + roMaxSamples = 40; (* INT32 *) + roFiller1 = 44; (* INT32 *) + (* StimParams = 10 *) + (* StimParamChars = 320 *) + roParams = 48; (* ARRAY[0..9] OF LONGREAL *) + roParamText = 128; (* ARRAY[0..9],[0..31]OF CHAR *) + roReserved = 448; (* String128Type *) + roFiller2 = 576; (* INT32 *) + roReserved2 = 580; (* 560 Bytes *) + roCRC = 1140; (* CARD32 *) + RootRecSize = 1144; + diff --git a/@HEKA_Importer/HEKA_FileFormat/FileFormat_v1000/TimeFormat.txt b/@HEKA_Importer/HEKA_FileFormat/FileFormat_v1000/TimeFormat.txt new file mode 100644 index 0000000..f1f614c --- /dev/null +++ b/@HEKA_Importer/HEKA_FileFormat/FileFormat_v1000/TimeFormat.txt @@ -0,0 +1,79 @@ +PatchMaster v2.90 / PM Next + +Time is stored as seconds from 01-Jan-1990. +To convert the stored time into a string, proceed as follows: + +MacOS + JanFirst1990 - The number of seconds between 1/1/1904 (Apple's + beginning of time) and 1/1/1990, the beginning of + time for PowerMod's environment. + + JanFirst1990 = 1580970496.0; + MacTime = (int)( StoredTime - JanFirst1990 ); + + Pass MacTime to the API function DateTimeUtils.SecondsToDate + to convert it to a string + +Windows + Windows uses 01-Jan-1601 as its starting point in calculating dates. + + Pass StoredTime to the function PatchMasterSecondsToFileTime or + PatchMasterSecondsToDate below to convert it to a standard Windows + format. + +#define MAC_BASE 9561652096.0 +#define HIGH_DWORD 4294967296.0 +#define JanFirst1990 1580970496.0 + +// Function PatchMasterSecondsToFileTime +// Convert seconds to FILETIME. +// In converting double to DWORD we must be carefull because the +// double will first be converted to a signed int. +// Do the operations modulo 2^31. +// Get the next bit from the high DWORD and then shift high DWORD +// throwing away the highest bit. + +void PatchMasterSecondsToFileTime( double time, FILETIME* file_time ) +{ + time -= JanFirst1990; + + if (time < 0.0) + time += HIGH_DWORD; + + time += MAC_BASE; + + time *= 10000000.0; + + file_time->dwHighDateTime = (DWORD) (time / (HIGH_DWORD / 2.0)); + + file_time->dwLowDateTime = (DWORD) + (time - (double) file_time->dwHighDateTime * (HIGH_DWORD / 2.0)); + + file_time->dwLowDateTime |= ((file_time->dwHighDateTime & 1) << 31); + + file_time->dwHighDateTime >>= 1; +} + +void PatchMasterSecondsToDate( double storedTime, SYSTEMTIME* system_time ) +{ + FILETIME file_time; + PatchMasterSecondsToFileTime( storedTime, &file_time ); + FileTimeToSystemTime( &file_time, system_time ); +} + + +Example 1: applied to the root date of "DemoV9Bundle.dat": +1. RootTime = 221667551 +2. subtract JanFirst1990 time = 221667551 - 1580970496 = -1359302944 +3. is it < 0 ? + yes => add HIGH_DWORD time = -1359302944 + 4294967296 = 2935664351 +4. add correction for Windows time = 2935664351 + 9561652096 = 12497316447 +5. convert to date date = 09-Jan-1997 + +Example 2: applied to the root date of "Malcom.dat": +1. RootTime = 4922414972 +2. subtract JanFirst1990 time = 4922414972 - 1580970496 = 3341444476 +3. is it < 0 ? + no +4. add correction for Windows time = 3341444476 + 9561652096 = 12903096572 +5. convert to date date = 19-Nov-2009 diff --git a/@HEKA_Importer/HEKA_Importer.m b/@HEKA_Importer/HEKA_Importer.m index 0dc6f84..7b4a64b 100644 --- a/@HEKA_Importer/HEKA_Importer.m +++ b/@HEKA_Importer/HEKA_Importer.m @@ -1,152 +1,159 @@ classdef HEKA_Importer < handle - -% Class to import HEKA Patchmaster files into Matlab. -% The core functionality is based on the HEKA importer from sigTool -% (https://doi.org/10.1016/j.neuron.2015.10.042 and -% https://github.com/irondukepublishing/sigTOOL) with modifications -% from Sammy Katta (https://github.com/sammykatta/Matlab-PatchMaster). -% -% This stand-alone importer works independently of sigTool and will -% additionally extract the stimulus (reconstructed from the pgf) -% and solutions (when solution base was active during recording). -% -% The recordings will be sorted into a table together with various -% parameters e.g series resistance (Rs), cell membrane capacitance (Cm), -% holding potential (Vhold), stimulus and solutions. -% -% Note: Currently, not all possible stimuli are supported. -% If your stimulus contains ramps or alternating segments, it will not be -% reconstructed properly. However, it should work fine for most stimuli -% and support for new stimuli will be added in the future. -% -% >> How to use: -% -% - INPUTS: -% -% - filepath char/string full file path and name of HEKA Patchmaster -% file that is to be loaded, -% e.g. to load HEKA Patchmaster file -% "MyData.dat" located in "C:\PatchClamp\" -% run "HEKA_Importer('C:\PatchClamp\MyData.dat')" -% -% *Alternative:* run "HEKA_Importer.GUI" which will open the file dialog -% box from which the Patchmaster file can be selected. -% -% - OUTPUTS: -% Heka_Importer creates object containing the following properties: -% -% - trees struct structure containing the dataTree -% (from the .pul file), the stimTree -% (from the .pgf file)and solTree -% (from the .sol file). These tree structures -% are how HEKA saves the metadata for -% different recordings. For details on the -% HEKA file format check -% ftp://server.hekahome.de/pub/FileFormat/Patchmasterv9/. -% -% - opt: struct structure containing different options when -% loading the file, currently it only contains -% the filepath of the HEKA Patchmaster file -% which was loaded and serves as placeholder -% for additional options in the future. -% -% - RecTable: table Matlab table containing the recordings and -% several parameters associated with them. -% Each row represents a different recording. -% The recorded data are stored in RecTable.dataRaw -% and sorted by channel within, e.g. -% "RecTable.dataRaw{1}{2}" contains all sweeps -% of the first series/recording for the second -% channel. The corresponding name of the -% channels is stored in "RecTable.chNames{1}". -% -% - solutions: table Matlab table containing the solutions and -% composition (chemicals & concentration) -% used during the experiments. This table is -% read-out from the solTree of the HEKA -% Patchmaster file and requires that the -% recordings were associated with a solution -% base (otherwise this variable will be empty). -% The names of solutions correspond to the -% columns "ExternalSolution" and "InternalSolution" -% of the RecTable. -% -% See also HEKA_Importer.HI_loadHEKAFile -% HEKA_Importer.HI_ImportHEKAtoMat -% HEKA_Importer.HI_extractHEKAStimTree -% HEKA_Importer.HI_extractHEKASolutionTree -% HEKA_Importer.HI_extractHEKADataTree - - properties (Access = public) - - trees = []; % contains tree structure from Patchmaster files: dataTree, stimTree (stimulus parameters), and solTree (solutions) - opt - RecTable % contains recordings in table with various parameters, e.g. Rs, Cm, nSweeps ect. - solutions = [] - - end - - - properties (Access = private) - % PLACEHOLDER - - end - - %% - methods (Access = public) - function obj = HEKA_Importer(filepath,varargin) %CONSTRUCTOR - - P = inputParser; - P.addRequired('filepath',@ischar) - P.parse(filepath,varargin{:}); - obj.opt = P.Results; - - obj.HI_loadHEKAFile; - + + % Class to import HEKA Patchmaster files into Matlab. + % The core functionality is based on the HEKA importer from sigTool + % (https://doi.org/10.1016/j.neuron.2015.10.042 and + % https://github.com/irondukepublishing/sigTOOL) with modifications + % from Sammy Katta (https://github.com/sammykatta/Matlab-PatchMaster). + % + % This stand-alone importer works independently of sigTool and will + % additionally extract the stimulus (reconstructed from the pgf) + % and solutions (when solution base was active during recording). + % + % The recordings will be sorted into a table together with various + % parameters e.g series resistance (Rs), cell membrane capacitance (Cm), + % holding potential (Vhold), stimulus and solutions. + % + % Note: Currently, not all possible stimuli are supported. + % If your stimulus contains ramps or alternating segments, it will not be + % reconstructed properly. However, it should work fine for most stimuli + % and support for new stimuli will be added in the future. + % + % >> How to use: + % + % - INPUTS: + % + % - filepath char/string full file path and name of HEKA Patchmaster + % file that is to be loaded, + % e.g. to load HEKA Patchmaster file + % "MyData.dat" located in "C:\PatchClamp\" + % run "HEKA_Importer('C:\PatchClamp\MyData.dat')" + % + % *Alternative:* run "HEKA_Importer.GUI" which will open the file dialog + % box from which the Patchmaster file can be selected. + % + % - OUTPUTS: + % Heka_Importer creates object containing the following properties: + % + % - trees struct structure containing the dataTree + % (from the .pul file), the stimTree + % (from the .pgf file)and solTree + % (from the .sol file). These tree structures + % are how HEKA saves the metadata for + % different recordings. For details on the + % HEKA file format check + % ftp://server.hekahome.de/pub/FileFormat/Patchmasterv9/. + % + % - opt: struct structure containing different options when + % loading the file, currently it only contains + % the filepath of the HEKA Patchmaster file + % which was loaded and serves as placeholder + % for additional options in the future. + % + % - RecTable: table Matlab table containing the recordings and + % several parameters associated with them. + % Each row represents a different recording. + % The recorded data are stored in RecTable.dataRaw + % and sorted by channel within, e.g. + % "RecTable.dataRaw{1}{2}" contains all sweeps + % of the first series/recording for the second + % channel. The corresponding name of the + % channels is stored in "RecTable.chNames{1}". + % + % - solutions: table Matlab table containing the solutions and + % composition (chemicals & concentration) + % used during the experiments. This table is + % read-out from the solTree of the HEKA + % Patchmaster file and requires that the + % recordings were associated with a solution + % base (otherwise this variable will be empty). + % The names of solutions correspond to the + % columns "ExternalSolution" and "InternalSolution" + % of the RecTable. + % + % See also HEKA_Importer + % HEKA_Importer.HI_loadHEKAFile + % HEKA_Importer.HI_extractHEKASolutionTree + % HEKA_Importer.HI_extractHEKAStimTree + % HEKA_Importer.HI_extractHEKADataTree + % HEKA_Importer.HI_readPulseFileHEKA + % HEKA_Importer.HI_readStimulusFileHEKA + % HEKA_Importer.HI_readAmplifierFileHEKA + % HEKA_Importer.HI_readSolutionFileHEKA + + properties (Access = public) + + trees = []; % contains tree structure from Patchmaster files: dataTree, stimTree (stimulus parameters), and solTree (solutions) + opt + RecTable % contains recordings in table with various parameters, e.g. Rs, Cm, nSweeps ect. + solutions = [] + end + + + properties (Access = private) + % PLACEHOLDER + + end + + %% + methods (Access = public) + function obj = HEKA_Importer(filepath,varargin) %CONSTRUCTOR + + P = inputParser; + P.addRequired('filepath',@ischar) + P.parse(filepath,varargin{:}); + obj.opt = P.Results; + + obj.HI_loadHEKAFile; + end - - end - - methods (Static, Hidden=false) - - function obj = GUI() % OPEN GUI TO SELECT RECORDING - - [file,path] = uigetfile({'*.dat','HEKA PATCHMASTER FILE'},'Select HEKA Patchmaster file to import',... - 'MultiSelect','off'); - - obj = HEKA_Importer(fullfile(path,file)); - - end - - end - - - methods (Access = private) - - HI_loadHEKAFile(obj,varargin); - HI_ImportHEKAtoMat(obj) - HI_extractHEKADataTree(obj); - HI_extractHEKAStimTree(obj); - HI_extractHEKASolutionTree(obj); - - end - - %% Hide some of the handle class member functions for ease of use. - methods (Hidden=true) - function notify(~) - end - function addlistener(~) - end - function findobj(~) - end - function findprop(~) - end - function listener(~) - end - function delete(~) - end - - end + + end + + methods (Static, Hidden=false) + + function obj = GUI() % OPEN GUI TO SELECT RECORDING + + [file,path] = uigetfile({'*.dat','HEKA PATCHMASTER FILE'},'Select HEKA Patchmaster file to import',... + 'MultiSelect','off'); + + obj = HEKA_Importer(fullfile(path,file)); + + end + + end + + methods (Access = private) + + HI_loadHEKAFile(obj,varargin); + HI_ImportHEKAtoMat(obj) + HI_extractHEKADataTree(obj); + HI_extractHEKAStimTree(obj); + HI_extractHEKASolutionTree(obj); + str = HI_time2date(obj,t); + + HI_readPulseFileHEKA(obj,Level); + HI_readStimulusFileHEKA(obj,Level); + HI_readAmplifierFileHEKA(obj,Level); + HI_readSolutionFileHEKA(obj,Level); + end + + %% Hide some of the handle class member functions for ease of use. + methods (Hidden=true) + function notify(~) + end + function addlistener(~) + end + function findobj(~) + end + function findprop(~) + end + function listener(~) + end + function delete(~) + end + + end end diff --git a/@HEKA_Importer/HI_ImportHEKAtoMat.m b/@HEKA_Importer/HI_ImportHEKAtoMat.m index 9744ce7..d65a7cd 100644 --- a/@HEKA_Importer/HI_ImportHEKAtoMat.m +++ b/@HEKA_Importer/HI_ImportHEKAtoMat.m @@ -34,7 +34,10 @@ % HEKA_Importer.HI_extractHEKASolutionTree % HEKA_Importer.HI_extractHEKAStimTree % HEKA_Importer.HI_extractHEKADataTree - +% HEKA_Importer.HI_readPulseFileHEKA +% HEKA_Importer.HI_readStimulusFileHEKA +% HEKA_Importer.HI_readAmplifierFileHEKA +% HEKA_Importer.HI_readSolutionFileHEKA [pathname, filename, ext]=fileparts(obj.opt.filepath); @@ -54,8 +57,8 @@ %% GET DATA, STIM AND SOLUTION TREE -fileExt = {'.pul','.pgf','.sol'}; -treeName = {'dataTree','stimTree','solTree'}; +fileExt = {'.pul','.pgf','.sol','.amp'}; +treeName = {'dataTree','stimTree','solTree','ampTree'}; for iidx = fileExt fileExist = true; @@ -88,12 +91,24 @@ Position=ftell(fh); % Get the tree structures form the file sections - obj.trees.(treeName{strcmp(iidx, fileExt)})=getTree(fh, Sizes, Position, iidx{1}); + obj.opt.fileData.fh = fh; + obj.opt.fileData.Sizes = Sizes; + obj.opt.fileData.Position = Position; + obj.opt.fileData.fileExt = iidx{1}; + + obj.trees.(treeName{strcmp(iidx, fileExt)})=getTree(obj); + else obj.trees.(treeName{strcmp(iidx, fileExt)}) = []; end end +% clean-up remaining temporary data +try + obj.opt.fileData = rmfield(obj.opt.fileData,{'Sizes','Position','fileExt','Counter','Tree','Level','nchild'}); +catch +end + %% GET DATA if isBundled % Set offset for data @@ -136,7 +151,6 @@ obj.RecTable.dataRaw = vertcat(dataRaw{:}); obj.RecTable = struct2table(obj.RecTable); - end %-------------------------------------------------------------------------- @@ -157,11 +171,11 @@ isBundled=false; case {'DAT1' 'DAT2'} % Newer format - h.oVersion=fread(fh, 32, 'uint8=>char')'; - h.oTime=fread(fh, 1, 'double'); - h.oItems=fread(fh, 1, 'int32=>int32'); - h.oIsLittleEndian=fread(fh, 1, 'uint8=>logical'); - h.BundleHeaderSize=256; + h.oVersion = fread(fh, 32,'uint8=>char')'; + h.oTime = fread(fh, 1, 'double'); + h.oItems = fread(fh, 1, 'int32=>int32'); + h.oIsLittleEndian = fread(fh, 1, 'uint8=>logical'); + h.BundleHeaderSize = 256; switch h.oSignature case 'DAT1' h.oBundleItems=[]; @@ -169,10 +183,10 @@ case {'DAT2'} fseek(fh, 64, 'bof'); for k=1:12 - h.oBundleItems(k).oStart=fread(fh, 1, 'int32=>int32'); - h.oBundleItems(k).oLength=fread(fh, 1, 'int32=>int32'); - h.oBundleItems(k).oExtension=deblank(fread(fh, 8, 'uint8=>char')'); - h.oBundleItems(k).BundleItemSize=16; + h.oBundleItems(k).oStart = fread(fh, 1, 'int32=>int32'); + h.oBundleItems(k).oLength = fread(fh, 1, 'int32=>int32'); + h.oBundleItems(k).oExtension = deblank(fread(fh, 8, 'uint8=>char')'); + h.oBundleItems(k).BundleItemSize = 16; end isBundled=true; end @@ -185,668 +199,46 @@ %-------------------------------------------------------------------------- -function [Tree, Counter]=getTree(fh, Sizes, Position, ext) +function Tree=getTree(obj) %-------------------------------------------------------------------------- % Main entry point for loading tree -[Tree, Counter]=getTreeReentrant(fh, {}, Sizes, 0, Position, 0, ext); + +obj.opt.fileData.Counter = 0; +obj.opt.fileData.Tree = {}; +obj.opt.fileData.Level = 0; + +Tree = getTreeReentrant(obj,0); end -function [Tree, Position, Counter]=getTreeReentrant(fh, Tree, Sizes, Level, Position, Counter, ext) +function Tree=getTreeReentrant(obj,Level) %-------------------------------------------------------------------------- % Recursive routine called from LoadTree -switch ext +switch obj.opt.fileData.fileExt case '.pul' - [Tree, Position, Counter, nchild]=getOneDataLevel(fh, Tree, Sizes, Level, Position, Counter); + obj.HI_readPulseFileHEKA(Level); case '.pgf' - [Tree, Position, Counter, nchild]=getOneStimLevel(fh, Tree, Sizes, Level, Position, Counter); + obj.HI_readStimulusFileHEKA(Level); case '.sol' - [Tree, Position, Counter, nchild]=getOneSolutionLevel(fh, Tree, Sizes, Level, Position, Counter); -end - -for k=1:double(nchild) - [Tree, Position, Counter]=getTreeReentrant(fh, Tree, Sizes, Level+1, Position, Counter, ext); -end - -end - - -%-------------------------------------------------------------------------- -function [Tree, Position, Counter, nchild]=getOneDataLevel(fh, Tree, Sizes, Level, Position, Counter) -%-------------------------------------------------------------------------- -% Gets one record of the tree and the number of children -[s, Counter]=getOneRecord(fh, Level, Counter); -Tree{Counter, Level+1}=s; -Position=Position+Sizes(Level+1); -fseek(fh, Position, 'bof'); -nchild=fread(fh, 1, 'int32=>int32'); -Position=ftell(fh); -end - -%-------------------------------------------------------------------------- -function [rec, Counter]=getOneRecord(fh, Level, Counter) -%-------------------------------------------------------------------------- -% Gets one record -Counter=Counter+1; -switch Level - case 0 - rec=getRoot(fh); - case 1 - rec=getGroup(fh); - case 2 - rec=getSeries(fh); - case 3 - rec=getSweep(fh); - case 4 - rec=getTrace(fh); - otherwise - error('Unexpected Level'); -end -end - -% The functions below return data as defined by the HEKA PatchMaster -% specification - -%-------------------------------------------------------------------------- -function p=getRoot(fh) -%-------------------------------------------------------------------------- -p.RoVersion=fread(fh, 1, 'int32=>int32'); -p.RoMark=fread(fh, 1, 'int32=>int32');% = 4; (* INT32 *) -p.RoVersionName=deblank(fread(fh, 32, 'uint8=>char')');% = 8; (* String32Type *) -p.RoAuxFileName=deblank(fread(fh, 80, 'uint8=>char')');% = 40; (* String80Type *) -p.RoRootText=deblank(fread(fh, 400, 'uint8=>char')');% (* String400Type *) -p.RoStartTime=fread(fh, 1, 'double=>double') ;% = 520; (* LONGREAL *) -p.RoStartTimeMATLAB=time2date(p.RoStartTime); -p.RoMaxSamples=fread(fh, 1, 'int32=>int32'); % = 528; (* INT32 *) -p.RoCRC=fread(fh, 1, 'int32=>int32'); % = 532; (* CARD32 *) -p.RoFeatures=fread(fh, 1, 'int16=>int16'); % = 536; (* SET16 *) -p.RoFiller1=fread(fh, 1, 'int16=>int16');% = 538; (* INT16 *) -p.RoFiller2=fread(fh, 1, 'int32=>int32');% = 540; (* INT32 *) -p.RootRecSize= 544; -p=orderfields(p); - -end - -%-------------------------------------------------------------------------- -function g=getGroup(fh) -%-------------------------------------------------------------------------- -% Group -g.GrMark=fread(fh, 1, 'int32=>int32');% = 0; (* INT32 *) -g.GrLabel=deblank(fread(fh, 32, 'uint8=>char')');% = 4; (* String32Size *) -g.GrText=deblank(fread(fh, 80, 'uint8=>char')');% = 36; (* String80Size *) -g.GrExperimentNumber=fread(fh, 1, 'int32=>int32');% = 116; (* INT32 *) -g.GrGroupCount=fread(fh, 1, 'int32=>int32');% = 120; (* INT32 *) -g.GrCRC=fread(fh, 1, 'int32=>int32');% = 124; (* CARD32 *) -g.GroupRecSize=128;% (* = 16 * 8 *) -g=orderfields(g); - -end - -%-------------------------------------------------------------------------- -function s=getSeries(fh) -%-------------------------------------------------------------------------- -s.SeMark=fread(fh, 1, 'int32=>int32');% = 0; (* INT32 *) -s.SeLabel=deblank(fread(fh, 32, 'uint8=>char')');% = 4; (* String32Type *) -s.SeComment=deblank(fread(fh, 80, 'uint8=>char')');% = 36; (* String80Type *) -s.SeSeriesCount=fread(fh, 1, 'int32=>int32');% = 116; (* INT32 *) -s.SeNumbersw=fread(fh, 1, 'int32=>int32');% = 120; (* INT32 *) -s.SeAmplStateOffset=fread(fh, 1, 'int32=>int32');% = 124; (* INT32 *) -s.SeAmplStateSeries=fread(fh, 1, 'int32=>int32');% = 128; (* INT32 *) -s.SeSeriesType=fread(fh, 1, 'uint8=>uint8');% = 132; (* BYTE *) - -% Added 15.08.2012 -s.SeUseXStart=logical(fread(fh, 1, 'uint8=>uint8'));% = 133; (* BYTE *) - -s.SeFiller2=fread(fh, 1, 'uint8=>uint8');% = 134; (* BYTE *) -s.SeFiller3=fread(fh, 1, 'uint8=>uint8');% = 135; (* BYTE *) -s.SeTime=fread(fh, 1, 'double=>double') ;% = 136; (* LONGREAL *) -s.SeTimeMATLAB=time2date(s.SeTime); -s.SePageWidth=fread(fh, 1, 'double=>double') ;% = 144; (* LONGREAL *) -for k=1:4 - s.SeSwUserParamDescr(k).Name=deblank(fread(fh, 32, 'uint8=>char')');% - s.SeSwUserParamDescr(k).Unit=deblank(fread(fh, 8, 'uint8=>char')');% -end -s.SeFiller4=fread(fh, 32, 'uint8=>uint8');% = 312; (* 32 BYTE *) -s.SeSeUserParams=fread(fh, 4, 'double=>double');% = 344; (* ARRAY[0..3] OF LONGREAL *) -s.SeLockInParams=getSeLockInParams(fh);% = 376; (* SeLockInSize = 96, see "Pulsed.de" *) -s.SeAmplifierState=getAmplifierState(fh);% = 472; (* AmplifierStateSize = 400 *) -s.SeUsername=deblank(fread(fh, 80, 'uint8=>char')');% = 872; (* String80Type *) -for k=1:4 - s.SeSeUserParamDescr(k).Name=deblank(fread(fh, 32, 'uint8=>char')');% (* ARRAY[0..3] OF UserParamDescrType = 4*40 *) - s.SeSeUserParamDescr(k).Unit=deblank(fread(fh, 8, 'uint8=>char')');% -end -s.SeFiller5=fread(fh, 1, 'int32=>int32');% = 1112; (* INT32 *) -s.SeCRC=fread(fh, 1, 'int32=>int32');% = 1116; (* CARD32 *) - -% Added 15.08.2012 -s.SeSeUserParams2=fread(fh, 4, 'double=>double'); -for k=1:4 - s.SeSeUserParamDescr2(k).Name=deblank(fread(fh, 32, 'uint8=>char')');% - s.SeSeUserParamDescr2(k).Unit=deblank(fread(fh, 8, 'uint8=>char')');% -end -s.SeScanParams=fread(fh, 96, 'uint8=>uint8'); -s.SeriesRecSize=1408;% (* = 176 * 8 *) -s=orderfields(s); -s.Sweeps = []; % used to store all the sweeps within the recording structure later on - -end - -%-------------------------------------------------------------------------- -function sw=getSweep(fh) -%-------------------------------------------------------------------------- -sw.SwMark=fread(fh, 1, 'int32=>int32');% = 0; (* INT32 *) -sw.SwLabel=deblank(fread(fh, 32, 'uint8=>char')');% = 4; (* String32Type *) -sw.SwAuxDataFileOffset=fread(fh, 1, 'int32=>int32');% = 36; (* INT32 *) -sw.SwStimCount=fread(fh, 1, 'int32=>int32');% = 40; (* INT32 *) -sw.SwSweepCount=fread(fh, 1, 'int32=>int32');% = 44; (* INT32 *) -sw.SwTime=fread(fh, 1, 'double=>double');% = 48; (* LONGREAL *) -sw.SwTimeMATLAB=time2date(sw.SwTime);% Also add in MATLAB datenum format -sw.SwTimer=fread(fh, 1, 'double=>double');% = 56; (* LONGREAL *) -sw.SwSwUserParams=fread(fh, 4, 'double=>double');% = 64; (* ARRAY[0..3] OF LONGREAL *) -sw.SwTemperature=fread(fh, 1, 'double=>double');% = 96; (* LONGREAL *) -sw.SwOldIntSol=fread(fh, 1, 'int32=>int32');% = 104; (* INT32 *) -sw.SwOldExtSol=fread(fh, 1, 'int32=>int32');% = 108; (* INT32 *) -sw.SwDigitalIn=fread(fh, 1, 'int16=>int16');% = 112; (* SET16 *) -sw.SwSweepKind=fread(fh, 1, 'int16=>int16');% = 114; (* SET16 *) -sw.SwFiller1=fread(fh, 1, 'int32=>int32');% = 116; (* INT32 *) -sw.SwMarkers=fread(fh, 4, 'double=>double');% = 120; (* ARRAY[0..3] OF LONGREAL *) -sw.SwFiller2=fread(fh, 1, 'int32=>int32');% = 152; (* INT32 *) -sw.SwCRC=fread(fh, 1, 'int32=>int32');% = 156; (* CARD32 *) -sw.SweepRecSize = 160;% (* = 20 * 8 *) -sw=orderfields(sw); -sw.Traces = []; % used to store all the traces/channels within the sweep structure later on -end - -%-------------------------------------------------------------------------- -function tr=getTrace(fh) -%-------------------------------------------------------------------------- -tr.TrMark=fread(fh, 1, 'int32=>int32');% = 0; (* INT32 *) -tr.TrLabel=deblank(fread(fh, 32, 'uint8=>char')');% = 4; (* String32Type *) -tr.TrTraceCount=fread(fh, 1, 'int32=>int32');% = 36; (* INT32 *) -tr.TrData=fread(fh, 1, 'int32=>int32');% = 40; (* INT32 *) -tr.TrDataPoints=fread(fh, 1, 'int32=>int32');% = 44; (* INT32 *) -tr.TrInternalSolution=fread(fh, 1, 'int32=>int32');% = 48; (* INT32 *) -tr.TrAverageCount=fread(fh, 1, 'int32=>int32');% = 52; (* INT32 *) -tr.TrLeakCount=fread(fh, 1, 'int32=>int32');% = 56; (* INT32 *) -tr.TrLeakTraces=fread(fh, 1, 'int32=>int32');% = 60; (* INT32 *) -tr.TrDataKind=fread(fh, 1, 'uint16=>uint16');% = 64; (* SET16 *) NB Stored unsigned -tr.TrFiller1=fread(fh, 1, 'int16=>int16');% = 66; (* SET16 *) -tr.TrRecordingMode=fread(fh, 1, 'uint8=>uint8');% = 68; (* BYTE *) -tr.TrAmplIndex=fread(fh, 1, 'uint8=>uint8');% = 69; (* CHAR *) -tr.TrDataFormat=fread(fh, 1, 'uint8=>uint8');% = 70; (* BYTE *) -tr.TrDataAbscissa=fread(fh, 1, 'uint8=>uint8');% = 71; (* BYTE *) -tr.TrDataScaler=fread(fh, 1, 'double=>double');% = 72; (* LONGREAL *) -tr.TrTimeOffset=fread(fh, 1, 'double=>double');% = 80; (* LONGREAL *) -tr.TrZeroData=fread(fh, 1, 'double=>double');% = 88; (* LONGREAL *) -tr.TrYUnit=deblank(fread(fh, 8, 'uint8=>char')');% = 96; (* String8Type *) -tr.TrXInterval=fread(fh, 1, 'double=>double');% = 104; (* LONGREAL *) -tr.TrXStart=fread(fh, 1, 'double=>double');% = 112; (* LONGREAL *) -% 17.04.10 TrXUnit bytes may include some trailing characters after NULL -% byte -tr.TrXUnit=deblank(fread(fh, 8, 'uint8=>char')');% = 120; (* String8Type *) -tr.TrYRange=fread(fh, 1, 'double=>double');% = 128; (* LONGREAL *) -tr.TrYOffset=fread(fh, 1, 'double=>double');% = 136; (* LONGREAL *) -tr.TrBandwidth=fread(fh, 1, 'double=>double');% = 144; (* LONGREAL *) -tr.TrPipetteResistance=fread(fh, 1, 'double=>double');% = 152; (* LONGREAL *) -tr.TrCellPotential=fread(fh, 1, 'double=>double');% = 160; (* LONGREAL *) -tr.TrSealResistance=fread(fh, 1, 'double=>double');% = 168; (* LONGREAL *) -tr.TrCSlow=fread(fh, 1, 'double=>double');% = 176; (* LONGREAL *) -tr.TrGSeries=fread(fh, 1, 'double=>double');% = 184; (* LONGREAL *) -tr.TrRsValue=fread(fh, 1, 'double=>double');% = 192; (* LONGREAL *) -tr.TrGLeak=fread(fh, 1, 'double=>double');% = 200; (* LONGREAL *) -tr.TrMConductance=fread(fh, 1, 'double=>double');% = 208; (* LONGREAL *) -tr.TrLinkDAChannel=fread(fh, 1, 'int32=>int32');% = 216; (* INT32 *) -tr.TrValidYrange=fread(fh, 1, 'uint8=>logical');% = 220; (* BOOLEAN *) -tr.TrAdcMode=fread(fh, 1, 'uint8=>uint8');% = 221; (* CHAR *) -tr.TrAdcChannel=fread(fh, 1, 'int16=>int16');% = 222; (* INT16 *) -tr.TrYmin=fread(fh, 1, 'double=>double');% = 224; (* LONGREAL *) -tr.TrYmax=fread(fh, 1, 'double=>double');% = 232; (* LONGREAL *) -tr.TrSourceChannel=fread(fh, 1, 'int32=>int32');% = 240; (* INT32 *) -tr.TrExternalSolution=fread(fh, 1, 'int32=>int32');% = 244; (* INT32 *) -tr.TrCM=fread(fh, 1, 'double=>double');% = 248; (* LONGREAL *) -tr.TrGM=fread(fh, 1, 'double=>double');% = 256; (* LONGREAL *) -tr.TrPhase=fread(fh, 1, 'double=>double');% = 264; (* LONGREAL *) -tr.TrDataCRC=fread(fh, 1, 'int32=>int32');% = 272; (* CARD32 *) -tr.TrCRC=fread(fh, 1, 'int32=>int32');% = 276; (* CARD32 *) -tr.TrGS=fread(fh, 1, 'double=>double');% = 280; (* LONGREAL *) -tr.TrSelfChannel=fread(fh, 1, 'int32=>int32');% = 288; (* INT32 *) - -% Added 15.08.2012 -tr.TrInterleaveSize=fread(fh, 1, 'int32=>int32');% = 292; (* INT32 *) -tr.TrInterleaveSkip=fread(fh, 1, 'int32=>int32');% = 296; (* INT32 *) -tr.TrImageIndex=fread(fh, 1, 'int32=>int32');% = 300; (* INT32 *) -tr.TrMarkers=fread(fh, 10, 'double=>double');% = 304; (* ARRAY[0..9] OF LONGREAL *) -tr.TrSECM_X=fread(fh, 1, 'double=>double');% = 384; (* LONGREAL *) -tr.TrSECM_Y=fread(fh, 1, 'double=>double');% = 392; (* LONGREAL *) -tr.TrSECM_Z=fread(fh, 1, 'double=>double');% = 400; (* LONGREAL *) -tr.TraceRecSize=408; - -tr=orderfields(tr); - -end - -%% GET SOLUTION TREE -%-------------------------------------------------------------------------- -function [Tree, Position, Counter, nchild]=getOneSolutionLevel(fh, Tree, Sizes, Level, Position, Counter) -%-------------------------------------------------------------------------- -% Gets one record of the tree and the number of children -[s, Counter]=getOneSolutionRecord(fh, Level, Counter); -Tree{Counter, Level+1}=s; -Position=Position+Sizes(Level+1); -fseek(fh, Position, 'bof'); -nchild=fread(fh, 1, 'int32=>int32'); -Position=ftell(fh); - -end - -%-------------------------------------------------------------------------- -function [rec, Counter]=getOneSolutionRecord(fh, Level, Counter) -%-------------------------------------------------------------------------- -% Gets one record -Counter=Counter+1; -switch Level - case 0 - rec=getSolutionRoot(fh); - case 1 - rec=getSolution(fh); - case 2 - rec=getChemical(fh); - - otherwise - error('Unexpected Level'); -end - -end - -%-------------------------------------------------------------------------- -function p=getSolutionRoot(fh) -%-------------------------------------------------------------------------- -p.RoVersion=fread(fh, 1, 'int16=>int16'); % = 0; (* INT16 *) -p.RoDataBaseName=deblank(fread(fh, 80, 'uint8=>char')');% = 2; (* SolutionNameSize *) -p.RoSpare1=fread(fh, 1, 'int16=>int16');% = 82; (* INT16 *) -p.RoCRC=fread(fh, 1, 'int32=>int32'); % = 84; (* CARD32 *) -p.RootSize = 88;% = 88 - -p=orderfields(p); - -end - - -function s=getSolution(fh) -%-------------------------------------------------------------------------- -% Stimulus level -s.SoNumber=fread(fh, 1, 'int32=>int32');% = 0; (* INT32 *) -s.SoName=deblank(fread(fh, 80, 'uint8=>char')');% = 4; (* SolutionNameSize *) -s.SoNumeric=fread(fh, 1, 'real*4=>double');% = 84; (* REAL *) *) -s.SoNumericName=deblank(fread(fh, 30, 'uint8=>char')');% = 88; (* ChemicalNameSize *) -s.SoPH=fread(fh, 1, 'real*4=>double');% = 118; (* REAL *) -s.SopHCompound=deblank(fread(fh, 30, 'uint8=>char')');% = 122; (* ChemicalNameSize *) -s.soOsmol=fread(fh, 1, 'real*4=>double'); %152; (* REAL *) -s.SoCRC=fread(fh, 1, 'int32=>int32') ;% = 156; (* CARD32 *) -s.SolutionSize=160;% = 160 - -s=orderfields(s); + obj.HI_readSolutionFileHEKA(Level); + case '.amp' + obj.HI_readAmplifierFileHEKA(Level); end -%-------------------------------------------------------------------------- -function c=getChemical(fh) -%-------------------------------------------------------------------------- -c.ChConcentration=fread(fh, 1, 'real*4=>double');% = 0; (* REAL *) -c.ChName=deblank(fread(fh, 30, 'uint8=>char')');% = 4; (* ChemicalNameSize *) -c.ChSpare1=fread(fh, 1, 'int16=>int16');% = 34; (* INT16 *) -c.ChCRC=fread(fh, 1, 'int32=>int32')';% 36; (* CARD32 *) -c.ChemicalSize=40;% = 40 - -c=orderfields(c); - -end - - -%% GET STIMULUS TREE -%-------------------------------------------------------------------------- -function [Tree, Position, Counter, nchild]=getOneStimLevel(fh, Tree, Sizes, Level, Position, Counter) -%-------------------------------------------------------------------------- -% Gets one record of the tree and the number of children -[s, Counter]=getOneStimRecord(fh, Level, Counter); -Tree{Counter, Level+1}=s; -Position=Position+Sizes(Level+1); -fseek(fh, Position, 'bof'); -nchild=fread(fh, 1, 'int32=>int32'); -Position=ftell(fh); - +for k=1:double(obj.opt.fileData.nchild) + getTreeReentrant(obj,Level+1); end -%-------------------------------------------------------------------------- -function [rec, Counter]=getOneStimRecord(fh, Level, Counter) -%-------------------------------------------------------------------------- -% Gets one record -Counter=Counter+1; -switch Level - case 0 - rec=getStimRoot(fh); - case 1 - rec=getStimulation(fh); - case 2 - rec=getChannel(fh); - case 3 - rec=getStimSegment(fh); - otherwise - error('Unexpected Level'); -end +Tree = obj.opt.fileData.Tree; -end -% The functions below return data as defined by the HEKA PatchMaster -% specification -%-------------------------------------------------------------------------- -function p=getStimRoot(fh) -%-------------------------------------------------------------------------- -p.RoVersion=fread(fh, 1, 'int32=>int32'); -p.RoMark=fread(fh, 1, 'int32=>int32');% = 4; (* INT32 *) -p.RoVersionName=deblank(fread(fh, 32, 'uint8=>char')');% = 8; (* String32Type *) -p.RoMaxSamples=fread(fh, 1, 'int32=>int32'); % = 40; (* INT32 *) -p.RoFiller1 = fread(fh, 1, 'int32=>int32');% = 44; (* INT32 *) -p.RoParams = fread(fh, 10, 'double=>double');% = 48; (* ARRAY[0..9] OF LONGREAL *) -for k=1:10 - p.RoParamText{k}=deblank(fread(fh, 32, 'uint8=>char')');% = 128; (* ARRAY[0..9],[0..31]OF CHAR *) -end -p.RoReserved = fread(fh, 32, 'int32=>int32');% = 448; (* INT32 *) -p.RoFiller2= fread(fh, 1, 'int32=>int32');% = 576; (* INT32 *) -p.RoCRC= fread(fh, 1, 'int32=>int32');% = 580; (* CARD32 *) -p.RootRecSize= 584; % (* = 73 * 8 *) -p=orderfields(p); end -%-------------------------------------------------------------------------- -function s=getStimulation(fh) -%-------------------------------------------------------------------------- -% Stimulus level -s.stMark=fread(fh, 1, 'int32=>int32');% = 0; (* INT32 *) -s.stEntryName=deblank(fread(fh, 32, 'uint8=>char')');% = 4; (* String32Type *) -s.stFileName=deblank(fread(fh, 32, 'uint8=>char')');% = 36; (* String32Type *) -s.stAnalName=deblank(fread(fh, 32, 'uint8=>char')');% = 68; (* String32Type *) -s.stDataStartSegment=fread(fh, 1, 'int32=>int32');% = 100; (* INT32 *) -s.stDataStartTime=fread(fh, 1, 'double=>double') ;% = 104; (* LONGREAL *) -s.stDataStartTimeMATLAB=time2date(s.stDataStartTime); -s.stSampleInterval=fread(fh, 1, 'double=>double') ;% = 112; (* LONGREAL *) -s.stSweepInterval=fread(fh, 1, 'double=>double') ;% = 120; (* LONGREAL *) -s.stLeakDelay=fread(fh, 1, 'double=>double') ;% = 128; (* LONGREAL *) -s.stFilterFactor=fread(fh, 1, 'double=>double') ;% = 136; (* LONGREAL *) -s.stNumberSweeps=fread(fh, 1, 'int32=>int32');% = 144; (* INT32 *) -s.stNumberLeaks=fread(fh, 1, 'int32=>int32');% = 148; (* INT32 *) -s.stNumberAverages=fread(fh, 1, 'int32=>int32');% = 152; (* INT32 *) -s.stActualAdcChannels=fread(fh, 1, 'int32=>int32');% = 156; (* INT32 *) -s.stActualDacChannels=fread(fh, 1, 'int32=>int32');% = 160; (* INT32 *) -s.stExtTrigger=fread(fh, 1, 'uint8=>uint8');% = 164; (* BYTE *) -s.stNoStartWait=fread(fh, 1, 'uint8=>logical');% = 165; (* BOOLEAN *) -s.stUseScanRates=fread(fh, 1, 'uint8=>logical');% = 166; (* BOOLEAN *) -s.stNoContAq=fread(fh, 1, 'uint8=>logical');% = 167; (* BOOLEAN *) -s.stHasLockIn=fread(fh, 1, 'uint8=>logical');% = 168; (* BOOLEAN *) -s.stOldStartMacKind=fread(fh, 1, 'uint8=>char');% = 169; (* CHAR *) -s.stOldEndMacKind=fread(fh, 1, 'uint8=>logical');% = 170; (* BOOLEAN *) -s.stAutoRange=fread(fh, 1, 'uint8=>uint8');% = 171; (* BYTE *) -s.stBreakNext=fread(fh, 1, 'uint8=>logical');% = 172; (* BOOLEAN *) -s.stIsExpanded=fread(fh, 1, 'uint8=>logical');% = 173; (* BOOLEAN *) -s.stLeakCompMode=fread(fh, 1, 'uint8=>logical');% = 174; (* BOOLEAN *) -s.stHasChirp=fread(fh, 1, 'uint8=>logical');% = 175; (* BOOLEAN *) -s.stOldStartMacro=deblank(fread(fh, 32, 'uint8=>char')');% = 176; (* String32Type *) -s.stOldEndMacro=deblank(fread(fh, 32, 'uint8=>char')');% = 208; (* String32Type *) -s.sIsGapFree=fread(fh, 1, 'uint8=>logical');% = 240; (* BOOLEAN *) -s.sHandledExternally=fread(fh, 1, 'uint8=>logical');% = 241; (* BOOLEAN *) -s.stFiller1=fread(fh, 1, 'uint8=>logical');% = 242; (* BOOLEAN *) -s.stFiller2=fread(fh, 1, 'uint8=>logical');% = 243; (* BOOLEAN *) -s.stCRC=fread(fh, 1, 'int32=>int32'); % = 244; (* CARD32 *) -s.stTag=deblank(fread(fh, 32, 'uint8=>char')');% = 248; (* String32Type *) -s.StimulationRecSize = 280;% (* = 35 * 8 *) - -s=orderfields(s); -end - -%-------------------------------------------------------------------------- -function c=getChannel(fh) -%-------------------------------------------------------------------------- -c.chMark=fread(fh, 1, 'int32=>int32');% = 0; (* INT32 *) -c.chLinkedChannel=fread(fh, 1, 'int32=>int32');% = 4; (* INT32 *) -c.chCompressionFactor=fread(fh, 1, 'int32=>int32');% = 8; (* INT32 *) -c.chYUnit=deblank(fread(fh, 8, 'uint8=>char')');% = 12; (* String8Type *) -c.chAdcChannel=fread(fh, 1, 'int16=>int16');% = 20; (* INT16 *) -c.chAdcMode=fread(fh, 1, 'uint8=>uint8');% = 22; (* BYTE *) -c.chDoWrite=fread(fh, 1, 'uint8=>logical');% = 23; (* BOOLEAN *) -c.stLeakStore=fread(fh, 1, 'uint8=>uint8');% = 24; (* BYTE *) -c.chAmplMode=fread(fh, 1, 'uint8=>uint8');% = 25; (* BYTE *) -c.chOwnSegTime=fread(fh, 1, 'uint8=>logical');% = 26; (* BOOLEAN *) -c.chSetLastSegVmemb=fread(fh, 1, 'uint8=>logical');% = 27; (* BOOLEAN *) -c.chDacChannel=fread(fh, 1, 'int16=>int16');% = 28; (* INT16 *) -c.chDacMode=fread(fh, 1, 'uint8=>uint8');% = 30; (* BYTE *) -c.chHasLockInSquare=fread(fh, 1, 'uint8=>uint8');% = 31; (* BYTE *) -c.chRelevantXSegment=fread(fh, 1, 'int32=>int32');% = 32; (* INT32 *) -c.chRelevantYSegment=fread(fh, 1, 'int32=>int32');% = 36; (* INT32 *) -c.chDacUnit=deblank(fread(fh, 8, 'uint8=>char')');% = 40; (* String8Type *) -c.chHolding=fread(fh, 1, 'double=>double') ;% = 48; (* LONGREAL *) -c.chLeakHolding=fread(fh, 1, 'double=>double') ;% = 56; (* LONGREAL *) -c.chLeakSize=fread(fh, 1, 'double=>double') ;% = 64; (* LONGREAL *) -c.chLeakHoldMode=fread(fh, 1, 'uint8=>uint8');% = 72; (* BYTE *) -c.chLeakAlternate=fread(fh, 1, 'uint8=>logical');% = 73; (* BOOLEAN *) -c.chAltLeakAveraging=fread(fh, 1, 'uint8=>logical');% = 74; (* BOOLEAN *) -c.chLeakPulseOn=fread(fh, 1, 'uint8=>logical');% = 75; (* BOOLEAN *) -c.chStimToDacID=fread(fh, 1, 'int16=>int16');% = 76; (* SET16 *) -c.chCompressionMode=fread(fh, 1, 'int16=>int16');% = 78; (* SET16 *) -c.chCompressionSkip=fread(fh, 1, 'int32=>int32');% = 80; (* INT32 *) -c.chDacBit=fread(fh, 1, 'int16=>int16');% = 84; (* INT16 *) -c.chHasLockInSine=fread(fh, 1, 'uint8=>logical');% = 86; (* BOOLEAN *) -c.chBreakMode=fread(fh, 1, 'uint8=>uint8');% = 87; (* BYTE *) -c.chZeroSeg=fread(fh, 1, 'int32=>int32');% = 88; (* INT32 *) -c.chFiller1=fread(fh, 1, 'int32=>int32');% = 92; (* INT32 *) -c.chSine_Cycle=fread(fh, 1, 'double=>double') ;% = 96; (* LONGREAL *) -c.chSine_Amplitude=fread(fh, 1, 'double=>double') ;% = 104; (* LONGREAL *) -c.chLockIn_VReversal=fread(fh, 1, 'double=>double') ;% = 112; (* LONGREAL *) -c.chChirp_StartFreq=fread(fh, 1, 'double=>double') ;% = 120; (* LONGREAL *) -c.chChirp_EndFreq=fread(fh, 1, 'double=>double') ;% = 128; (* LONGREAL *) -c.chChirp_MinPoints=fread(fh, 1, 'double=>double') ;% = 136; (* LONGREAL *) -c.chSquare_NegAmpl=fread(fh, 1, 'double=>double') ;% = 144; (* LONGREAL *) -c.chSquare_DurFactor=fread(fh, 1, 'double=>double') ;% = 152; (* LONGREAL *) -c.chLockIn_Skip=fread(fh, 1, 'int32=>int32');% = 160; (* INT32 *) -c.chPhoto_MaxCycles=fread(fh, 1, 'int32=>int32');% = 164; (* INT32 *) -c.chPhoto_SegmentNo=fread(fh, 1, 'int32=>int32');% = 168; (* INT32 *) -c.chLockIn_AvgCycles=fread(fh, 1, 'int32=>int32');% = 172; (* INT32 *) -c.chImaging_RoiNo=fread(fh, 1, 'int32=>int32');% = 176; (* INT32 *) -c.chChirp_Skip=fread(fh, 1, 'int32=>int32');% = 180; (* INT32 *) -c.chChirp_Amplitude=fread(fh, 1, 'double=>double') ;% = 184; (* LONGREAL *) -c.chPhoto_Adapt=fread(fh, 1, 'uint8=>uint8');% = 192; (* BYTE *) -c.chSine_Kind=fread(fh, 1, 'uint8=>uint8');% = 193; (* BYTE *) -c.chChirp_PreChirp=fread(fh, 1, 'uint8=>uint8');% = 194; (* BYTE *) -c.chSine_Source=fread(fh, 1, 'uint8=>uint8');% = 195; (* BYTE *) -c.chSquare_NegSource=fread(fh, 1, 'uint8=>uint8');% = 196; (* BYTE *) -c.chSquare_PosSource=fread(fh, 1, 'uint8=>uint8');% = 197; (* BYTE *) -c.chChirp_Kind=fread(fh, 1, 'uint8=>uint8');% = 198; (* BYTE *) -c.chChirp_Source=fread(fh, 1, 'uint8=>uint8');% = 199; (* BYTE *) -c.chDacOffset=fread(fh, 1, 'double=>double') ;% = 200; (* LONGREAL *) -c.chAdcOffset=fread(fh, 1, 'double=>double') ;% = 208; (* LONGREAL *) -c.chTraceMathFormat=fread(fh, 1, 'uint8=>uint8');% = 216; (* BYTE *) -c.chHasChirp=fread(fh, 1, 'uint8=>logical');% = 217; (* BOOLEAN *) -c.chSquare_Kind=fread(fh, 1, 'uint8=>uint8');% = 218; (* BYTE *) -c.chFiller2=fread(fh,13,'uint8=>char');% = 219; (* ARRAY[0..13] OF CHAR *) -c.chSquare_Cycle=fread(fh, 1, 'double=>double') ;% = 232; (* LONGREAL *) -c.chSquare_PosAmpl=fread(fh, 1, 'double=>double') ;% = 240; (* LONGREAL *) -c.chCompressionOffset=fread(fh, 1, 'int32=>int32');% = 248; (* INT32 *) -c.chPhotoMode=fread(fh, 1, 'int32=>int32');% = 252; (* INT32 *) -c.chBreakLevel=fread(fh, 1, 'double=>double') ;% = 256; (* LONGREAL *) -c.chTraceMath=deblank(fread(fh,128,'uint8=>char')');% = 264; (* String128Type *) -c.chOldCRC=fread(fh, 1, 'int32=>int32');% = 268; (* CARD32 *) -c.chFiller3=fread(fh, 1, 'int32=>int32');% = 392; (* INT32 *) -c.chCRC=fread(fh, 1, 'int32=>int32');% = 396; (* CARD32 *) -c.ChannelRecSize = 400;% (* = 50 * 8 *) -c=orderfields(c); - -end - -%-------------------------------------------------------------------------- -function ss=getStimSegment(fh) -%-------------------------------------------------------------------------- -ss.seMark=fread(fh, 1, 'int32=>int32');% = 0; (* INT32 *) -ss.seClass=fread(fh, 1, 'uint8=>uint8');% = 4; (* BYTE *) -ss.seDoStore=fread(fh, 1, 'uint8=>logical');% = 5; (* BOOLEAN *) -ss.seVoltageIncMode=fread(fh, 1, 'uint8=>uint8');% = 6; (* BYTE *) -ss.seDurationIncMode=fread(fh, 1, 'uint8=>uint8');% = 7; (* BYTE *) -ss.seVoltage=fread(fh, 1, 'double=>double');% = 8; (* LONGREAL *) -ss.seVoltageSource=fread(fh, 1, 'int32=>int32');% = 16; (* INT32 *) -ss.seDeltaVFactor=fread(fh, 1, 'double=>double');% = 20; (* LONGREAL *) -ss.seDeltaVIncrement=fread(fh, 1, 'double=>double');% = 28; (* LONGREAL *) -ss.seDuration=fread(fh, 1, 'double=>double');% = 36; (* LONGREAL *) -ss.seDurationSource=fread(fh, 1, 'int32=>int32');% = 44; (* INT32 *) -ss.seDeltaTFactor=fread(fh, 1, 'double=>double');% = 48; (* LONGREAL *) -ss.seDeltaTIncrement=fread(fh, 1, 'double=>double');% = 56; (* LONGREAL *) -ss.seFiller1=fread(fh, 1, 'int32=>int32');% = 64; (* INT32 *) -ss.seCRC=fread(fh, 1, 'int32=>int32');% = 68; (* CARD32 *) -ss.seScanRate=fread(fh, 1, 'double=>double');% = 72; (* LONGREAL *) -ss.StimSegmentRecSize = 80;% (* = 10 * 8 *) -ss=orderfields(ss); - -end - - - -%% GET AMPLIFIER DATA -%-------------------------------------------------------------------------- -function L=getSeLockInParams(fh) -%-------------------------------------------------------------------------- -offset=ftell(fh); -L.loExtCalPhase=fread(fh, 1, 'double=>double') ;% = 0; (* LONGREAL *) -L.loExtCalAtten=fread(fh, 1, 'double=>double') ;% = 8; (* LONGREAL *) -L.loPLPhase=fread(fh, 1, 'double=>double') ;% = 16; (* LONGREAL *) -L.loPLPhaseY1=fread(fh, 1, 'double=>double') ;% = 24; (* LONGREAL *) -L.loPLPhaseY2=fread(fh, 1, 'double=>double') ;% = 32; (* LONGREAL *) -L.loUsedPhaseShift=fread(fh, 1, 'double=>double') ;% = 40; (* LONGREAL *) -L.loUsedAttenuation=fread(fh, 1, 'double=>double');% = 48; (* LONGREAL *) -L.loFiller1=fread(fh, 1, 'double=>double'); -L.loExtCalValid=fread(fh, 1, 'uint8=>logical') ;% = 64; (* BOOLEAN *) -L.loPLPhaseValid=fread(fh, 1, 'uint8=>logical') ;% = 65; (* BOOLEAN *) -L.loLockInMode=fread(fh, 1, 'uint8=>uint8') ;% = 66; (* BYTE *) -L.loCalMode=fread(fh, 1, 'uint8=>uint8') ;% = 67; (* BYTE *) -L.LockInParamsSize=96; -fseek(fh, offset+L.LockInParamsSize, 'bof'); - -end - -%-------------------------------------------------------------------------- -function A=getAmplifierState(fh) -%-------------------------------------------------------------------------- -offset=ftell(fh); -A.E9StateVersion=fread(fh, 1, 'double=>double');% = 0; (* 8 = SizeStateVersion *) -A.E9RealCurrentGain=fread(fh, 1, 'double=>double');% = 8; (* LONGREAL *) -A.E9RealF2Bandwidth=fread(fh, 1, 'double=>double');% = 16; (* LONGREAL *) -A.E9F2Frequency=fread(fh, 1, 'double=>double');% = 24; (* LONGREAL *) -A.E9RsValue=fread(fh, 1, 'double=>double');% = 32; (* LONGREAL *) -A.E9RsFraction=fread(fh, 1, 'double=>double');% = 40; (* LONGREAL *) -A.E9GLeak=fread(fh, 1, 'double=>double');% = 48; (* LONGREAL *) -A.E9CFastAmp1=fread(fh, 1, 'double=>double');% = 56; (* LONGREAL *) -A.E9CFastAmp2=fread(fh, 1, 'double=>double');% = 64; (* LONGREAL *) -A.E9CFastTau=fread(fh, 1, 'double=>double');% = 72; (* LONGREAL *) -A.E9CSlow=fread(fh, 1, 'double=>double');% = 80; (* LONGREAL *) -A.E9GSeries=fread(fh, 1, 'double=>double');% = 88; (* LONGREAL *) -A.E9StimDacScale=fread(fh, 1, 'double=>double');% = 96; (* LONGREAL *) -A.E9CCStimScale=fread(fh, 1, 'double=>double');% = 104; (* LONGREAL *) -A.E9VHold=fread(fh, 1, 'double=>double');% = 112; (* LONGREAL *) -A.E9LastVHold=fread(fh, 1, 'double=>double');% = 120; (* LONGREAL *) -A.E9VpOffset=fread(fh, 1, 'double=>double');% = 128; (* LONGREAL *) -A.E9VLiquidJunction=fread(fh, 1, 'double=>double');% = 136; (* LONGREAL *) -A.E9CCIHold=fread(fh, 1, 'double=>double');% = 144; (* LONGREAL *) -A.E9CSlowStimVolts=fread(fh, 1, 'double=>double');% = 152; (* LONGREAL *) -A.E9CCtr.TrackVHold=fread(fh, 1, 'double=>double');% = 160; (* LONGREAL *) -A.E9TimeoutLength=fread(fh, 1, 'double=>double');% = 168; (* LONGREAL *) -A.E9SearchDelay=fread(fh, 1, 'double=>double');% = 176; (* LONGREAL *) -A.E9MConductance=fread(fh, 1, 'double=>double');% = 184; (* LONGREAL *) -A.E9MCapacitance=fread(fh, 1, 'double=>double');% = 192; (* LONGREAL *) -A.E9SerialNumber=fread(fh, 1, 'double=>double');% = 200; (* 8 = SizeSerialNumber *) -A.E9E9Boards=fread(fh, 1, 'int16=>int16');% = 208; (* INT16 *) -A.E9CSlowCycles=fread(fh, 1, 'int16=>int16');% = 210; (* INT16 *) -A.E9IMonAdc=fread(fh, 1, 'int16=>int16');% = 212; (* INT16 *) -A.E9VMonAdc=fread(fh, 1, 'int16=>int16');% = 214; (* INT16 *) -A.E9MuxAdc=fread(fh, 1, 'int16=>int16');% = 216; (* INT16 *) -A.E9TstDac=fread(fh, 1, 'int16=>int16');% = 218; (* INT16 *) -A.E9StimDac=fread(fh, 1, 'int16=>int16');% = 220; (* INT16 *) -A.E9StimDacOffset=fread(fh, 1, 'int16=>int16');% = 222; (* INT16 *) -A.E9MaxDigitalBit=fread(fh, 1, 'int16=>int16');% = 224; (* INT16 *) -A.E9SpareInt1=fread(fh, 1, 'int16=>int16');% = 226; (* INT16 *) -A.E9SpareInt2=fread(fh, 1, 'int16=>int16');% = 228; (* INT16 *) -A.E9SpareInt3=fread(fh, 1, 'int16=>int16');% = 230; (* INT16 *) - -A.E9AmplKind=fread(fh, 1, 'uint8=>uint8');% = 232; (* BYTE *) -A.E9IsEpc9N=fread(fh, 1, 'uint8=>uint8');% = 233; (* BYTE *) -A.E9ADBoard=fread(fh, 1, 'uint8=>uint8');% = 234; (* BYTE *) -A.E9BoardVersion=fread(fh, 1, 'uint8=>uint8');% = 235; (* BYTE *) -A.E9ActiveE9Board=fread(fh, 1, 'uint8=>uint8');% = 236; (* BYTE *) -A.E9Mode=fread(fh, 1, 'uint8=>uint8');% = 237; (* BYTE *) -A.E9Range=fread(fh, 1, 'uint8=>uint8');% = 238; (* BYTE *) -A.E9F2Response=fread(fh, 1, 'uint8=>uint8');% = 239; (* BYTE *) - -A.E9RsOn=fread(fh, 1, 'uint8=>uint8');% = 240; (* BYTE *) -A.E9CSlowRange=fread(fh, 1, 'uint8=>uint8');% = 241; (* BYTE *) -A.E9CCRange=fread(fh, 1, 'uint8=>uint8');% = 242; (* BYTE *) -A.E9CCGain=fread(fh, 1, 'uint8=>uint8');% = 243; (* BYTE *) -A.E9CSlowToTstDac=fread(fh, 1, 'uint8=>uint8');% = 244; (* BYTE *) -A.E9StimPath=fread(fh, 1, 'uint8=>uint8');% = 245; (* BYTE *) -A.E9CCtr.TrackTau=fread(fh, 1, 'uint8=>uint8');% = 246; (* BYTE *) -A.E9WasClipping=fread(fh, 1, 'uint8=>uint8');% = 247; (* BYTE *) - -A.E9RepetitiveCSlow=fread(fh, 1, 'uint8=>uint8');% = 248; (* BYTE *) -A.E9LastCSlowRange=fread(fh, 1, 'uint8=>uint8');% = 249; (* BYTE *) -A.E9Locked=fread(fh, 1, 'uint8=>uint8');% = 250; (* BYTE *) -A.E9CanCCFast=fread(fh, 1, 'uint8=>uint8');% = 251; (* BYTE *) -A.E9CanLowCCRange=fread(fh, 1, 'uint8=>uint8');% = 252; (* BYTE *) -A.E9CanHighCCRange=fread(fh, 1, 'uint8=>uint8');% = 253; (* BYTE *) -A.E9CanCCtr.Tracking=fread(fh, 1, 'uint8=>uint8');% = 254; (* BYTE *) -A.E9HasVmonPath=fread(fh, 1, 'uint8=>uint8');% = 255; (* BYTE *) - -A.E9HasNewCCMode=fread(fh, 1, 'uint8=>uint8');% = 256; (* BYTE *) -A.E9Selector=fread(fh, 1, 'uint8=>char');% = 257; (* CHAR *) -A.E9HoldInverted=fread(fh, 1, 'uint8=>uint8');% = 258; (* BYTE *) -A.E9AutoCFast=fread(fh, 1, 'uint8=>uint8');% = 259; (* BYTE *) -A.E9AutoCSlow=fread(fh, 1, 'uint8=>uint8');% = 260; (* BYTE *) -A.E9HasVmonX100=fread(fh, 1, 'uint8=>uint8');% = 261; (* BYTE *) -A.E9TestDacOn=fread(fh, 1, 'uint8=>uint8');% = 262; (* BYTE *) -A.E9QMuxAdcOn=fread(fh, 1, 'uint8=>uint8');% = 263; (* BYTE *) - -A.E9RealImon1Bandwidth=fread(fh, 1, 'double=>double');% = 264; (* LONGREAL *) -A.E9StimScale=fread(fh, 1, 'double=>double');% = 272; (* LONGREAL *) - -A.E9Gain=fread(fh, 1, 'uint8=>uint8');% = 280; (* BYTE *) -A.E9Filter1=fread(fh, 1, 'uint8=>uint8');% = 281; (* BYTE *) -A.E9StimFilterOn=fread(fh, 1, 'uint8=>uint8');% = 282; (* BYTE *) -A.E9RsSlow=fread(fh, 1, 'uint8=>uint8');% = 283; (* BYTE *) -A.E9Old1=fread(fh, 1, 'uint8=>uint8');% = 284; (* BYTE *) -A.E9CCCFastOn=fread(fh, 1, 'uint8=>uint8');% = 285; (* BYTE *) -A.E9CCFastSpeed=fread(fh, 1, 'uint8=>uint8');% = 286; (* BYTE *) -A.E9F2Source=fread(fh, 1, 'uint8=>uint8');% = 287; (* BYTE *) - -A.E9TestRange=fread(fh, 1, 'uint8=>uint8');% = 288; (* BYTE *) -A.E9TestDacPath=fread(fh, 1, 'uint8=>uint8');% = 289; (* BYTE *) -A.E9MuxChannel=fread(fh, 1, 'uint8=>uint8');% = 290; (* BYTE *) -A.E9MuxGain64=fread(fh, 1, 'uint8=>uint8');% = 291; (* BYTE *) -A.E9VmonX100=fread(fh, 1, 'uint8=>uint8');% = 292; (* BYTE *) -A.E9IsQuadro=fread(fh, 1, 'uint8=>uint8');% = 293; (* BYTE *) -A.E9SpareBool4=fread(fh, 1, 'uint8=>uint8');% = 294; (* BYTE *) -A.E9SpareBool5=fread(fh, 1, 'uint8=>uint8');% = 295; (* BYTE *) - -A.E9StimFilterHz=fread(fh, 1, 'double=>double');% = 296; (* LONGREAL *) -A.E9RsTau=fread(fh, 1, 'double=>double');% = 304; (* LONGREAL *) -A.E9FilterOffsetDac=fread(fh, 1, 'int16=>int16');% = 312; (* INT16 *) -A.E9ReferenceDac=fread(fh, 1, 'int16=>int16');% = 314; (* INT16 *) -A.E9SpareInt6=fread(fh, 1, 'int16=>int16');% = 316; (* INT16 *) -A.E9SpareInt7=fread(fh, 1, 'int16=>int16');% = 318; (* INT16 *) -A.E9Spares1=320; - -A.E9CalibDate=fread(fh, 2, 'double=>double');% = 344; (* 16 = SizeCalibDate *) -A.E9SelHold=fread(fh, 1, 'double=>double');% = 360; (* LONGREAL *) -A.AmplifierStateSize = 400; -fseek(fh, offset+A.AmplifierStateSize, 'bof'); - -end %-------------------------------------------------------------------------- function matData2=LocalImportGroup(fh, dataTree, grp, grp_row) @@ -859,7 +251,7 @@ % Collect the series headers and row numbers for this group into a % structure array -[ser_s, ser_row, nseries]=getSeriesHeaders(dataTree, grp_row, grp); +[ser_row, nseries]=getSeriesHeaders(dataTree, grp_row, grp); % Pad for last series ser_row(nseries+1)=grp_row(grp+1); @@ -928,8 +320,7 @@ end end end - - + % Now scale the data to real world units % Note we also apply zero adjustment for col=1:size(data,2) @@ -943,7 +334,6 @@ end - if numel(unique(dataoffsets)) +% ser_s(nseries+1)=tree{k, 3}; %#ok ser_row(nseries+1)=k; %#ok nseries=nseries+1; end @@ -1098,15 +488,3 @@ return end -%-------------------------------------------------------------------------- -function str=time2date(t) -%-------------------------------------------------------------------------- -t=t-1580970496; -if t<0 - t=t+4294967296; -end -t=t+9561652096; -str=datestr(t/(24*60*60)+datenum(1601,1,1)); -return -end -%-------------------------------------------------------------------------- \ No newline at end of file diff --git a/@HEKA_Importer/HI_extractHEKADataTree.m b/@HEKA_Importer/HI_extractHEKADataTree.m index b049132..a28bc43 100644 --- a/@HEKA_Importer/HI_extractHEKADataTree.m +++ b/@HEKA_Importer/HI_extractHEKADataTree.m @@ -7,9 +7,13 @@ function HI_extractHEKADataTree(obj) % % See also HEKA_Importer % HEKA_Importer.HI_loadHEKAFile -% HEKA_Importer.HI_ImportHEKAtoMat % HEKA_Importer.HI_extractHEKASolutionTree % HEKA_Importer.HI_extractHEKAStimTree +% HEKA_Importer.HI_extractHEKADataTree +% HEKA_Importer.HI_readPulseFileHEKA +% HEKA_Importer.HI_readStimulusFileHEKA +% HEKA_Importer.HI_readAmplifierFileHEKA +% HEKA_Importer.HI_readSolutionFileHEKA %1: Root %2: Group/Experiment @@ -18,14 +22,11 @@ function HI_extractHEKADataTree(obj) %5: Trace/Channel %check if datetime functions exist - if ~isempty(which('datetime')) && ~isempty(which('NaT')) hasDateTime = true; else hasDateTime = false; end - - dataTree = obj.trees.dataTree; @@ -58,7 +59,7 @@ function HI_extractHEKADataTree(obj) recIDs = find(~cellfun(@isempty,dataTree(:,3))); recIDs = recIDs(recIDs>thisExpID & recIDsint32'); +obj.opt.fileData.Position=ftell(obj.opt.fileData.fh); + +end + +%-------------------------------------------------------------------------- +function rec=getOneAmplifierRecord(obj,Level) +%-------------------------------------------------------------------------- +% Gets one record +obj.opt.fileData.Counter = obj.opt.fileData.Counter+1; +switch Level + case 0 + rec=getAmplifierRootRecord(obj); + case 1 + rec=getAmplifierSeriesRecord(obj); + case 2 + rec=getAmplifierStateRecord(obj); + otherwise + error('Unexpected Level'); +end + +end + +%-------------------------------------------------------------------------- +function p=getAmplifierRootRecord(obj) +%-------------------------------------------------------------------------- +fh = obj.opt.fileData.fh; + +p.RoVersion = fread(fh, 1, 'int32=>int32');% = 0; (* INT32 *) +p.RoMark = fread(fh, 1, 'int32=>int32');% = 4; (* INT32 *) +p.RoVersionName = deblank(fread(fh, 32, 'uint8=>char')');% = 8; (* String32Type *) +p.RoAmplifierName = deblank(fread(fh, 32, 'uint8=>char')');% = 40; (* String32Type *) +p.RoAmplifier = fread(fh,1,'uint8=>uint8');% = 72; (* CHAR *) +p.RoADBoard = fread(fh,1,'uint8=>uint8');% = 73; (* CHAR *) +p.RoCreator = fread(fh,1,'uint8=>uint8');% = 74; (* CHAR *) + p.RoFiller1 = fread(fh, 1, 'uint8=>uint8');% = 75; (* BYTE *) +p.RoCRC = fread(fh, 1, 'int32=>int32');% = 76; (* CARD32 *) +p.RootRecSize = 80;% (* = 10 * 8 *) + +p=orderfields(p); + +end + +%-------------------------------------------------------------------------- +function s=getAmplifierSeriesRecord(obj) +%-------------------------------------------------------------------------- +fh = obj.opt.fileData.fh; + +s.SeMark = fread(fh, 1, 'int32=>int32');% = 0; (* INT32 *) +s.SeSeriesCount = fread(fh, 1, 'int32=>int32');% = 4; (* INT32 *) +s.SeFiller1 = fread(fh, 1, 'int32=>int32');% = 8; (* INT32 *) +s.SeCRC = fread(fh, 1, 'int32=>int32');% = 12; (* CARD32 *) +s.SeriesRecSize = 16;% (* = 2 * 8 *) + +s=orderfields(s); + +end + +%-------------------------------------------------------------------------- +function a=getAmplifierStateRecord(obj) +%-------------------------------------------------------------------------- +fh = obj.opt.fileData.fh; + +a.AmMark = fread(fh, 1, 'int32=>int32');% = 0; (* INT32 *) +a.AmStateCount = fread(fh, 1, 'int32=>int32');% = 4; (* INT32 *) +a.AmStateVersion = fread(fh,1,'uint8=>uint8');% = 8; (* CHAR *) + a.AmFiller1 = fread(fh, 1, 'uint8=>uint8');% = 9; (* BYTE *) + a.AmFiller2 = fread(fh, 1, 'uint8=>uint8');% = 10; (* BYTE *) + a.AmFiller3 = fread(fh, 1, 'uint8=>uint8');% = 11; (* BYTE *) + a.AmFiller4 = fread(fh, 1, 'int32=>int32');% = 12; (* INT32 *) +a.AmLockInParams = getSeLockInParams(fh);% = 16; (* LockInParamsSize = 96 *) +a.AmAmplifierState = getAmplifierState(fh);% = 112; (* AmplifierStateSize = 400 *) +a.AmIntSol = fread(fh, 1, 'int32=>int32');% = 512; (* INT32 *) +a.AmExtSol = fread(fh, 1, 'int32=>int32');% = 516; (* INT32 *) + a.AmFiller5 = fread(fh, 36, 'uint8=>uint8');% = 520; (* spares: 36 bytes *) +a.AmCRC = fread(fh, 1, 'int32=>int32');% = 556; (* CARD32 *) +a.StateRecSize = 560;% (* = 70 * 8 *) + +a = orderfields(a); + +end + +function L=getSeLockInParams(fh) +%-------------------------------------------------------------------------- +offset=ftell(fh); +L.loExtCalPhase = fread(fh, 1, 'double=>double');% = 0; (* LONGREAL *) +L.loExtCalAtten = fread(fh, 1, 'double=>double');% = 8; (* LONGREAL *) +L.loPLPhase = fread(fh, 1, 'double=>double');% = 16; (* LONGREAL *) +L.loPLPhaseY1 = fread(fh, 1, 'double=>double');% = 24; (* LONGREAL *) +L.loPLPhaseY2 = fread(fh, 1, 'double=>double');% = 32; (* LONGREAL *) +L.loUsedPhaseShift = fread(fh, 1, 'double=>double');% = 40; (* LONGREAL *) +L.loUsedAttenuation = fread(fh, 1, 'double=>double');% = 48; (* LONGREAL *) + L.loSpare = fread(fh, 1, 'double=>double');% = 56; (* LONGREAL *) +L.loExtCalValid = fread(fh, 1, 'uint8=>logical');% = 64; (* BOOLEAN *) +L.loPLPhaseValid = fread(fh, 1, 'uint8=>logical');% = 65; (* BOOLEAN *) +L.loLockInMode = fread(fh, 1, 'uint8=>uint8');% = 66; (* BYTE *) +L.loCalMode = fread(fh, 1, 'uint8=>uint8');% = 67; (* BYTE *) + L.loSpare2 = fread(fh, 7, 'int32=>in32');% = 68; (* remaining *) +L.LockInParamsSize = 96; + +fseek(fh, offset+L.LockInParamsSize, 'bof'); + +end + +%-------------------------------------------------------------------------- +function A=getAmplifierState(fh) +%-------------------------------------------------------------------------- +offset=ftell(fh); +A.sStateVersion = fread(fh, 1, 'double=>double');% = 0; (* 8 = SizeStateVersion *) +A.sCurrentGain = fread(fh, 1, 'double=>double');% = 8; (* LONGREAL *) +A.sF2Bandwidth = fread(fh, 1, 'double=>double');% = 16; (* LONGREAL *) +A.sF2Frequency = fread(fh, 1, 'double=>double');% = 24; (* LONGREAL *) +A.sRsValue = fread(fh, 1, 'double=>double');% = 32; (* LONGREAL *) +A.sRsFraction = fread(fh, 1, 'double=>double');% = 40; (* LONGREAL *) +A.sGLeak = fread(fh, 1, 'double=>double');% = 48; (* LONGREAL *) +A.sCFastAmp1 = fread(fh, 1, 'double=>double');% = 56; (* LONGREAL *) +A.sCFastAmp2 = fread(fh, 1, 'double=>double');% = 64; (* LONGREAL *) +A.sCFastTau = fread(fh, 1, 'double=>double');% = 72; (* LONGREAL *) +A.sCSlow = fread(fh, 1, 'double=>double');% = 80; (* LONGREAL *) +A.sGSeries = fread(fh, 1, 'double=>double');% = 88; (* LONGREAL *) +A.sVCStimDacScale = fread(fh, 1, 'double=>double');% = 96; (* LONGREAL *) +A.sCCStimScale = fread(fh, 1, 'double=>double');% = 104; (* LONGREAL *) +A.sVHold = fread(fh, 1, 'double=>double');% = 112; (* LONGREAL *) +A.sLastVHold = fread(fh, 1, 'double=>double');% = 120; (* LONGREAL *) +A.sVpOffset = fread(fh, 1, 'double=>double');% = 128; (* LONGREAL *) +A.sVLiquidJunction = fread(fh, 1, 'double=>double');% = 136; (* LONGREAL *) +A.sCCIHold = fread(fh, 1, 'double=>double');% = 144; (* LONGREAL *) +A.sCSlowStimVolts = fread(fh, 1, 'double=>double');% = 152; (* LONGREAL *) +A.sCCTrackVHold = fread(fh, 1, 'double=>double');% = 160; (* LONGREAL *) +A.sTimeoutCSlow = fread(fh, 1, 'double=>double');% = 168; (* LONGREAL *) +A.sSearchDelay = fread(fh, 1, 'double=>double');% = 176; (* LONGREAL *) +A.sMConductance = fread(fh, 1, 'double=>double');% = 184; (* LONGREAL *) +A.sMCapacitance = fread(fh, 1, 'double=>double');% = 192; (* LONGREAL *) +A.sSerialNumber = fread(fh, 1, 'double=>double');% = 200; (* 8 = SizeSerialNumber *) + +A.sE9Boards = fread(fh, 1, 'int16=>int16');% = 208; (* INT16 *) +A.sCSlowCycles = fread(fh, 1, 'int16=>int16');% = 210; (* INT16 *) +A.sIMonAdc = fread(fh, 1, 'int16=>int16');% = 212; (* INT16 *) +A.sVMonAdc = fread(fh, 1, 'int16=>int16');% = 214; (* INT16 *) + +A.sMuxAdc = fread(fh, 1, 'int16=>int16');% = 216; (* INT16 *) +A.sTestDac = fread(fh, 1, 'int16=>int16');% = 218; (* INT16 *) +A.sStimDac = fread(fh, 1, 'int16=>int16');% = 220; (* INT16 *) +A.sStimDacOffset = fread(fh, 1, 'int16=>int16');% = 222; (* INT16 *) + +A.sMaxDigitalBit = fread(fh, 1, 'int16=>int16');% = 224; (* INT16 *) +A.sHasCFastHigh = fread(fh, 1, 'uint8=>uint8');% = 226; (* BYTE *) +A.sCFastHigh = fread(fh, 1, 'uint8=>uint8');% = 227; (* BYTE *) +A.sHasBathSense = fread(fh, 1, 'uint8=>uint8');% = 228; (* BYTE *) +A.sBathSense = fread(fh, 1, 'uint8=>uint8');% = 229; (* BYTE *) +A.sHasF2Bypass = fread(fh, 1, 'uint8=>uint8');% = 230; (* BYTE *) +A.sF2Mode = fread(fh, 1, 'uint8=>uint8');% = 231; (* BYTE *) + +A.sAmplKind = fread(fh, 1, 'uint8=>uint8');% = 232; (* BYTE *) +A.sIsEpc9N = fread(fh, 1, 'uint8=>uint8');% = 233; (* BYTE *) +A.sADBoard = fread(fh, 1, 'uint8=>uint8');% = 234; (* BYTE *) +A.sBoardVersion = fread(fh, 1, 'uint8=>uint8');% = 235; (* BYTE *) +A.sActiveE9Board = fread(fh, 1, 'uint8=>uint8');% = 236; (* BYTE *) +A.sMode = fread(fh, 1, 'uint8=>uint8');% = 237; (* BYTE *) +A.sRange = fread(fh, 1, 'uint8=>uint8');% = 238; (* BYTE *) +A.sF2Response = fread(fh, 1, 'uint8=>uint8');% = 239; (* BYTE *) + +A.sRsOn = fread(fh, 1, 'uint8=>uint8');% = 240; (* BYTE *) +A.sCSlowRange = fread(fh, 1, 'uint8=>uint8');% = 241; (* BYTE *) +A.sCCRange = fread(fh, 1, 'uint8=>uint8');% = 242; (* BYTE *) +A.sCCGain = fread(fh, 1, 'uint8=>uint8');% = 243; (* BYTE *) +A.sCSlowToTestDac = fread(fh, 1, 'uint8=>uint8');% = 244; (* BYTE *) +A.sStimPath = fread(fh, 1, 'uint8=>uint8');% = 245; (* BYTE *) +A.sCCTrackTau = fread(fh, 1, 'uint8=>uint8');% = 246; (* BYTE *) +A.sWasClipping = fread(fh, 1, 'uint8=>uint8');% = 247; (* BYTE *) + +A.sRepetitiveCSlow = fread(fh, 1, 'uint8=>uint8');% = 248; (* BYTE *) +A.sLastCSlowRange = fread(fh, 1, 'uint8=>uint8');% = 249; (* BYTE *) + A.sOld1 = fread(fh, 1, 'uint8=>uint8');% = 250; (* BYTE *) +A.sCanCCFast = fread(fh, 1, 'uint8=>uint8');% = 251; (* BYTE *) +A.sCanLowCCRange = fread(fh, 1, 'uint8=>uint8');% = 252; (* BYTE *) +A.sCanHighCCRange = fread(fh, 1, 'uint8=>uint8');% = 253; (* BYTE *) +A.sCanCCTrackingg = fread(fh, 1, 'uint8=>uint8');% = 254; (* BYTE *) +A.sCHasVmonPath = fread(fh, 1, 'uint8=>uint8');% = 255; (* BYTE *) + +A.sHasNewCCMode = fread(fh, 1, 'uint8=>uint8');% = 256; (* BYTE *) +A.sSelector = fread(fh, 1, 'uint8=>char');% = 257; (* CHAR *) +A.sHoldInverted = fread(fh, 1, 'uint8=>uint8');% = 258; (* BYTE *) +A.sAutoCFast = fread(fh, 1, 'uint8=>uint8');% = 259; (* BYTE *) +A.sAutoCSlow = fread(fh, 1, 'uint8=>uint8');% = 260; (* BYTE *) +A.sHasVmonX100 = fread(fh, 1, 'uint8=>uint8');% = 261; (* BYTE *) +A.sTestDacOn = fread(fh, 1, 'uint8=>uint8');% = 262; (* BYTE *) +A.sQMuxAdcOn = fread(fh, 1, 'uint8=>uint8');% = 263; (* BYTE *) + +A.sImon1Bandwidth = fread(fh, 1, 'double=>double');% = 264; (* LONGREAL *) +A.sStimScale = fread(fh, 1, 'double=>double');% = 272; (* LONGREAL *) + +A.sGain = fread(fh, 1, 'uint8=>uint8');% = 280; (* BYTE *) +A.sFilter1 = fread(fh, 1, 'uint8=>uint8');% = 281; (* BYTE *) +A.sStimFilterOn = fread(fh, 1, 'uint8=>uint8');% = 282; (* BYTE *) +A.sRsSlow = fread(fh, 1, 'uint8=>uint8');% = 283; (* BYTE *) + A.sOld2 = fread(fh, 1, 'uint8=>uint8');% = 284; (* BYTE *) +A.sCCCFastOn = fread(fh, 1, 'uint8=>uint8');% = 285; (* BYTE *) +A.sCCFastSpeed = fread(fh, 1, 'uint8=>uint8');% = 286; (* BYTE *) +A.sF2Source = fread(fh, 1, 'uint8=>uint8');% = 287; (* BYTE *) + +A.sTestRange = fread(fh, 1, 'uint8=>uint8');% = 288; (* BYTE *) +A.sTestDacPath = fread(fh, 1, 'uint8=>uint8');% = 289; (* BYTE *) +A.sMuxChannel = fread(fh, 1, 'uint8=>uint8');% = 290; (* BYTE *) +A.sMuxGain64 = fread(fh, 1, 'uint8=>uint8');% = 291; (* BYTE *) +A.sVmonX100 = fread(fh, 1, 'uint8=>uint8');% = 292; (* BYTE *) +A.sIsQuadro = fread(fh, 1, 'uint8=>uint8');% = 293; (* BYTE *) +A.sF1Mode = fread(fh, 1, 'uint8=>uint8');% = 294; (* BYTE *) + A.sOld3 = fread(fh, 1, 'uint8=>uint8');% = 295; (* BYTE *) + +A.sStimFilterHz = fread(fh, 1, 'double=>double');% = 296; (* LONGREAL *) +A.sRsTau = fread(fh, 1, 'double=>double');% = 304; (* LONGREAL *) +A.sDacToAdcDelay = fread(fh, 1, 'double=>double');% = 312; (* LONGREAL *) +A.sInputFilterTau = fread(fh, 1, 'double=>double');% = 320; (* LONGREAL *) +A.sOutputFilterTau = fread(fh, 1, 'double=>double');% = 328; (* LONGREAL *) +A.sVmonFactor = fread(fh, 1, 'double=>double');% = 336; (* LONGREAL *) +A.sCalibDate = fread(fh, 2, 'double=>double');% = 344; (* 16 = SizeCalibDate *) +A.sVmonOffset = fread(fh, 1, 'double=>double');% = 360; (* LONGREAL *) + +A.sEEPROMKind = fread(fh, 1, 'uint8=>uint8');% = 368; (* BYTE *) +A.sVrefX2 = fread(fh, 1, 'uint8=>uint8');% = 369; (* BYTE *) +A.sHasVrefX2AndF2Vmon = fread(fh, 1, 'uint8=>uint8');% = 370; (* BYTE *) +A.sSpare1 = fread(fh, 1, 'uint8=>uint8');% = 371; (* BYTE *) +A.sSpare2 = fread(fh, 1, 'uint8=>uint8');% = 372; (* BYTE *) +A.sSpare3 = fread(fh, 1, 'uint8=>uint8');% = 373; (* BYTE *) +A.sSpare4 = fread(fh, 1, 'uint8=>uint8');% = 374; (* BYTE *) +A.sSpare5 = fread(fh, 1, 'uint8=>uint8');% = 375; (* BYTE *) + +A.sCCStimDacScale = fread(fh, 1, 'double=>double');% = 376; (* LONGREAL *) +A.sVmonFiltBandwidth = fread(fh, 1, 'double=>double');% = 384; (* LONGREAL *) +A.sVmonFiltFrequency = fread(fh, 1, 'double=>double');% = 392; (* LONGREAL *) +A.AmplifierStateSize = 400;% (* = 50 * 8 *) + +fseek(fh, offset+A.AmplifierStateSize, 'bof'); + +end diff --git a/@HEKA_Importer/HI_readPulseFileHEKA.m b/@HEKA_Importer/HI_readPulseFileHEKA.m new file mode 100644 index 0000000..51b49b6 --- /dev/null +++ b/@HEKA_Importer/HI_readPulseFileHEKA.m @@ -0,0 +1,459 @@ +function HI_readPulseFileHEKA(obj,Level) + +% extracts data stored in the "*.pul" file, or the corresponding portion of +% the bundled ".dat" file +% +% See also HEKA_Importer +% HEKA_Importer.HI_loadHEKAFile +% HEKA_Importer.HI_extractHEKASolutionTree +% HEKA_Importer.HI_extractHEKAStimTree +% HEKA_Importer.HI_extractHEKADataTree +% HEKA_Importer.HI_readPulseFileHEKA +% HEKA_Importer.HI_readStimulusFileHEKA +% HEKA_Importer.HI_readAmplifierFileHEKA +% HEKA_Importer.HI_readSolutionFileHEKA + +%-------------------------------------------------------------------------- +% Gets one record of the tree and the number of children +s = getOneRecord(obj,Level); +obj.opt.fileData.Tree{obj.opt.fileData.Counter, Level+1} = s; + +obj.opt.fileData.Position = obj.opt.fileData.Position+obj.opt.fileData.Sizes(Level+1); +fseek(obj.opt.fileData.fh, obj.opt.fileData.Position, 'bof'); +obj.opt.fileData.nchild=fread(obj.opt.fileData.fh, 1, 'int32=>int32'); +if obj.opt.fileData.nchild >10 + +end +obj.opt.fileData.Position=ftell(obj.opt.fileData.fh); + +end + +%-------------------------------------------------------------------------- +function rec=getOneRecord(obj,Level) +%-------------------------------------------------------------------------- +% Gets one record +obj.opt.fileData.Counter = obj.opt.fileData.Counter+1; + +switch Level + case 0 + rec=getRoot(obj); + case 1 + rec=getGroup(obj); + case 2 + rec=getSeries(obj); + case 3 + rec=getSweep(obj); + case 4 + rec=getTrace(obj); + otherwise + error('Unexpected Level'); +end +end + +% The functions below return data as defined by the HEKA PatchMaster +% specification found at ftp://server.hekahome.de/pub/FileFormat/ + +%-------------------------------------------------------------------------- +function p=getRoot(obj) +%-------------------------------------------------------------------------- +fh = obj.opt.fileData.fh; + +p.RoVersion = fread(fh, 1, 'int32=>int32');% = 4; (* INT32 *) +p.RoMark = fread(fh, 1, 'int32=>int32');% = 4; (* INT32 *) +p.RoVersionName = deblank(fread(fh, 32, 'uint8=>char')');% = 8; (* String32Type *) +p.RoAuxFileName = deblank(fread(fh, 80, 'uint8=>char')');% = 40; (* String80Type *) +p.RoRootText = deblank(fread(fh, 400, 'uint8=>char')');% (* String400Type *) +p.RoStartTime = fread(fh, 1, 'double=>double') ;% = 520; (* LONGREAL *) +p.RoStartTimeMATLAB = obj.HI_time2date(p.RoStartTime); +p.RoMaxSamples = fread(fh, 1, 'int32=>int32'); % = 528; (* INT32 *) +p.RoCRC = fread(fh, 1, 'int32=>int32'); % = 532; (* CARD32 *) +p.RoFeatures = fread(fh, 1, 'int16=>int16'); % = 536; (* SET16 *) +p.RoFiller1 = fread(fh, 1, 'int16=>int16');% = 538; (* INT16 *) +p.RoFiller2 = fread(fh, 1, 'int32=>int32');% = 540; (* INT32 *) +p.RoTcEnumerator = fread(fh,32,'int16=>int16');% = 544; (* ARRAY[0..Max_TcKind_M1] OF INT16 *) +p.RoTcKind = fread(fh,32,'int8=>int8');% = 608; (* ARRAY[0..Max_TcKind_M1] OF INT8 *) +p.RootRecSize = 640;% (* = 80 * 8 *); +p=orderfields(p); + +obj.opt.fileData.fileVersion = p.RoVersion; +end + +%-------------------------------------------------------------------------- +function g=getGroup(obj) +%-------------------------------------------------------------------------- +% Group +fh = obj.opt.fileData.fh; + +g.GrMark = fread(fh, 1, 'int32=>int32');% = 0; (* INT32 *) +g.GrLabel = deblank(fread(fh, 32, 'uint8=>char')');% = 4; (* String32Size *) +g.GrText = deblank(fread(fh, 80, 'uint8=>char')');% = 36; (* String80Size *) +g.GrExperimentNumber = fread(fh, 1, 'int32=>int32');% = 116; (* INT32 *) +g.GrGroupCount = fread(fh, 1, 'int32=>int32');% = 120; (* INT32 *) +g.GrCRC = fread(fh, 1, 'int32=>int32');% = 124; (* CARD32 *) +g.GrMatrixWidth = fread(fh,1,'double=>double');% = 128; (* LONGREAL *) +g.GrMatrixHeight = fread(fh,1,'double=>double');% = 136; (* LONGREAL *) +g.GroupRecSize = 144; % (* = 18 * 8 *) + +g=orderfields(g); + +end + +%-------------------------------------------------------------------------- +function s=getSeries(obj) +%-------------------------------------------------------------------------- +fh = obj.opt.fileData.fh; + +s.SeMark = fread(fh, 1, 'int32=>int32');% = 0; (* INT32 *) +s.SeLabel = deblank(fread(fh, 32, 'uint8=>char')');% = 4; (* String32Type *) +s.SeComment = deblank(fread(fh, 80, 'uint8=>char')');% = 36; (* String80Type *) +s.SeSeriesCount = fread(fh, 1, 'int32=>int32');% = 116; (* INT32 *) +s.SeNumbersw = fread(fh, 1, 'int32=>int32');% = 120; (* INT32 *) +switch obj.opt.fileData.fileVersion + case 9 + s.SeAmplStateOffset = fread(fh, 1, 'int32=>int32');% = 124; (* INT32 * + s.SeAmplStateSeries = fread(fh, 1, 'int32=>int32');% = 128; (* INT32 * + case 1000 + s.SeAmplStateFlag = fread(fh,1,'int32=>int32');% = 124; (* INT32 *) // flag > 0 => load local oldAmpState, otherwise load from .amp File. + s.SeAmplStateRef = fread(fh,1,'int32=>int32'); % = 128; (* INT32 *) // ref = 0 => use local oldAmpState +end +s.SeMethodTag = fread(fh,1,'int32=>int32'); % = 132; (* INT32 *) +s.SeTime = fread(fh,1,'double=>double'); % = 136; (* LONGREAL *) +s.SeTimeMATLAB = obj.HI_time2date(s.SeTime); +s.SePageWidth = fread(fh, 1, 'double=>double') ;% = 144; (* LONGREAL *) +switch obj.opt.fileData.fileVersion + case 9 + for k=1:4 % = 152; (* ARRAY[0..1] OF UserParamDescrType = 4*40 *) + s.SeSwUserParamDescr(k).Name=deblank(fread(fh, 32, 'uint8=>char')');% + s.SeSwUserParamDescr(k).Unit=deblank(fread(fh, 8, 'uint8=>char')');% + end + case 1000 + for k=1:2 % = 152; (* ARRAY[0..1] OF UserParamDescrType = 4*40 *) + s.SeUserDescr1(k).Name=deblank(fread(fh, 32, 'uint8=>char')');% + s.SeUserDescr1(k).Unit=deblank(fread(fh, 8, 'uint8=>char')');% + end + s.SeFiller1 = deblank(fread(fh,80,'uint8=>char')'); % = 232; (* ARRAY[0..1] OF UserParamDescrType = 2*40 *) +end +s.SeMethodName = deblank(fread(fh,32,'uint8=>char')');% = 312; (* String32Type *) +switch obj.opt.fileData.fileVersion + case 9 + s.SeSeUserParams1 = fread(fh ,4 ,'double=>double');% = 344; (* ARRAY[0..3] OF LONGREAL *) + s.SeLockInParams = getSeLockInParams(fh);% = 376; (* SeLockInSize = 96, see "Pulsed.de" *) + s.SeAmplifierState = getAmplifierState(fh);% = 472; (* AmplifierStateSize = 400 *) + case 1000 + s.SePhotoParams1 = fread(fh, 4, 'double=>double'); % = 344; (* ARRAY[0..3] OF LONGREAL = 4*8 *) + s.SeOldLockInParams = getSeLockInParams(fh);% = 376; (* SeOldLockInSize = 96, see "Pulsed.de" *) + s.SeOldAmpState = getAmplifierState(fh);% = 472; (* SeOldAmpState = 400 -> the AmplStateRecord is now stored in the .amp file *) +end +s.SeUsername = deblank(fread(fh, 80, 'uint8=>char')');% = 872; (* String80Type *) +switch obj.opt.fileData.fileVersion + case 9 + for k=1:4% = 952; (* ARRAY[0..3] OF UserParamDescrType = 4*40 *) + s.SeSeUserParamDescr1(k).Name=deblank(fread(fh, 32, 'uint8=>char')');% + s.SeSeUserParamDescr1(k).Unit=deblank(fread(fh, 8, 'uint8=>char')');% + end + case 1000 + for k=1:4% = 952; (* ARRAY[0..3] OF UserParamDescrType = 4*40 *) + s.SePhotoParams2(k).Name=deblank(fread(fh, 32, 'uint8=>char')');% + s.SePhotoParams2(k).Unit=deblank(fread(fh, 8, 'uint8=>char')');% + end +end +s.SeFiller1 = fread(fh, 1, 'int32=>int32');% = 1112; (* INT32 *) +s.SeCRC = fread(fh, 1, 'int32=>int32');% = 1116; (* CARD32 *) +s.SeSeUserParams2 = fread(fh, 4, 'double=>double');% = 1120; (* ARRAY[0..3] OF LONGREAL *) +for k=1:4 % = 1152; (* ARRAY[0..3] OF UserParamDescrType = 4*40 *) + s.SeSeUserParamDescr2(k).Name=deblank(fread(fh, 32, 'uint8=>char')');% + s.SeSeUserParamDescr2(k).Unit=deblank(fread(fh, 8, 'uint8=>char')');% +end +s.SeScanParams = fread(fh, 96, 'uint8=>uint8');% = 1312; (* ScanParamsSize = 96 (ElProScan Extension) *) +switch obj.opt.fileData.fileVersion + case 9 + s.SeriesRecSize = 1408;% = 1408; (* = 176 * 8 *) + case 1000 + for k=1:8 % = 1408; (* ARRAY[0..7] OF UserParamDescrType = 8*40 *) + s.SeSeUserDescr2(k).Name=deblank(fread(fh, 32, 'uint8=>char')');% + s.SeSeUserDescr2(k).Unit=deblank(fread(fh, 8, 'uint8=>char')'); + end + s.SeriesRecSize = 1728;% = 1728; +end + +s=orderfields(s); +s.Sweeps = []; % used to store all the sweeps within the recording structure later on + +end + +%-------------------------------------------------------------------------- +function sw=getSweep(obj) +%-------------------------------------------------------------------------- + +fh = obj.opt.fileData.fh; + +sw.SwMark = fread(fh, 1, 'int32=>int32');% = 0; (* INT32 *) +sw.SwLabel = deblank(fread(fh, 32, 'uint8=>char')');% = 4; (* String32Type *) +sw.SwAuxDataFileOffset = fread(fh, 1, 'int32=>int32');% = 36; (* INT32 *) +sw.SwStimCount = fread(fh, 1, 'int32=>int32');% = 40; (* INT32 *) +sw.SwSweepCount = fread(fh, 1, 'int32=>int32');% = 44; (* INT32 *) +sw.SwTime = fread(fh, 1, 'double=>double');% = 48; (* LONGREAL *) +sw.SwTimeMATLAB = obj.HI_time2date(sw.SwTime);% Also add in MATLAB datenum format +sw.SwTimer = fread(fh, 1, 'double=>double');% = 56; (* LONGREAL *) +switch obj.opt.fileData.fileVersion + case 9 + sw.SwSwUserParams = fread(fh, 4, 'double=>double');% = 64; (* ARRAY[0..3] OF LONGREAL *) + case 1000 + sw.SwSwUserParams = fread(fh, 2, 'double=>double');% = 64; (* ARRAY[0..1] OF LONGREAL *) + sw.SwPipPressure = fread(fh, 1, 'double=>double');% = 80; (* LONGREAL * + sw.SwRMSNoise = fread(fh,1,'double=>double'); % = 88; (* LONGREAL *) +end +sw.SwTemperature = fread(fh, 1, 'double=>double');% = 96; (* LONGREAL *) +sw.SwOldIntSol = fread(fh, 1, 'int32=>int32');% = 104; (* INT32 *) +sw.SwOldExtSol = fread(fh, 1, 'int32=>int32');% = 108; (* INT32 *) +sw.SwDigitalIn = fread(fh, 1, 'int16=>int16');% = 112; (* SET16 *) +sw.SwSweepKind = fread(fh, 1, 'int16=>int16');% = 114; (* SET16 *) +sw.SwDigitalOut = fread(fh,1, 'int16=>int16');% = 116; (* SET16 *) +sw.SwFiller1 = fread(fh, 1, 'int16=>int16');% = 118; (* INT32 *) +sw.SwMarkers = fread(fh, 4, 'double=>double');% = 120; (* ARRAY[0..3] OF LONGREAL, see SwMarkersNo *) +sw.SwFiller2 = fread(fh, 1, 'int32=>int32');% = 152; (* INT32 *) +sw.SwCRC = fread(fh, 1, 'int32=>int32');% = 156; (* CARD32 *) +sw.SwSwHolding = fread(fh,16,'double=>double');% = 160; (* ARRAY[0..15] OF LONGREAL, see SwHoldingNo *) +switch obj.opt.fileData.fileVersion + case 9 + sw.SweepRecSize = 288;% = 288; (* = 36 * 8 *) + case 1000 + sw.SwSwUserParamEx = fread(fh,8,'double=>double'); % = 288; (* ARRAY[0..7] OF LONGREAL *) + sw.SweepRecSize = 352;% = 352; +end +sw=orderfields(sw); +sw.Traces = []; % used to store all the traces/channels within the sweep structure later on +end + +%-------------------------------------------------------------------------- +function tr=getTrace(obj) +%-------------------------------------------------------------------------- +fh = obj.opt.fileData.fh; + +tr.TrMark = fread(fh, 1, 'int32=>int32');% = 0; (* INT32 *) +tr.TrLabel = deblank(fread(fh, 32, 'uint8=>char')');% = 4; (* String32Type *) +tr.TrTraceCount = fread(fh, 1, 'int32=>int32');% = 36; (* INT32 *) +tr.TrData = fread(fh, 1, 'int32=>int32');% = 40; (* INT32 *) +tr.TrDataPoints = fread(fh, 1, 'int32=>int32');% = 44; (* INT32 *) +tr.TrInternalSolution = fread(fh, 1, 'int32=>int32');% = 48; (* INT32 *) +tr.TrAverageCount = fread(fh, 1, 'int32=>int32');% = 52; (* INT32 *) +tr.TrLeakCount = fread(fh, 1, 'int32=>int32');% = 56; (* INT32 *) +tr.TrLeakTraces = fread(fh, 1, 'int32=>int32');% = 60; (* INT32 *) +tr.TrDataKind = fread(fh, 1, 'uint16=>uint16');% = 64; (* SET16 *) NB Stored unsigned +tr.TrFiller1 = fread(fh, 1, 'int16=>int16');% = 66; (* SET16 *) +tr.TrRecordingMode = fread(fh, 1, 'uint8=>uint8');% = 68; (* BYTE *) +tr.TrAmplIndex = fread(fh, 1, 'uint8=>uint8');% = 69; (* CHAR *) +tr.TrDataFormat = fread(fh, 1, 'uint8=>uint8');% = 70; (* BYTE *) +tr.TrDataAbscissa = fread(fh, 1, 'uint8=>uint8');% = 71; (* BYTE *) +tr.TrDataScaler = fread(fh, 1, 'double=>double');% = 72; (* LONGREAL *) +tr.TrTimeOffset = fread(fh, 1, 'double=>double');% = 80; (* LONGREAL *) +tr.TrZeroData = fread(fh, 1, 'double=>double');% = 88; (* LONGREAL *) +tr.TrYUnit = deblank(fread(fh, 8, 'uint8=>char')');% = 96; (* String8Type *) +tr.TrXInterval = fread(fh, 1, 'double=>double');% = 104; (* LONGREAL *) +tr.TrXStart = fread(fh, 1, 'double=>double');% = 112; (* LONGREAL *) +% 17.04.10 TrXUnit bytes may include some trailing characters after NULL +% byte +tr.TrXUnit = deblank(fread(fh, 8, 'uint8=>char')');% = 120; (* String8Type *) +tr.TrYRange = fread(fh, 1, 'double=>double');% = 128; (* LONGREAL *) +tr.TrYOffset = fread(fh, 1, 'double=>double');% = 136; (* LONGREAL *) +tr.TrBandwidth = fread(fh, 1, 'double=>double');% = 144; (* LONGREAL *) +tr.TrPipetteResistance = fread(fh, 1, 'double=>double');% = 152; (* LONGREAL *) +tr.TrCellPotential = fread(fh, 1, 'double=>double');% = 160; (* LONGREAL *) +tr.TrSealResistance = fread(fh, 1, 'double=>double');% = 168; (* LONGREAL *) +tr.TrCSlow = fread(fh, 1, 'double=>double');% = 176; (* LONGREAL *) +tr.TrGSeries = fread(fh, 1, 'double=>double');% = 184; (* LONGREAL *) +tr.TrRsValue = fread(fh, 1, 'double=>double');% = 192; (* LONGREAL *) +tr.TrGLeak = fread(fh, 1, 'double=>double');% = 200; (* LONGREAL *) +tr.TrMConductance = fread(fh, 1, 'double=>double');% = 208; (* LONGREAL *) +tr.TrLinkDAChannel = fread(fh, 1, 'int32=>int32');% = 216; (* INT32 *) +tr.TrValidYrange = fread(fh, 1, 'uint8=>logical');% = 220; (* BOOLEAN *) +tr.TrAdcMode = fread(fh, 1, 'uint8=>uint8');% = 221; (* CHAR *) +tr.TrAdcChannel = fread(fh, 1, 'int16=>int16');% = 222; (* INT16 *) +tr.TrYmin = fread(fh, 1, 'double=>double');% = 224; (* LONGREAL *) +tr.TrYmax = fread(fh, 1, 'double=>double');% = 232; (* LONGREAL *) +tr.TrSourceChannel = fread(fh, 1, 'int32=>int32');% = 240; (* INT32 *) +tr.TrExternalSolution = fread(fh, 1, 'int32=>int32');% = 244; (* INT32 *) +tr.TrCM = fread(fh, 1, 'double=>double');% = 248; (* LONGREAL *) +tr.TrGM = fread(fh, 1, 'double=>double');% = 256; (* LONGREAL *) +tr.TrPhase = fread(fh, 1, 'double=>double');% = 264; (* LONGREAL *) +tr.TrDataCRC = fread(fh, 1, 'int32=>int32');% = 272; (* CARD32 *) +tr.TrCRC = fread(fh, 1, 'int32=>int32');% = 276; (* CARD32 *) +tr.TrGS = fread(fh, 1, 'double=>double');% = 280; (* LONGREAL *) +tr.TrSelfChannel = fread(fh, 1, 'int32=>int32');% = 288; (* INT32 *) + +tr.TrInterleaveSize = fread(fh, 1, 'int32=>int32');% = 292; (* INT32 *) +tr.TrInterleaveSkip = fread(fh, 1, 'int32=>int32');% = 296; (* INT32 *) +tr.TrImageIndex = fread(fh, 1, 'int32=>int32');% = 300; (* INT32 *) +tr.TrMarkers = fread(fh, 10, 'double=>double');% = 304; (* ARRAY[0..9] OF LONGREAL *) +tr.TrSECM_X = fread(fh, 1, 'double=>double');% = 384; (* LONGREAL *) +tr.TrSECM_Y = fread(fh, 1, 'double=>double');% = 392; (* LONGREAL *) +tr.TrSECM_Z = fread(fh, 1, 'double=>double');% = 400; (* LONGREAL *) +tr.TrTrHolding = fread(fh, 1, 'double=>double');% = 408; (* LONGREAL *) +tr.TrTcEnumerator = fread(fh, 1, 'int32=>int32');% = 416; (* INT32 *) +tr.TrXTrace = fread(fh, 1, 'int32=>int32');% = 420; (* INT32 *) +tr.TrIntSolValue = fread(fh, 1, 'double=>double');% = 424; (* LONGREAL *) +tr.TrExtSolValue = fread(fh, 1, 'double=>double');% = 432; (* LONGREAL *) +tr.TrIntSolName = deblank(fread(fh, 32, 'uint8=>char')');% = 440; (* String32Size *) +tr.TrExtSolName = deblank(fread(fh, 32, 'uint8=>char')');% = 472; (* String32Size *) +tr.TrDataPedestal = fread(fh, 1, 'double=>double');% = 504; (* LONGREAL *) + +tr.TraceRecSize=512;% (* = 64 * 8 *) + +tr=orderfields(tr); + +end + +function L=getSeLockInParams(fh) +%-------------------------------------------------------------------------- +offset=ftell(fh); +L.loExtCalPhase = fread(fh, 1, 'double=>double');% = 0; (* LONGREAL *) +L.loExtCalAtten = fread(fh, 1, 'double=>double');% = 8; (* LONGREAL *) +L.loPLPhase = fread(fh, 1, 'double=>double');% = 16; (* LONGREAL *) +L.loPLPhaseY1 = fread(fh, 1, 'double=>double');% = 24; (* LONGREAL *) +L.loPLPhaseY2 = fread(fh, 1, 'double=>double');% = 32; (* LONGREAL *) +L.loUsedPhaseShift = fread(fh, 1, 'double=>double');% = 40; (* LONGREAL *) +L.loUsedAttenuation = fread(fh, 1, 'double=>double');% = 48; (* LONGREAL *) + L.loSpare = fread(fh, 1, 'double=>double');% = 56; (* LONGREAL *) +L.loExtCalValid = fread(fh, 1, 'uint8=>logical');% = 64; (* BOOLEAN *) +L.loPLPhaseValid = fread(fh, 1, 'uint8=>logical');% = 65; (* BOOLEAN *) +L.loLockInMode = fread(fh, 1, 'uint8=>uint8');% = 66; (* BYTE *) +L.loCalMode = fread(fh, 1, 'uint8=>uint8');% = 67; (* BYTE *) + L.loSpare2 = fread(fh, 7, 'int32=>in32');% = 68; (* remaining *) +L.LockInParamsSize = 96; + +fseek(fh, offset+L.LockInParamsSize, 'bof'); + +end + +%-------------------------------------------------------------------------- +function A=getAmplifierState(fh) +%-------------------------------------------------------------------------- +offset=ftell(fh); +A.sStateVersion = fread(fh, 1, 'double=>double');% = 0; (* 8 = SizeStateVersion *) +A.sCurrentGain = fread(fh, 1, 'double=>double');% = 8; (* LONGREAL *) +A.sF2Bandwidth = fread(fh, 1, 'double=>double');% = 16; (* LONGREAL *) +A.sF2Frequency = fread(fh, 1, 'double=>double');% = 24; (* LONGREAL *) +A.sRsValue = fread(fh, 1, 'double=>double');% = 32; (* LONGREAL *) +A.sRsFraction = fread(fh, 1, 'double=>double');% = 40; (* LONGREAL *) +A.sGLeak = fread(fh, 1, 'double=>double');% = 48; (* LONGREAL *) +A.sCFastAmp1 = fread(fh, 1, 'double=>double');% = 56; (* LONGREAL *) +A.sCFastAmp2 = fread(fh, 1, 'double=>double');% = 64; (* LONGREAL *) +A.sCFastTau = fread(fh, 1, 'double=>double');% = 72; (* LONGREAL *) +A.sCSlow = fread(fh, 1, 'double=>double');% = 80; (* LONGREAL *) +A.sGSeries = fread(fh, 1, 'double=>double');% = 88; (* LONGREAL *) +A.sVCStimDacScale = fread(fh, 1, 'double=>double');% = 96; (* LONGREAL *) +A.sCCStimScale = fread(fh, 1, 'double=>double');% = 104; (* LONGREAL *) +A.sVHold = fread(fh, 1, 'double=>double');% = 112; (* LONGREAL *) +A.sLastVHold = fread(fh, 1, 'double=>double');% = 120; (* LONGREAL *) +A.sVpOffset = fread(fh, 1, 'double=>double');% = 128; (* LONGREAL *) +A.sVLiquidJunction = fread(fh, 1, 'double=>double');% = 136; (* LONGREAL *) +A.sCCIHold = fread(fh, 1, 'double=>double');% = 144; (* LONGREAL *) +A.sCSlowStimVolts = fread(fh, 1, 'double=>double');% = 152; (* LONGREAL *) +A.sCCTrackVHold = fread(fh, 1, 'double=>double');% = 160; (* LONGREAL *) +A.sTimeoutCSlow = fread(fh, 1, 'double=>double');% = 168; (* LONGREAL *) +A.sSearchDelay = fread(fh, 1, 'double=>double');% = 176; (* LONGREAL *) +A.sMConductance = fread(fh, 1, 'double=>double');% = 184; (* LONGREAL *) +A.sMCapacitance = fread(fh, 1, 'double=>double');% = 192; (* LONGREAL *) +A.sSerialNumber = fread(fh, 1, 'double=>double');% = 200; (* 8 = SizeSerialNumber *) + +A.sE9Boards = fread(fh, 1, 'int16=>int16');% = 208; (* INT16 *) +A.sCSlowCycles = fread(fh, 1, 'int16=>int16');% = 210; (* INT16 *) +A.sIMonAdc = fread(fh, 1, 'int16=>int16');% = 212; (* INT16 *) +A.sVMonAdc = fread(fh, 1, 'int16=>int16');% = 214; (* INT16 *) + +A.sMuxAdc = fread(fh, 1, 'int16=>int16');% = 216; (* INT16 *) +A.sTestDac = fread(fh, 1, 'int16=>int16');% = 218; (* INT16 *) +A.sStimDac = fread(fh, 1, 'int16=>int16');% = 220; (* INT16 *) +A.sStimDacOffset = fread(fh, 1, 'int16=>int16');% = 222; (* INT16 *) + +A.sMaxDigitalBit = fread(fh, 1, 'int16=>int16');% = 224; (* INT16 *) +A.sHasCFastHigh = fread(fh, 1, 'uint8=>uint8');% = 226; (* BYTE *) +A.sCFastHigh = fread(fh, 1, 'uint8=>uint8');% = 227; (* BYTE *) +A.sHasBathSense = fread(fh, 1, 'uint8=>uint8');% = 228; (* BYTE *) +A.sBathSense = fread(fh, 1, 'uint8=>uint8');% = 229; (* BYTE *) +A.sHasF2Bypass = fread(fh, 1, 'uint8=>uint8');% = 230; (* BYTE *) +A.sF2Mode = fread(fh, 1, 'uint8=>uint8');% = 231; (* BYTE *) + +A.sAmplKind = fread(fh, 1, 'uint8=>uint8');% = 232; (* BYTE *) +A.sIsEpc9N = fread(fh, 1, 'uint8=>uint8');% = 233; (* BYTE *) +A.sADBoard = fread(fh, 1, 'uint8=>uint8');% = 234; (* BYTE *) +A.sBoardVersion = fread(fh, 1, 'uint8=>uint8');% = 235; (* BYTE *) +A.sActiveE9Board = fread(fh, 1, 'uint8=>uint8');% = 236; (* BYTE *) +A.sMode = fread(fh, 1, 'uint8=>uint8');% = 237; (* BYTE *) +A.sRange = fread(fh, 1, 'uint8=>uint8');% = 238; (* BYTE *) +A.sF2Response = fread(fh, 1, 'uint8=>uint8');% = 239; (* BYTE *) + +A.sRsOn = fread(fh, 1, 'uint8=>uint8');% = 240; (* BYTE *) +A.sCSlowRange = fread(fh, 1, 'uint8=>uint8');% = 241; (* BYTE *) +A.sCCRange = fread(fh, 1, 'uint8=>uint8');% = 242; (* BYTE *) +A.sCCGain = fread(fh, 1, 'uint8=>uint8');% = 243; (* BYTE *) +A.sCSlowToTestDac = fread(fh, 1, 'uint8=>uint8');% = 244; (* BYTE *) +A.sStimPath = fread(fh, 1, 'uint8=>uint8');% = 245; (* BYTE *) +A.sCCTrackTau = fread(fh, 1, 'uint8=>uint8');% = 246; (* BYTE *) +A.sWasClipping = fread(fh, 1, 'uint8=>uint8');% = 247; (* BYTE *) + +A.sRepetitiveCSlow = fread(fh, 1, 'uint8=>uint8');% = 248; (* BYTE *) +A.sLastCSlowRange = fread(fh, 1, 'uint8=>uint8');% = 249; (* BYTE *) + A.sOld1 = fread(fh, 1, 'uint8=>uint8');% = 250; (* BYTE *) +A.sCanCCFast = fread(fh, 1, 'uint8=>uint8');% = 251; (* BYTE *) +A.sCanLowCCRange = fread(fh, 1, 'uint8=>uint8');% = 252; (* BYTE *) +A.sCanHighCCRange = fread(fh, 1, 'uint8=>uint8');% = 253; (* BYTE *) +A.sCanCCTrackingg = fread(fh, 1, 'uint8=>uint8');% = 254; (* BYTE *) +A.sCHasVmonPath = fread(fh, 1, 'uint8=>uint8');% = 255; (* BYTE *) + +A.sHasNewCCMode = fread(fh, 1, 'uint8=>uint8');% = 256; (* BYTE *) +A.sSelector = fread(fh, 1, 'uint8=>char');% = 257; (* CHAR *) +A.sHoldInverted = fread(fh, 1, 'uint8=>uint8');% = 258; (* BYTE *) +A.sAutoCFast = fread(fh, 1, 'uint8=>uint8');% = 259; (* BYTE *) +A.sAutoCSlow = fread(fh, 1, 'uint8=>uint8');% = 260; (* BYTE *) +A.sHasVmonX100 = fread(fh, 1, 'uint8=>uint8');% = 261; (* BYTE *) +A.sTestDacOn = fread(fh, 1, 'uint8=>uint8');% = 262; (* BYTE *) +A.sQMuxAdcOn = fread(fh, 1, 'uint8=>uint8');% = 263; (* BYTE *) + +A.sImon1Bandwidth = fread(fh, 1, 'double=>double');% = 264; (* LONGREAL *) +A.sStimScale = fread(fh, 1, 'double=>double');% = 272; (* LONGREAL *) + +A.sGain = fread(fh, 1, 'uint8=>uint8');% = 280; (* BYTE *) +A.sFilter1 = fread(fh, 1, 'uint8=>uint8');% = 281; (* BYTE *) +A.sStimFilterOn = fread(fh, 1, 'uint8=>uint8');% = 282; (* BYTE *) +A.sRsSlow = fread(fh, 1, 'uint8=>uint8');% = 283; (* BYTE *) + A.sOld2 = fread(fh, 1, 'uint8=>uint8');% = 284; (* BYTE *) +A.sCCCFastOn = fread(fh, 1, 'uint8=>uint8');% = 285; (* BYTE *) +A.sCCFastSpeed = fread(fh, 1, 'uint8=>uint8');% = 286; (* BYTE *) +A.sF2Source = fread(fh, 1, 'uint8=>uint8');% = 287; (* BYTE *) + +A.sTestRange = fread(fh, 1, 'uint8=>uint8');% = 288; (* BYTE *) +A.sTestDacPath = fread(fh, 1, 'uint8=>uint8');% = 289; (* BYTE *) +A.sMuxChannel = fread(fh, 1, 'uint8=>uint8');% = 290; (* BYTE *) +A.sMuxGain64 = fread(fh, 1, 'uint8=>uint8');% = 291; (* BYTE *) +A.sVmonX100 = fread(fh, 1, 'uint8=>uint8');% = 292; (* BYTE *) +A.sIsQuadro = fread(fh, 1, 'uint8=>uint8');% = 293; (* BYTE *) +A.sF1Mode = fread(fh, 1, 'uint8=>uint8');% = 294; (* BYTE *) + A.sOld3 = fread(fh, 1, 'uint8=>uint8');% = 295; (* BYTE *) + +A.sStimFilterHz = fread(fh, 1, 'double=>double');% = 296; (* LONGREAL *) +A.sRsTau = fread(fh, 1, 'double=>double');% = 304; (* LONGREAL *) +A.sDacToAdcDelay = fread(fh, 1, 'double=>double');% = 312; (* LONGREAL *) +A.sInputFilterTau = fread(fh, 1, 'double=>double');% = 320; (* LONGREAL *) +A.sOutputFilterTau = fread(fh, 1, 'double=>double');% = 328; (* LONGREAL *) +A.sVmonFactor = fread(fh, 1, 'double=>double');% = 336; (* LONGREAL *) +A.sCalibDate = fread(fh, 2, 'double=>double');% = 344; (* 16 = SizeCalibDate *) +A.sVmonOffset = fread(fh, 1, 'double=>double');% = 360; (* LONGREAL *) + +A.sEEPROMKind = fread(fh, 1, 'uint8=>uint8');% = 368; (* BYTE *) +A.sVrefX2 = fread(fh, 1, 'uint8=>uint8');% = 369; (* BYTE *) +A.sHasVrefX2AndF2Vmon = fread(fh, 1, 'uint8=>uint8');% = 370; (* BYTE *) +A.sSpare1 = fread(fh, 1, 'uint8=>uint8');% = 371; (* BYTE *) +A.sSpare2 = fread(fh, 1, 'uint8=>uint8');% = 372; (* BYTE *) +A.sSpare3 = fread(fh, 1, 'uint8=>uint8');% = 373; (* BYTE *) +A.sSpare4 = fread(fh, 1, 'uint8=>uint8');% = 374; (* BYTE *) +A.sSpare5 = fread(fh, 1, 'uint8=>uint8');% = 375; (* BYTE *) + +A.sCCStimDacScale = fread(fh, 1, 'double=>double');% = 376; (* LONGREAL *) +A.sVmonFiltBandwidth = fread(fh, 1, 'double=>double');% = 384; (* LONGREAL *) +A.sVmonFiltFrequency = fread(fh, 1, 'double=>double');% = 392; (* LONGREAL *) +A.AmplifierStateSize = 400;% (* = 50 * 8 *) + +fseek(fh, offset+A.AmplifierStateSize, 'bof'); + +end \ No newline at end of file diff --git a/@HEKA_Importer/HI_readSolutionFileHEKA.m b/@HEKA_Importer/HI_readSolutionFileHEKA.m new file mode 100644 index 0000000..8c1a309 --- /dev/null +++ b/@HEKA_Importer/HI_readSolutionFileHEKA.m @@ -0,0 +1,95 @@ +function HI_readSolutionFileHEKA(obj,Level) + +% extracts data stored in the "*.sol" file, or the corresponding portion of +% the bundled ".dat" file +% +% See also HEKA_Importer +% HEKA_Importer.HI_loadHEKAFile +% HEKA_Importer.HI_extractHEKASolutionTree +% HEKA_Importer.HI_extractHEKAStimTree +% HEKA_Importer.HI_extractHEKADataTree +% HEKA_Importer.HI_readPulseFileHEKA +% HEKA_Importer.HI_readStimulusFileHEKA +% HEKA_Importer.HI_readAmplifierFileHEKA +% HEKA_Importer.HI_readSolutionFileHEKA + +%-------------------------------------------------------------------------- +% Gets one record of the tree and the number of children +s = getOneSolutionRecord(obj,Level); +obj.opt.fileData.Tree{obj.opt.fileData.Counter, Level+1} = s; + +obj.opt.fileData.Position = obj.opt.fileData.Position+obj.opt.fileData.Sizes(Level+1); +fseek(obj.opt.fileData.fh, obj.opt.fileData.Position, 'bof'); +obj.opt.fileData.nchild=fread(obj.opt.fileData.fh, 1, 'int32=>int32'); +obj.opt.fileData.Position=ftell(obj.opt.fileData.fh); + +end + + +%-------------------------------------------------------------------------- +function rec=getOneSolutionRecord(obj,Level) +%-------------------------------------------------------------------------- +% Gets one record +obj.opt.fileData.Counter = obj.opt.fileData.Counter+1; +switch Level + case 0 + rec=getSolutionRoot(obj); + case 1 + rec=getSolutionRecord(obj); + case 2 + rec=getChemicalRecord(obj); + + otherwise + error('Unexpected Level'); +end + +end + +%-------------------------------------------------------------------------- +function p=getSolutionRoot(obj) +%-------------------------------------------------------------------------- +fh = obj.opt.fileData.fh; + +p.RoVersion = fread(fh, 1, 'int16=>int16'); % = 0; (* INT16 *) +p.RoDataBaseName = deblank(fread(fh, 80, 'uint8=>char')');% = 2; (* SolutionNameSize *) +p.RoSpare1 = fread(fh, 1, 'int16=>int16');% = 82; (* INT16 *) +p.RoCRC = fread(fh, 1, 'int32=>int32'); % = 84; (* CARD32 *) +p.RootSize = 88;% = 88 + +p=orderfields(p); + +end + +%-------------------------------------------------------------------------- +function s=getSolutionRecord(obj) +%-------------------------------------------------------------------------- +fh = obj.opt.fileData.fh; + +s.SoNumber = fread(fh, 1, 'int32=>int32');% = 0; (* INT32 *) +s.SoName = deblank(fread(fh, 80, 'uint8=>char')');% = 4; (* SolutionNameSize *) +s.SoNumeric = fread(fh, 1, 'real*4=>double');% = 84; (* REAL *) *) +s.SoNumericName = deblank(fread(fh, 30, 'uint8=>char')');% = 88; (* ChemicalNameSize *) +s.SoPH = fread(fh, 1, 'real*4=>double');% = 118; (* REAL *) +s.SopHCompound = deblank(fread(fh, 30, 'uint8=>char')');% = 122; (* ChemicalNameSize *) +s.soOsmol = fread(fh, 1, 'real*4=>double');% = 152; (* REAL *) +s.SoCRC = fread(fh, 1, 'int32=>int32') ;% = 156; (* CARD32 *) +s.SolutionSize = 160;% = 160 + +s=orderfields(s); + +end + +%-------------------------------------------------------------------------- +function c=getChemicalRecord(obj) +%-------------------------------------------------------------------------- +fh = obj.opt.fileData.fh; + +c.ChConcentration = fread(fh, 1, 'real*4=>double');% = 0; (* REAL *) +c.ChName = deblank(fread(fh, 30, 'uint8=>char')');% = 4; (* ChemicalNameSize *) +c.ChSpare1 = fread(fh, 1, 'int16=>int16');% = 34; (* INT16 *) +c.ChCRC = fread(fh, 1, 'int32=>int32')';% = 36; (* CARD32 *) +c.ChemicalSize = 40;% = 40 + +c=orderfields(c); + +end diff --git a/@HEKA_Importer/HI_readStimulusFileHEKA.m b/@HEKA_Importer/HI_readStimulusFileHEKA.m new file mode 100644 index 0000000..43bb83f --- /dev/null +++ b/@HEKA_Importer/HI_readStimulusFileHEKA.m @@ -0,0 +1,224 @@ +function HI_readStimulusFileHEKA(obj,Level) +% +% extracts data stored in the "*.pgf" file, or the corresponding portion of +% the bundled ".dat" file +% +%% See also HEKA_Importer +% HEKA_Importer.HI_loadHEKAFile +% HEKA_Importer.HI_extractHEKASolutionTree +% HEKA_Importer.HI_extractHEKAStimTree +% HEKA_Importer.HI_extractHEKADataTree +% HEKA_Importer.HI_readPulseFileHEKA +% HEKA_Importer.HI_readStimulusFileHEKA +% HEKA_Importer.HI_readAmplifierFileHEKA +% HEKA_Importer.HI_readSolutionFileHEKA + +%-------------------------------------------------------------------------- +% Gets one record of the tree and the number of children +s = getOneStimRecord(obj,Level); +obj.opt.fileData.Tree{obj.opt.fileData.Counter, Level+1} = s; +obj.opt.fileData.Position = obj.opt.fileData.Position+obj.opt.fileData.Sizes(Level+1); +fseek(obj.opt.fileData.fh, obj.opt.fileData.Position, 'bof'); +obj.opt.fileData.nchild=fread(obj.opt.fileData.fh, 1, 'int32=>int32'); +obj.opt.fileData.Position=ftell(obj.opt.fileData.fh); +end + + +%-------------------------------------------------------------------------- +function rec=getOneStimRecord(obj,Level) +%-------------------------------------------------------------------------- +% Gets one record +obj.opt.fileData.Counter = obj.opt.fileData.Counter+1; +switch Level + case 0 + rec=getStimRoot(obj); + case 1 + rec=getStimulation(obj); + case 2 + rec=getChannel(obj); + case 3 + rec=getStimSegment(obj); + otherwise + error('Unexpected Level'); +end + +end + +% The functions below return data as defined by the HEKA PatchMaster +% specification + +%-------------------------------------------------------------------------- +function p=getStimRoot(obj) +%-------------------------------------------------------------------------- +fh = obj.opt.fileData.fh; + +p.RoVersion = fread(fh, 1, 'int32=>int32');% = 0; (* INT32 *) +p.RoMark = fread(fh, 1, 'int32=>int32');% = 4; (* INT32 *) +p.RoVersionName = deblank(fread(fh, 32, 'uint8=>char')');% = 8; (* String32Type *) +p.RoMaxSamples = fread(fh, 1, 'int32=>int32'); % = 40; (* INT32 *) +p.RoFiller1 = fread(fh, 1, 'int32=>int32');% = 44; (* INT32 *) +p.RoParams = fread(fh, 10, 'double=>double');% = 48; (* ARRAY[0..9] OF LONGREAL *) +for k=1:10 + p.RoParamText{k}=deblank(fread(fh, 32, 'uint8=>char')');% = 128; (* ARRAY[0..9],[0..31]OF CHAR *) +end +p.RoReserved = fread(fh, 32, 'int32=>int32');% = 448; (* INT32 *) +p.RoFiller2 = fread(fh, 1, 'int32=>int32');% = 576; (* INT32 *) +p.RoCRC = fread(fh, 1, 'int32=>int32');% = 580; (* CARD32 *) +p.RootRecSize = 584; % (* = 73 * 8 *) +p=orderfields(p); + +end + +%-------------------------------------------------------------------------- +function s=getStimulation(obj) +%-------------------------------------------------------------------------- +fh = obj.opt.fileData.fh; + +% Stimulus level +s.stMark = fread(fh, 1, 'int32=>int32');% = 0; (* INT32 *) +s.stEntryName = deblank(fread(fh, 32, 'uint8=>char')');% = 4; (* String32Type *) +s.stFileName = deblank(fread(fh, 32, 'uint8=>char')');% = 36; (* String32Type *) +s.stAnalName = deblank(fread(fh, 32, 'uint8=>char')');% = 68; (* String32Type *) +s.stDataStartSegment = fread(fh, 1, 'int32=>int32');% = 100; (* INT32 *) +s.stDataStartTime = fread(fh, 1, 'double=>double') ;% = 104; (* LONGREAL *) +s.stDataStartTimeMATLAB = obj.HI_time2date(s.stDataStartTime); +s.stSampleInterval = fread(fh, 1, 'double=>double') ;% = 112; (* LONGREAL *) +s.stSweepInterval = fread(fh, 1, 'double=>double') ;% = 120; (* LONGREAL *) +s.stLeakDelay = fread(fh, 1, 'double=>double') ;% = 128; (* LONGREAL *) +s.stFilterFactor = fread(fh, 1, 'double=>double') ;% = 136; (* LONGREAL *) +s.stNumberSweeps = fread(fh, 1, 'int32=>int32');% = 144; (* INT32 *) +s.stNumberLeaks = fread(fh, 1, 'int32=>int32');% = 148; (* INT32 *) +s.stNumberAverages = fread(fh, 1, 'int32=>int32');% = 152; (* INT32 *) +s.stActualAdcChannels = fread(fh, 1, 'int32=>int32');% = 156; (* INT32 *) +s.stActualDacChannels = fread(fh, 1, 'int32=>int32');% = 160; (* INT32 *) +s.stExtTrigger = fread(fh, 1, 'uint8=>uint8');% = 164; (* BYTE *) +s.stNoStartWait = fread(fh, 1, 'uint8=>logical');% = 165; (* BOOLEAN *) +s.stUseScanRates = fread(fh, 1, 'uint8=>logical');% = 166; (* BOOLEAN *) +s.stNoContAq = fread(fh, 1, 'uint8=>logical');% = 167; (* BOOLEAN *) +s.stHasLockIn = fread(fh, 1, 'uint8=>logical');% = 168; (* BOOLEAN *) +s.stOldStartMacKind = fread(fh, 1, 'uint8=>char');% = 169; (* CHAR *) +s.stOldEndMacKind = fread(fh, 1, 'uint8=>logical');% = 170; (* BOOLEAN *) +s.stAutoRange = fread(fh, 1, 'uint8=>uint8');% = 171; (* BYTE *) +s.stBreakNext = fread(fh, 1, 'uint8=>logical');% = 172; (* BOOLEAN *) +s.stIsExpanded = fread(fh, 1, 'uint8=>logical');% = 173; (* BOOLEAN *) +s.stLeakCompMode = fread(fh, 1, 'uint8=>logical');% = 174; (* BOOLEAN *) +s.stHasChirp = fread(fh, 1, 'uint8=>logical');% = 175; (* BOOLEAN *) +s.stOldStartMacro = deblank(fread(fh, 32, 'uint8=>char')');% = 176; (* String32Type *) +s.stOldEndMacro = deblank(fread(fh, 32, 'uint8=>char')');% = 208; (* String32Type *) +s.sIsGapFree = fread(fh, 1, 'uint8=>logical');% = 240; (* BOOLEAN *) +s.sHandledExternally = fread(fh, 1, 'uint8=>logical');% = 241; (* BOOLEAN *) + s.stFiller1 = fread(fh, 1, 'uint8=>logical');% = 242; (* BOOLEAN *) + s.stFiller2 = fread(fh, 1, 'uint8=>logical');% = 243; (* BOOLEAN *) +s.stCRC = fread(fh, 1, 'int32=>int32'); % = 244; (* CARD32 *) +s.StimulationRecSize = 248;% (* = 35 * 8 *) + +s=orderfields(s); + +end + +%-------------------------------------------------------------------------- +function c=getChannel(obj) +%-------------------------------------------------------------------------- +fh = obj.opt.fileData.fh; + +c.chMark = fread(fh, 1, 'int32=>int32');% = 0; (* INT32 *) +c.chLinkedChannel = fread(fh, 1, 'int32=>int32');% = 4; (* INT32 *) +c.chCompressionFactor = fread(fh, 1, 'int32=>int32');% = 8; (* INT32 *) +c.chYUnit = deblank(fread(fh, 8, 'uint8=>char')');% = 12; (* String8Type *) +c.chAdcChannel = fread(fh, 1, 'int16=>int16');% = 20; (* INT16 *) +c.chAdcMode = fread(fh, 1, 'uint8=>uint8');% = 22; (* BYTE *) +c.chDoWrite = fread(fh, 1, 'uint8=>logical');% = 23; (* BOOLEAN *) +c.stLeakStore = fread(fh, 1, 'uint8=>uint8');% = 24; (* BYTE *) +c.chAmplMode = fread(fh, 1, 'uint8=>uint8');% = 25; (* BYTE *) +c.chOwnSegTime = fread(fh, 1, 'uint8=>logical');% = 26; (* BOOLEAN *) +c.chSetLastSegVmemb = fread(fh, 1, 'uint8=>logical');% = 27; (* BOOLEAN *) +c.chDacChannel = fread(fh, 1, 'int16=>int16');% = 28; (* INT16 *) +c.chDacMode = fread(fh, 1, 'uint8=>uint8');% = 30; (* BYTE *) +c.chHasLockInSquare = fread(fh, 1, 'uint8=>uint8');% = 31; (* BYTE *) +c.chRelevantXSegment = fread(fh, 1, 'int32=>int32');% = 32; (* INT32 *) +c.chRelevantYSegment = fread(fh, 1, 'int32=>int32');% = 36; (* INT32 *) +c.chDacUnit = deblank(fread(fh, 8, 'uint8=>char')');% = 40; (* String8Type *) +c.chHolding = fread(fh, 1, 'double=>double') ;% = 48; (* LONGREAL *) +c.chLeakHolding = fread(fh, 1, 'double=>double') ;% = 56; (* LONGREAL *) +c.chLeakSize = fread(fh, 1, 'double=>double') ;% = 64; (* LONGREAL *) +c.chLeakHoldMode = fread(fh, 1, 'uint8=>uint8');% = 72; (* BYTE *) +c.chLeakAlternate = fread(fh, 1, 'uint8=>logical');% = 73; (* BOOLEAN *) +c.chAltLeakAveraging = fread(fh, 1, 'uint8=>logical');% = 74; (* BOOLEAN *) +c.chLeakPulseOn = fread(fh, 1, 'uint8=>logical');% = 75; (* BOOLEAN *) +c.chStimToDacID = fread(fh, 1, 'int16=>int16');% = 76; (* SET16 *) +c.chCompressionMode = fread(fh, 1, 'int16=>int16');% = 78; (* SET16 *) +c.chCompressionSkip = fread(fh, 1, 'int32=>int32');% = 80; (* INT32 *) +c.chDacBit = fread(fh, 1, 'int16=>int16');% = 84; (* INT16 *) +c.chHasLockInSine = fread(fh, 1, 'uint8=>logical');% = 86; (* BOOLEAN *) +c.chBreakMode = fread(fh, 1, 'uint8=>uint8');% = 87; (* BYTE *) +c.chZeroSeg = fread(fh, 1, 'int32=>int32');% = 88; (* INT32 *) +c.chStimSweep = fread(fh, 1, 'int32=>int32');% = 92; (* INT32 *) +c.chSine_Cycle = fread(fh, 1, 'double=>double') ;% = 96; (* LONGREAL *) +c.chSine_Amplitude = fread(fh, 1, 'double=>double') ;% = 104; (* LONGREAL *) +c.chLockIn_VReversal = fread(fh, 1, 'double=>double') ;% = 112; (* LONGREAL *) +c.chChirp_StartFreq = fread(fh, 1, 'double=>double') ;% = 120; (* LONGREAL *) +c.chChirp_EndFreq = fread(fh, 1, 'double=>double') ;% = 128; (* LONGREAL *) +c.chChirp_MinPoints = fread(fh, 1, 'double=>double') ;% = 136; (* LONGREAL *) +c.chSquare_NegAmpl = fread(fh, 1, 'double=>double') ;% = 144; (* LONGREAL *) +c.chSquare_DurFactor = fread(fh, 1, 'double=>double') ;% = 152; (* LONGREAL *) +c.chLockIn_Skip = fread(fh, 1, 'int32=>int32');% = 160; (* INT32 *) +c.chPhoto_MaxCycles = fread(fh, 1, 'int32=>int32');% = 164; (* INT32 *) +c.chPhoto_SegmentNo = fread(fh, 1, 'int32=>int32');% = 168; (* INT32 *) +c.chLockIn_AvgCycles = fread(fh, 1, 'int32=>int32');% = 172; (* INT32 *) +c.chImaging_RoiNo = fread(fh, 1, 'int32=>int32');% = 176; (* INT32 *) +c.chChirp_Skip = fread(fh, 1, 'int32=>int32');% = 180; (* INT32 *) +c.chChirp_Amplitude = fread(fh, 1, 'double=>double');% = 184; (* LONGREAL *) +c.chPhoto_Adapt = fread(fh, 1, 'uint8=>uint8');% = 192; (* BYTE *) +c.chSine_Kind = fread(fh, 1, 'uint8=>uint8');% = 193; (* BYTE *) +c.chChirp_PreChirp = fread(fh, 1, 'uint8=>uint8');% = 194; (* BYTE *) +c.chSine_Source = fread(fh, 1, 'uint8=>uint8');% = 195; (* BYTE *) +c.chSquare_NegSource = fread(fh, 1, 'uint8=>uint8');% = 196; (* BYTE *) +c.chSquare_PosSource = fread(fh, 1, 'uint8=>uint8');% = 197; (* BYTE *) +c.chChirp_Kind = fread(fh, 1, 'uint8=>uint8');% = 198; (* BYTE *) +c.chChirp_Source = fread(fh, 1, 'uint8=>uint8');% = 199; (* BYTE *) +c.chDacOffset = fread(fh, 1, 'double=>double') ;% = 200; (* LONGREAL *) +c.chAdcOffset = fread(fh, 1, 'double=>double') ;% = 208; (* LONGREAL *) +c.chTraceMathFormat = fread(fh, 1, 'uint8=>uint8');% = 216; (* BYTE *) +c.chHasChirp = fread(fh, 1, 'uint8=>logical');% = 217; (* BOOLEAN *) +c.chSquare_Kind = fread(fh, 1, 'uint8=>uint8');% = 218; (* BYTE *) + c.chFiller1 = fread(fh, 5, 'uint8=>char');% = 219; (* ARRAY[0..5] OF CHAR *) +c.chSquare_BaseIncr = fread(fh, 1, 'double=>double');% = 224; (* LONGREAL *) +c.chSquare_Cycle = fread(fh, 1, 'double=>double') ;% = 232; (* LONGREAL *) +c.chSquare_PosAmpl = fread(fh, 1, 'double=>double') ;% = 240; (* LONGREAL *) +c.chCompressionOffset = fread(fh, 1, 'int32=>int32');% = 248; (* INT32 *) +c.chPhotoMode = fread(fh, 1, 'int32=>int32');% = 252; (* INT32 *) +c.chBreakLevel = fread(fh, 1, 'double=>double') ;% = 256; (* LONGREAL *) +c.chTraceMath = deblank(fread(fh,128,'uint8=>char')');% = 264; (* String128Type *) +c.chOldCRC = fread(fh, 1, 'int32=>int32');% = 268; (* CARD32 *) + c.chFiller2 = fread(fh, 1, 'int32=>int32');% = 392; (* INT32 *) +c.chCRC = fread(fh, 1, 'int32=>int32');% = 396; (* CARD32 *) +c.ChannelRecSize = 400;% (* = 50 * 8 *) +c=orderfields(c); + +end + +%-------------------------------------------------------------------------- +function ss=getStimSegment(obj) +%-------------------------------------------------------------------------- +fh = obj.opt.fileData.fh; + +ss.seMark = fread(fh, 1, 'int32=>int32');% = 0; (* INT32 *) +ss.seClass = fread(fh, 1, 'uint8=>uint8');% = 4; (* BYTE *) +ss.seDoStore = fread(fh, 1, 'uint8=>logical');% = 5; (* BOOLEAN *) +ss.seVoltageIncMode = fread(fh, 1, 'uint8=>uint8');% = 6; (* BYTE *) +ss.seDurationIncMode = fread(fh, 1, 'uint8=>uint8');% = 7; (* BYTE *) +ss.seVoltage = fread(fh, 1, 'double=>double');% = 8; (* LONGREAL *) +ss.seVoltageSource = fread(fh, 1, 'int32=>int32');% = 16; (* INT32 *) +ss.seDeltaVFactor = fread(fh, 1, 'double=>double');% = 20; (* LONGREAL *) +ss.seDeltaVIncrement = fread(fh, 1, 'double=>double');% = 28; (* LONGREAL *) +ss.seDuration = fread(fh, 1, 'double=>double');% = 36; (* LONGREAL *) +ss.seDurationSource = fread(fh, 1, 'int32=>int32');% = 44; (* INT32 *) +ss.seDeltaTFactor = fread(fh, 1, 'double=>double');% = 48; (* LONGREAL *) +ss.seDeltaTIncrement = fread(fh, 1, 'double=>double');% = 56; (* LONGREAL *) +ss.seFiller1 = fread(fh, 1, 'int32=>int32');% = 64; (* INT32 *) +ss.seCRC = fread(fh, 1, 'int32=>int32');% = 68; (* CARD32 *) +ss.seScanRate = fread(fh, 1, 'double=>double');% = 72; (* LONGREAL *) +ss.StimSegmentRecSize = 80;% (* = 10 * 8 *) +ss=orderfields(ss); + +end diff --git a/@HEKA_Importer/HI_time2date.m b/@HEKA_Importer/HI_time2date.m new file mode 100644 index 0000000..1f3e54f --- /dev/null +++ b/@HEKA_Importer/HI_time2date.m @@ -0,0 +1,24 @@ +function str=HI_time2date(obj,t) + +% converts time stored in HEKA file to Matlab time format. +% +% See also HEKA_Importer +% HEKA_Importer.HI_loadHEKAFile +% HEKA_Importer.HI_extractHEKASolutionTree +% HEKA_Importer.HI_extractHEKAStimTree +% HEKA_Importer.HI_extractHEKADataTree +% HEKA_Importer.HI_readPulseFileHEKA +% HEKA_Importer.HI_readStimulusFileHEKA +% HEKA_Importer.HI_readAmplifierFileHEKA +% HEKA_Importer.HI_readSolutionFileHEKA + +%-------------------------------------------------------------------------- +t=t-1580970496; +if t<0 + t=t+4294967296; +end +t=t+9561652096; +str=datestr(t/(24*60*60)+datenum(1601,1,1)); +return +end +%-------------------------------------------------------------------------- \ No newline at end of file diff --git a/@HEKA_Importer/old/HI_SplitSeries.m b/@HEKA_Importer/old/HI_SplitSeries.m deleted file mode 100644 index 05af13b..0000000 --- a/@HEKA_Importer/old/HI_SplitSeries.m +++ /dev/null @@ -1,198 +0,0 @@ -function obj = HI_SplitSeries(obj,data,varargin) - -% HI_SplitSeries.m -% This function takes the collapsed data set (dCollapse) and splits it by -% group and series, assigning these as fields into the struct. -% -% EXAMPLE: -% [structA] = SplitSeries(tree, data, saveName, structA) -% [structA] = SplitSeries(tree, data, saveName, structA, stimTree) -% -% INPUTS: -% tree struct The metadata tree, from importing a HEKA -% Patchmaster .dat file. -% -% data cell A 1xm cell containing all series and traces -% from all channels, as output by -% ImportHEKAtoMat() and collapsed by -% ImportPatchData(). -% -% saveName char The name of the file from which the data -% was imported, the date by default. -% -% structA struct The output data structure to which new -% fields will be appended. May be empty. -% -% OPTIONAL INPUTS: -% stimTree cell The stimulus metadata tree, from importing -% a .dat file. -% -% OUTPUTS: -% structA struct Output data structure in same format, with -% newly appended fields representing groups. -% Each group is a struct, containing the -% original filename, the list of pgfs, and -% the data in a cell of dimensions (series, -% channel) for that group. -% -% Created by Sammy Katta on 27 May 2014. -% Modified by Christian Keine 01/2019. - -P = inputParser; -P.addRequired('data'); - -P.parse(data,varargin{:}); - -stimTree = obj.trees.stimTree; -dataTree = obj.trees.dataTree; - -% Find which rows in tree contain group, series, and sweep metadata -grLoc = find(~cellfun('isempty',dataTree(:,2))); -seLoc = find(~cellfun('isempty',dataTree(:,3))); - -if ~isempty(stimTree) - stLoc = find(~cellfun('isempty',stimTree(:,2))); - - % The number of entries with stimulus parameters should match the total - % number of series. - if length(seLoc) ~= length(stLoc) - fprintf('%s stimulus data does not match total number of series\n', saveName) - return - end -end - -% Figure out how many series are in each group/biological cell by pulling -% the SeSeriesCount field for the last series in the group, and initialize -% a cell array of that length to hold data from that group -serTot = 1; -% traceTot = 1; -dataRaw = cell(size(grLoc)); -SR = cell(size(grLoc)); -chNames = cell(size(grLoc)); - -for iGr = 1:length(grLoc) - % Strip hyphens/other characters that are invalid in field names - currGr = matlab.lang.makeValidName(dataTree{grLoc(iGr),2}.GrLabel); - - % Find number of series in each group but don't get tripped up by the - % last group. - if iGr size(dataTree,1) ||... - isempty(dataTree{seLoc(serTot)+2+nChan,5}) - isTrace = 0; - else - nChan = nChan + 1; - chanType{nChan} = matlab.lang.makeValidName(dataTree{seLoc(serTot)+1+nChan,5}.TrLabel); - chanUnit{nChan} = dataTree{seLoc(serTot)+1+nChan,5}.TrYUnit; - end - end - - % Assign data to proper location in cell array for that group. - % If there are multiple channels/traces per sweep for a given - % series, Patchmaster stores them as separate series, one after - % another, i.e., if the real series 5 recorded both current and - % voltage, data(5) will contain the current and data(6) will - % contain the voltage. - - % STRIP DOWN TO ACTUAL NUMBER OF CHANNELS AND REMOVE EMPTY CELLS - % FOR RESHAPING LATER - - chanType = chanType(1:nChan,:); - chanUnit = chanUnit(1:nChan,:); - - - % GET CHANNEL TYPE/NAME AND UNITS - grpType{iSer} = reshape(chanType,1,nChan); - grpUnit{iSer} = reshape(chanUnit,1,nChan); - - if ~isempty(stimTree) - % Pull out the relevant section of the stimTree for the series at - % hand. nChan may not be the same for stimTree if you have channels - % with DA output but no *stored* AD input (i.e., more channels in - % stimTree than in dataTree). - try - stLocEnd = stLoc(serTot+1)-1; - catch - stLocEnd = size(stimTree,1); - end - - grpStim{iSer} = stimTree(stLoc(serTot):stLocEnd,2:4); - - end - - % Move on to the next round - serTot = serTot+1; - end - - % Save data to the appropriate group in the nested output struct. - ephysData.(currGr).data = data{iGr}; - ephysData.(currGr).protocols = grpProt; - ephysData.(currGr).channel = grpType; - ephysData.(currGr).dataunit = grpUnit; - ephysData.(currGr).samplingFreq = grpFs; - ephysData.(currGr).startTimes = grpTimes; - ephysData.(currGr).ccHold = grpHolds; - - if ~isempty(stimTree) - ephysData.(currGr).stimTree = grpStim; - end - - %% ADD MINIMUM RANDOM NUMBER TO AVOID DISCRETIZATION; ADD TO ALL CHANNELS - addEPS = @(x) x+randn(size(x))*eps; - - - for iSer=1:nSer - ephysData.(currGr).data{iSer} = cellfun(addEPS,ephysData.(currGr).data{iSer},'UniformOutput',false); - end - - dataRaw{iGr,:} = ephysData.(currGr).data; - SR{iGr,:} = reshape([ephysData.(currGr).samplingFreq{:}], numel([ephysData.(currGr).samplingFreq{:}]),1); - chNames{iGr,:} = grpType; - -end - -obj.RecTable.dataRaw = vertcat(dataRaw{:}); -obj.RecTable.SR = vertcat(SR{:}); -obj.RecTable.chNames = vertcat(chNames{:}); -obj.RecTable = struct2table(obj.RecTable); - -end diff --git a/README.md b/README.md index 9912b62..41fdbf8 100644 --- a/README.md +++ b/README.md @@ -22,10 +22,13 @@ to load HEKA Patchmaster file "MyData.dat" located in "C:\PatchClamp\" run `HEKA Heka_Importer creates object containing the following properties: -- **trees**: structure containing the dataTree (from the .pul file), the stimTree (from the .pgf file) and solTree (from the .sol file). These tree structures are how HEKA saves the metadata for different recordings. For details on the HEKA file format check ftp://server.hekahome.de/pub/FileFormat/Patchmasterv9/. +- **trees**: structure containing the dataTree (from the .pul file), the stimTree (from the .pgf file) and solTree (from the .sol file). These tree structures are how HEKA saves the metadata for different recordings. For details on the HEKA file format check ftp://server.hekahome.de/pub/FileFormat/Patchmasterv9/ and ftp://server.hekahome.de/pub/FileFormat/Patchmasterv1000/. -- **opt**: structure containing different options when loading the file, currently it only contains the filepath of the HEKA Patchmaster file which was loaded and serves as placeholder for additional options in the future. +- **opt**: structure containing different options when loading the file, currently it only contains the filepath of the HEKA Patchmaster file which was loaded and some temporary information used during loading the files. -- **RecTable**: Matlab table containing the recordings and several parameters associated with them. Each row represents a different recording. The recorded data are stored in `RecTable.dataRaw` and sorted by channel within, e.g. `RecTable.dataRaw{1}{2}` contains all sweeps of the first series/recording for the second channel. The corresponding name of the channels is stored in `RecTable.chNames{1}`. +- **RecTable**: Matlab table containing the recordings and several parameters associated with them. Each row represents a different recording. The recorded data are stored in `RecTable.dataRaw` and sorted by channel within, e.g. `RecTable.dataRaw{1}{2}` contains all sweeps of the first series/recording for the second channel. The corresponding name of the channels is stored in `RecTable.chNames{1}`. Accordingly, the cell capacitance for each sweep of this recording is stored in `RecTable.Cm{1}{2}`. Note that this is slightly different from how Patchmaster stores the data internally. In Patchmaster, the data tree is nested by Series > Sweep > Channel, whereas the data table in Matlab will be sorted as Series > Channel > Sweep. - **solutions**: Matlab table containing the solutions and composition (chemicals & concentration) used during the experiments. This table is read-out from the solTree of the HEKA Patchmaster file and requires that the recordings were associated with a solution base (otherwise this variable will be empty). The names of solutions correspond to the columns "ExternalSolution" and "InternalSolution" of the RecTable. + +UPDATE: As of Patchmaster version 2x90.3 (including Patchmaster Next), HEKA made minor changes to how data is stored in the tree structures. The amplifier settings are now always stored in a separate ".amp" file (which is part of the DAT bundle file). In previous versions, such a separate file was created only for EPC/n amplifiers. +The HEKA_Import function has been updated accordingly and should work with older 2x90 versions and newer (>2x90.3/PMN) alike, but the amplifier settings might be stored differently.