Loading EEG/EEG.cpp +45 −48 Original line number Diff line number Diff line Loading @@ -86,10 +86,9 @@ autoEEG EEG_create (double tmin, double tmax) { } integer EEG_getChannelNumber (EEG me, conststring32 channelName) { for (integer ichan = 1; ichan <= my numberOfChannels; ichan ++) { for (integer ichan = 1; ichan <= my numberOfChannels; ichan ++) if (Melder_equ (my channelNames [ichan].get(), channelName)) return ichan; } return 0; } Loading @@ -99,7 +98,7 @@ autoEEG EEG_readFromBdfFile (MelderFile file) { char buffer [81]; fread (buffer, 1, 8, f); buffer [8] = '\0'; bool is24bit = buffer [0] == (char) 255; const bool is24bit = ( buffer [0] == (char) 255 ); fread (buffer, 1, 80, f); buffer [80] = '\0'; trace (U"Local subject identification: \"", Melder_peek8to32 (buffer), U"\""); Loading @@ -114,27 +113,27 @@ autoEEG EEG_readFromBdfFile (MelderFile file) { trace (U"Start time of recording: \"", Melder_peek8to32 (buffer), U"\""); fread (buffer, 1, 8, f); buffer [8] = '\0'; integer numberOfBytesInHeaderRecord = atol (buffer); const integer numberOfBytesInHeaderRecord = atol (buffer); trace (U"Number of bytes in header record: ", numberOfBytesInHeaderRecord); fread (buffer, 1, 44, f); buffer [44] = '\0'; trace (U"Version of data format: \"", Melder_peek8to32 (buffer), U"\""); fread (buffer, 1, 8, f); buffer [8] = '\0'; integer numberOfDataRecords = strtol (buffer, nullptr, 10); const integer numberOfDataRecords = strtol (buffer, nullptr, 10); trace (U"Number of data records: ", numberOfDataRecords); fread (buffer, 1, 8, f); buffer [8] = '\0'; double durationOfDataRecord = atof (buffer); const double durationOfDataRecord = atof (buffer); trace (U"Duration of a data record: ", durationOfDataRecord); fread (buffer, 1, 4, f); buffer [4] = '\0'; integer numberOfChannels = atol (buffer); const integer numberOfChannels = atol (buffer); trace (U"Number of channels in data record: ", numberOfChannels); if (numberOfBytesInHeaderRecord != (numberOfChannels + 1) * 256) Melder_throw (U"Number of bytes in header record (", numberOfBytesInHeaderRecord, U") doesn't match number of channels (", numberOfChannels, U")."); autostring32vector channelNames (numberOfChannels); autoSTRVEC channelNames (numberOfChannels); for (integer ichannel = 1; ichannel <= numberOfChannels; ichannel ++) { fread (buffer, 1, 16, f); buffer [16] = '\0'; // labels of the channels Loading @@ -142,16 +141,15 @@ autoEEG EEG_readFromBdfFile (MelderFile file) { * Strip all final spaces. */ for (int i = 15; i >= 0; i --) { if (buffer [i] == ' ') { if (buffer [i] == ' ') buffer [i] = '\0'; } else { else break; } } channelNames [ichannel] = Melder_8to32 (buffer); trace (U"Channel <<", channelNames [ichannel].get(), U">>"); } bool hasLetters = str32equ (channelNames [numberOfChannels].get(), U"EDF Annotations"); const bool hasLetters = str32equ (channelNames [numberOfChannels].get(), U"EDF Annotations"); double samplingFrequency = undefined; for (integer channel = 1; channel <= numberOfChannels; channel ++) { fread (buffer, 1, 80, f); Loading Loading @@ -193,7 +191,7 @@ autoEEG EEG_readFromBdfFile (MelderFile file) { for (integer channel = 1; channel <= numberOfChannels; channel ++) { fread (buffer, 1, 8, f); buffer [8] = '\0'; // number of samples in each data record integer numberOfSamplesInThisDataRecord = atol (buffer); const integer numberOfSamplesInThisDataRecord = atol (buffer); if (isundef (samplingFrequency)) { numberOfSamplesPerDataRecord = numberOfSamplesInThisDataRecord; samplingFrequency = numberOfSamplesInThisDataRecord / durationOfDataRecord; Loading @@ -207,36 +205,37 @@ autoEEG EEG_readFromBdfFile (MelderFile file) { fread (buffer, 1, 32, f); buffer [32] = '\0'; // reserved } double duration = numberOfDataRecords * durationOfDataRecord; const double duration = numberOfDataRecords * durationOfDataRecord; autoEEG him = EEG_create (0, duration); his numberOfChannels = numberOfChannels; autoSound me = Sound_createSimple (numberOfChannels, duration, samplingFrequency); Melder_assert (my nx == numberOfSamplesPerDataRecord * numberOfDataRecords); autoNUMvector <uint8> dataBuffer ((integer) 0, 3 * numberOfSamplesPerDataRecord - 1); autoBYTEVEC dataBuffer = newBYTEVECzero (3 * numberOfSamplesPerDataRecord); for (integer record = 1; record <= numberOfDataRecords; record ++) { for (integer channel = 1; channel <= numberOfChannels; channel ++) { double factor = channel == numberOfChannels ? 1.0 : physicalMinimum [channel] / digitalMinimum [channel]; if (channel < numberOfChannels - EEG_getNumberOfExtraSensors (him.get())) factor /= 1000000.0; double factor = ( channel == numberOfChannels ? 1.0 : physicalMinimum [channel] / digitalMinimum [channel] ); if (channel < numberOfChannels - EEG_getNumberOfExtraSensors (him.get())) factor /= 1000000.0; if (is24bit) { fread (& dataBuffer [0], 3, (size_t) numberOfSamplesPerDataRecord, f); uint8 *p = & dataBuffer [0]; fread (dataBuffer.asArgumentToFunctionThatExpectsZeroBasedArray(), 3, (size_t) numberOfSamplesPerDataRecord, f); byte *p = & dataBuffer [1]; for (integer i = 1; i <= numberOfSamplesPerDataRecord; i ++) { integer sample = i + (record - 1) * numberOfSamplesPerDataRecord; const integer sample = i + (record - 1) * numberOfSamplesPerDataRecord; Melder_assert (sample <= my nx); uint8 lowByte = *p ++, midByte = *p ++, highByte = *p ++; const uint8 lowByte = *p ++, midByte = *p ++, highByte = *p ++; uint32 externalValue = ((uint32) highByte << 16) | ((uint32) midByte << 8) | (uint32) lowByte; if ((highByte & 128) != 0) // is the 24-bit sign bit on? externalValue |= 0xFF00'0000; // extend negative sign to 32 bits my z [channel] [sample] = (int32) externalValue * factor; } } else { fread (& dataBuffer [0], 2, (size_t) numberOfSamplesPerDataRecord, f); uint8 *p = & dataBuffer [0]; fread (dataBuffer.asArgumentToFunctionThatExpectsZeroBasedArray(), 2, (size_t) numberOfSamplesPerDataRecord, f); byte *p = & dataBuffer [1]; for (integer i = 1; i <= numberOfSamplesPerDataRecord; i ++) { integer sample = i + (record - 1) * numberOfSamplesPerDataRecord; const integer sample = i + (record - 1) * numberOfSamplesPerDataRecord; Melder_assert (sample <= my nx); uint8 lowByte = *p ++, highByte = *p ++; uint16 externalValue = (uint16) ((uint16) highByte << 8) | (uint16) lowByte; const uint8 lowByte = *p ++, highByte = *p ++; const uint16 externalValue = (uint16) ((uint16) highByte << 8) | (uint16) lowByte; my z [channel] [sample] = (int16) externalValue * factor; } } Loading @@ -244,21 +243,20 @@ autoEEG EEG_readFromBdfFile (MelderFile file) { } int numberOfStatusBits = 8; for (integer i = 1; i <= my nx; i ++) { uint32 value = (uint32) (int32) my z [numberOfChannels] [i]; if (value & 0x0000'FF00) { const uint32 value = (uint32) (int32) my z [numberOfChannels] [i]; if (value & 0x0000'FF00) numberOfStatusBits = 16; } } autoTextGrid thee; if (hasLetters) { thee = TextGrid_create (0, duration, U"Mark Trigger", U"Mark Trigger"); autoMelderString letters; double time = undefined; for (integer i = 1; i <= my nx; i ++) { uint32 value = (uint32) (int32) my z [numberOfChannels] [i]; const uint32 value = (uint32) (int32) my z [numberOfChannels] [i]; for (int ibyte = 1; ibyte <= numberOfStatusBits / 8; ibyte ++) { uint32 mask = ( ibyte == 1 ? 0x0000'00ff : 0x0000'ff00 ); char32 kar = ( ibyte == 1 ? (value & mask) : (value & mask) >> 8 ); const uint32 mask = ( ibyte == 1 ? 0x0000'00ff : 0x0000'ff00 ); const char32 kar = ( ibyte == 1 ? (value & mask) : (value & mask) >> 8 ); if (kar != U'\0' && kar != 20) { MelderString_appendCharacter (& letters, kar); } else if (letters. string [0] != U'\0') { Loading Loading @@ -307,13 +305,13 @@ autoEEG EEG_readFromBdfFile (MelderFile file) { U"" ); for (int bit = 1; bit <= numberOfStatusBits; bit ++) { uint32 bitValue = 1 << (bit - 1); const uint32 bitValue = 1 << (bit - 1); IntervalTier tier = (IntervalTier) thy tiers->at [bit]; for (integer i = 1; i <= my nx; i ++) { uint32 previousValue = i == 1 ? 0 : (uint32) (int32) my z [numberOfChannels] [i - 1]; uint32 thisValue = (uint32) (int32) my z [numberOfChannels] [i]; const uint32 previousValue = ( i == 1 ? 0 : (uint32) (int32) my z [numberOfChannels] [i - 1] ); const uint32 thisValue = (uint32) (int32) my z [numberOfChannels] [i]; if ((thisValue & bitValue) != (previousValue & bitValue)) { double time = i == 1 ? 0.0 : my x1 + (i - 1.5) * my dx; const double time = ( i == 1 ? 0.0 : my x1 + (i - 1.5) * my dx ); if (time != 0.0) TextGrid_insertBoundary (thee.get(), bit, time); if ((thisValue & bitValue) != 0) Loading Loading @@ -432,7 +430,7 @@ autoEEG EEG_readFromBdfFile (MelderFile file) { } static void detrend (VEC const& channel) { double firstValue = channel [1], lastValue = channel [channel.size]; const double firstValue = channel [1], lastValue = channel [channel.size]; channel [1] = channel [channel.size] = 0.0; for (integer isamp = 2; isamp < channel.size; isamp ++) channel [isamp] -= ((isamp - 1.0) * lastValue + (channel.size - isamp) * firstValue) / (channel.size - 1); Loading Loading @@ -529,7 +527,7 @@ void EEG_setChannelToZero (EEG me, integer channelNumber) { void EEG_setChannelToZero (EEG me, conststring32 channelName) { try { integer channelNumber = EEG_getChannelNumber (me, channelName); const integer channelNumber = EEG_getChannelNumber (me, channelName); if (channelNumber == 0) Melder_throw (U"No channel named \"", channelName, U"\"."); EEG_setChannelToZero (me, channelNumber); Loading @@ -554,7 +552,7 @@ autoEEG EEG_extractChannel (EEG me, integer channelNumber) { Melder_throw (U"No channel ", channelNumber, U"."); autoEEG thee = EEG_create (my xmin, my xmax); thy numberOfChannels = 1; thy channelNames = autostring32vector (1); thy channelNames = autoSTRVEC (1); thy channelNames [1] = Melder_dup (my channelNames [1].get()); thy sound = Sound_extractChannel (my sound.get(), channelNumber); thy textgrid = Data_copy (my textgrid.get()); Loading @@ -566,7 +564,7 @@ autoEEG EEG_extractChannel (EEG me, integer channelNumber) { autoEEG EEG_extractChannel (EEG me, conststring32 channelName) { try { integer channelNumber = EEG_getChannelNumber (me, channelName); const integer channelNumber = EEG_getChannelNumber (me, channelName); if (channelNumber == 0) Melder_throw (U"No channel named \"", channelName, U"\"."); return EEG_extractChannel (me, channelNumber); Loading @@ -577,15 +575,15 @@ autoEEG EEG_extractChannel (EEG me, conststring32 channelName) { autoEEG EEG_extractChannels (EEG me, constVECVU const& channelNumbers) { try { integer numberOfChannels = channelNumbers.size; const integer numberOfChannels = channelNumbers.size; Melder_require (numberOfChannels > 0, U"The number of channels should be greater than 0."); autoEEG you = EEG_create (my xmin, my xmax); your sound = Sound_extractChannels (my sound.get(), channelNumbers); your numberOfChannels = numberOfChannels; your channelNames = autostring32vector (numberOfChannels); your channelNames = autoSTRVEC (numberOfChannels); for (integer ichan = 1; ichan <= numberOfChannels; ichan ++) { integer originalChannelNumber = Melder_iround (channelNumbers [ichan]); const integer originalChannelNumber = Melder_iround (channelNumbers [ichan]); your channelNames [ichan] = Melder_dup (my channelNames [originalChannelNumber].get()); } your textgrid = Data_copy (my textgrid.get()); Loading Loading @@ -614,9 +612,8 @@ void EEG_removeChannel (EEG me, integer channelNumber) { try { if (channelNumber < 1 || channelNumber > my numberOfChannels) Melder_throw (U"No channel ", channelNumber, U"."); for (integer ichan = channelNumber; ichan < my numberOfChannels; ichan ++) { for (integer ichan = channelNumber; ichan < my numberOfChannels; ichan ++) my channelNames [ichan] = my channelNames [ichan + 1].move(); } my channelNames [my numberOfChannels]. reset(); my numberOfChannels -= 1; Sound_removeChannel (my sound.get(), channelNumber); Loading @@ -627,7 +624,7 @@ void EEG_removeChannel (EEG me, integer channelNumber) { void EEG_removeChannel (EEG me, conststring32 channelName) { try { integer channelNumber = EEG_getChannelNumber (me, channelName); const integer channelNumber = EEG_getChannelNumber (me, channelName); if (channelNumber == 0) Melder_throw (U"No channel named \"", channelName, U"\"."); EEG_removeChannel (me, channelNumber); Loading @@ -641,8 +638,8 @@ autoEEG EEGs_concatenate (OrderedOf<structEEG>* me) { if (my size < 1) Melder_throw (U"Cannot concatenate zero EEG objects."); EEG first = my at [1]; integer numberOfChannels = first -> numberOfChannels; autostring32vector channelNames = newSTRVECcopy (first -> channelNames.get()); const integer numberOfChannels = first -> numberOfChannels; autoSTRVEC channelNames = newSTRVECcopy (first -> channelNames.get()); for (integer ieeg = 2; ieeg <= my size; ieeg ++) { EEG other = my at [ieeg]; if (other -> numberOfChannels != numberOfChannels) Loading FFNet/FFNet.cpp +35 −24 Original line number Diff line number Diff line Loading @@ -77,7 +77,8 @@ autostring32 FFNet_createNameFromTopology (FFNet me) { static double sigmoid (FFNet /*me*/, double x, double *out_deriv) { const double act = NUMsigmoid (x); if (out_deriv) *out_deriv = act * (1.0 - act); if (out_deriv) *out_deriv = act * (1.0 - act); return act; } Loading Loading @@ -111,7 +112,6 @@ static double minimumCrossEntropy (FFNet me, constVEC& target) { for (integer i = 1; i <= my numberOfOutputs; i ++, k ++) { const double t1 = 1.0 - target [i]; const double o1 = 1.0 - my activity [k]; cost -= target [i] * log (my activity [k]) + t1 * log (o1); my error [k] = -t1 / o1 + target [i] / my activity [k]; } Loading @@ -134,8 +134,9 @@ static void bookkeeping (FFNet me) { U"Number of weights is incorrect."); my numberOfWeights = numberOfWeights; // The following test is essential because when an FFNet is read from file the w array already exists /* The following test is essential because when an FFNet is read from file the w array already exists */ if (! my w.at) my w = newVECzero (my numberOfWeights); Loading Loading @@ -257,7 +258,8 @@ void FFNet_setCostFunction (FFNet me, int costType) { double FFNet_getBias (FFNet me, integer layer, integer unit) { try { const integer node = FFNet_getNodeNumberFromUnitNumber (me, unit, layer); Melder_require (node > 0, U"Not a valid unit / layer combination."); Melder_require (node > 0, U"Not a valid unit / layer combination."); const integer bias_unit = my wLast [node]; return my w [bias_unit]; } catch (MelderError) { Loading Loading @@ -312,7 +314,7 @@ void FFNet_reset (FFNet me, double weightRange) { conststring32 FFNet_getCategoryOfOutputUnit (FFNet me, integer outputUnit) { conststring32 result = U"-- undefined --"; if (my outputCategories && outputUnit <= my outputCategories -> size) { SimpleString ss = my outputCategories->at [outputUnit]; const SimpleString ss = my outputCategories->at [outputUnit]; result = ss -> string.get(); } return result; Loading @@ -322,7 +324,7 @@ integer FFNet_getOutputUnitOfCategory (FFNet me, const char32* category) { integer result = 0; if (my outputCategories) { for (integer i = 1; i <= my outputCategories -> size; i ++) { SimpleString s = my outputCategories->at [i]; const SimpleString s = my outputCategories->at [i]; if (Melder_equ (s -> string.get(), category)) { result = i; break; Loading @@ -336,11 +338,15 @@ integer FFNet_getOutputUnitOfCategory (FFNet me, const char32* category) { /* step 1 */ void FFNet_propagate (FFNet me, constVEC input, autoVEC *output) { Melder_assert (my numberOfInputs == input.size); // clamp input pattern on the network /* Clamp input pattern on the network */ my activity.part (1, my numberOfInputs) <<= input; // on hidden units use activation function integer k = 1, numberOfNodes = my outputsAreLinear ? my numberOfNodes - my numberOfOutputs : my numberOfNodes; /* On hidden units use activation function */ const integer numberOfNodes = my outputsAreLinear ? my numberOfNodes - my numberOfOutputs : my numberOfNodes; integer k = 1; for (integer i = my numberOfInputs + 2; i <= numberOfNodes; i ++) { if (my isbias [i]) continue; Loading @@ -350,7 +356,9 @@ void FFNet_propagate (FFNet me, constVEC input, autoVEC *output) { my activity [i] = my nonLinearity (me, act, & my deriv [i]); } // on output units use another activation function /* On output units use another activation function */ if (my outputsAreLinear) { for (integer i = numberOfNodes + 1; i <= my numberOfNodes; i ++) { if (my isbias [i]) Loading @@ -373,12 +381,15 @@ void FFNet_propagate (FFNet me, constVEC input, autoVEC *output) { double FFNet_computeError (FFNet me, constVEC target) { Melder_assert (my numberOfOutputs == target.size); // compute error at output layer /* Compute error at output layer */ const double cost = my costFunction (me, target); for (integer i = 1; i <= my numberOfNodes - my numberOfOutputs; i ++) my error [i] = 0.0; // backpropagation of errors from output to first hidden layer /* Backpropagation of errors from output to first hidden layer */ for (integer i = my numberOfNodes; i > my numberOfInputs + 1; i--) { if (my isbias [i]) continue; Loading @@ -395,12 +406,11 @@ double FFNet_computeError (FFNet me, constVEC target) { void FFNet_computeDerivative (FFNet me) { integer k = 1; for (integer i = my numberOfInputs + 2; i <= my numberOfNodes; i ++) { for (integer i = my numberOfInputs + 2; i <= my numberOfNodes; i ++) if (! my isbias [i]) for (integer node = my nodeFirst [i]; node <= my nodeLast [i]; node ++, k ++) my dwi [k] = - my error [i] * my activity [node]; } } /******* end operation ******************************************************/ Loading @@ -413,10 +423,9 @@ integer FFNet_getWinningUnit (FFNet me, integer labeling) { sum += my activity [k + ioutput]; const double random = NUMrandomUniform (0.0, sum); for (winningUnit = my numberOfOutputs; winningUnit >= 2; winningUnit--) { for (winningUnit = my numberOfOutputs; winningUnit >= 2; winningUnit--) if (random > (sum -= my activity [k + winningUnit])) break; } } else { /* winner-takes-all */ double max = my activity [k + 1]; for (integer ioutput = 2; ioutput <= my numberOfOutputs; ioutput ++) Loading Loading @@ -546,7 +555,9 @@ void FFNet_drawTopology (FFNet me, Graphics g) { const double y2WC = dy / 2 + layer * dy; double dx2 = dx, x2WC; double x2 = (maxNumOfUnits - numberOfUnitsInLayer + 1) * dx2 / 2; /* draw the units */ /* Draw the units */ if (! dxIsFixed) { dx2 = 1.0 / numberOfUnitsInLayer; x2 = dx2 / 2.0; Loading Loading @@ -629,8 +640,8 @@ void FFNet_drawActivation (FFNet me, Graphics g) { } x2WC = x2; for (integer iunit = 1; iunit <= numberOfUnitsInLayer; iunit ++, node ++) { double activity = my activity [node]; double radius = r1 * (fabs (activity) < 0.05 ? 0.05 : fabs (activity)); const double activity = my activity [node]; const double radius = r1 * (fabs (activity) < 0.05 ? 0.05 : fabs (activity)); /*Graphics_setColour (g, activity < 0 ? Melder_BLACK : Melder_RED);*/ Graphics_circle (g, x2WC, y2WC, radius); if (activity < 0) Loading FFNet/FFNet_ActivationList_Categories.cpp +7 −8 Original line number Diff line number Diff line Loading @@ -28,10 +28,9 @@ static integer winnerTakesAll (FFNet me, constVEC activation) { integer pos = 1; double max = activation[1]; for (integer i = 2; i <= my numberOfOutputs; i ++) { for (integer i = 2; i <= my numberOfOutputs; i ++) if (activation [i] > max) max = activation [pos = i]; } return pos; } Loading @@ -43,7 +42,8 @@ static integer stochastic (FFNet me, constVEC activation) { const double number = NUMrandomUniform (0.0, range); for (i = 1; i <= my numberOfOutputs; i ++) { lower += activation [i]; if (number < lower) break; if (number < lower) break; } return i; } Loading Loading @@ -74,17 +74,16 @@ autoActivationList FFNet_Categories_to_ActivationList (FFNet me, Categories thee autoCategories uniq = Categories_selectUniqueItems (thee); Melder_require (my outputCategories, U"The FFNet does not have categories."); const integer nl = OrderedOfString_isSubsetOf (uniq.get(), my outputCategories.get(), 0); Melder_require (nl > 0, U"The Categories should match the categories of the FFNet."); autoActivationList him = ActivationList_create (thy size, my numberOfOutputs); for (integer i = 1; i <= thy size; i ++) { SimpleString category = thy at [i]; const SimpleString category = thy at [i]; const integer pos = OrderedOfString_indexOfItem_c (my outputCategories.get(), category -> string.get()); if (pos < 1) Melder_throw (U"The FFNet doesn't know the category ", category -> string.get(), U"."); Melder_require (pos > 0, U"The FFNet doesn't know the category ", category -> string.get(), U"."); his z [i] [pos] = 1.0; } return him; Loading FFNet/FFNet_Eigen.cpp +6 −10 Original line number Diff line number Diff line Loading @@ -50,28 +50,26 @@ void FFNet_Eigen_drawIntersection (FFNet me, Eigen eigen, Graphics g, integer pc Graphics_setWindow (g, xmin, xmax, ymin, ymax); for (integer i = 1; i <= my numberOfUnitsInLayer [1]; i ++) { const integer unitOffset = my numberOfInputs + 1; const double bias = my w [my wLast [unitOffset + i]]; double c1 = 0.0, c2 = 0.0; double x [6], y [6], xs [3], ys [3]; integer ns = 0; for (integer j = 1; j <= my numberOfInputs; j ++) { c1 += my w [my wFirst [unitOffset + i] + j - 1] * eigen -> eigenvectors [ix] [j]; c2 += my w [my wFirst [unitOffset + i] + j - 1] * eigen -> eigenvectors [iy] [j]; } double x [6], y [6], xs [3], ys [3]; x [1] = x [2] = x [5] = xmin; x [3] = x [4] = xmax; y [1] = y [4] = y [5] = ymin; y [2] = y [3] = ymax; integer ns = 0; const double bias = my w [my wLast [unitOffset + i]]; for (integer j = 1; j <= 4; j++) { const double p1 = c1 * x [j] + c2 * y [j] + bias; const double p2 = c1 * x [j + 1] + c2 * y [j + 1] + bias; const double r = fabs (p1) / (fabs (p1) + fabs (p2)); if (p1 *p2 > 0 || r == 0.0) continue; if (++ ns > 2) break; xs [ns] = x [j] + (x [j + 1] - x [j]) * r; ys [ns] = y [j] + (y [j + 1] - y [j]) * r; } Loading @@ -88,8 +86,7 @@ void FFNet_Eigen_drawIntersection (FFNet me, Eigen eigen, Graphics g, integer pc from layer j with the plane spanned by eigenvectors pcx and pcy. */ void FFNet_Eigen_drawDecisionPlaneInEigenspace (FFNet me, Eigen thee, Graphics g, integer unit, integer layer, integer pcx, integer pcy, double xmin, double xmax, double ymin, double ymax) { integer pcx, integer pcy, double xmin, double xmax, double ymin, double ymax) { if (layer < 1 || layer > my numberOfLayers) return; if (unit < 1 || unit > my numberOfUnitsInLayer [layer]) Loading @@ -100,7 +97,6 @@ void FFNet_Eigen_drawDecisionPlaneInEigenspace (FFNet me, Eigen thee, Graphics g if (numberOfUnitsInLayer_m1 != thy dimension) return; double x1, x2, y1, y2; Graphics_inqWindow (g, & x1, & x2, & y1, & y2); if (xmax <= xmin) { Loading Loading @@ -169,7 +165,7 @@ void FFNet_Eigen_drawDecisionPlaneInEigenspace (FFNet me, Eigen thee, Graphics g "for unit ", unit, U" in layer ", layer, U" with the plane spanned by the eigenvectors because \nboth planes are parallel."); return; } double xi [3], yi [3]; /* Intersections */ double xi [3], yi [3]; // Intersections const double ni = NUMgetIntersectionsWithRectangle (x1, y1, x2, y2, xmin, ymin, xmax, ymax, xi, yi); if (ni == 2) Graphics_line (g, xi [1], yi [1], xi [2], yi [2]); Loading FFNet/FFNet_PatternList_ActivationList.cpp +28 −26 File changed.Preview size limit exceeded, changes collapsed. Show changes Loading
EEG/EEG.cpp +45 −48 Original line number Diff line number Diff line Loading @@ -86,10 +86,9 @@ autoEEG EEG_create (double tmin, double tmax) { } integer EEG_getChannelNumber (EEG me, conststring32 channelName) { for (integer ichan = 1; ichan <= my numberOfChannels; ichan ++) { for (integer ichan = 1; ichan <= my numberOfChannels; ichan ++) if (Melder_equ (my channelNames [ichan].get(), channelName)) return ichan; } return 0; } Loading @@ -99,7 +98,7 @@ autoEEG EEG_readFromBdfFile (MelderFile file) { char buffer [81]; fread (buffer, 1, 8, f); buffer [8] = '\0'; bool is24bit = buffer [0] == (char) 255; const bool is24bit = ( buffer [0] == (char) 255 ); fread (buffer, 1, 80, f); buffer [80] = '\0'; trace (U"Local subject identification: \"", Melder_peek8to32 (buffer), U"\""); Loading @@ -114,27 +113,27 @@ autoEEG EEG_readFromBdfFile (MelderFile file) { trace (U"Start time of recording: \"", Melder_peek8to32 (buffer), U"\""); fread (buffer, 1, 8, f); buffer [8] = '\0'; integer numberOfBytesInHeaderRecord = atol (buffer); const integer numberOfBytesInHeaderRecord = atol (buffer); trace (U"Number of bytes in header record: ", numberOfBytesInHeaderRecord); fread (buffer, 1, 44, f); buffer [44] = '\0'; trace (U"Version of data format: \"", Melder_peek8to32 (buffer), U"\""); fread (buffer, 1, 8, f); buffer [8] = '\0'; integer numberOfDataRecords = strtol (buffer, nullptr, 10); const integer numberOfDataRecords = strtol (buffer, nullptr, 10); trace (U"Number of data records: ", numberOfDataRecords); fread (buffer, 1, 8, f); buffer [8] = '\0'; double durationOfDataRecord = atof (buffer); const double durationOfDataRecord = atof (buffer); trace (U"Duration of a data record: ", durationOfDataRecord); fread (buffer, 1, 4, f); buffer [4] = '\0'; integer numberOfChannels = atol (buffer); const integer numberOfChannels = atol (buffer); trace (U"Number of channels in data record: ", numberOfChannels); if (numberOfBytesInHeaderRecord != (numberOfChannels + 1) * 256) Melder_throw (U"Number of bytes in header record (", numberOfBytesInHeaderRecord, U") doesn't match number of channels (", numberOfChannels, U")."); autostring32vector channelNames (numberOfChannels); autoSTRVEC channelNames (numberOfChannels); for (integer ichannel = 1; ichannel <= numberOfChannels; ichannel ++) { fread (buffer, 1, 16, f); buffer [16] = '\0'; // labels of the channels Loading @@ -142,16 +141,15 @@ autoEEG EEG_readFromBdfFile (MelderFile file) { * Strip all final spaces. */ for (int i = 15; i >= 0; i --) { if (buffer [i] == ' ') { if (buffer [i] == ' ') buffer [i] = '\0'; } else { else break; } } channelNames [ichannel] = Melder_8to32 (buffer); trace (U"Channel <<", channelNames [ichannel].get(), U">>"); } bool hasLetters = str32equ (channelNames [numberOfChannels].get(), U"EDF Annotations"); const bool hasLetters = str32equ (channelNames [numberOfChannels].get(), U"EDF Annotations"); double samplingFrequency = undefined; for (integer channel = 1; channel <= numberOfChannels; channel ++) { fread (buffer, 1, 80, f); Loading Loading @@ -193,7 +191,7 @@ autoEEG EEG_readFromBdfFile (MelderFile file) { for (integer channel = 1; channel <= numberOfChannels; channel ++) { fread (buffer, 1, 8, f); buffer [8] = '\0'; // number of samples in each data record integer numberOfSamplesInThisDataRecord = atol (buffer); const integer numberOfSamplesInThisDataRecord = atol (buffer); if (isundef (samplingFrequency)) { numberOfSamplesPerDataRecord = numberOfSamplesInThisDataRecord; samplingFrequency = numberOfSamplesInThisDataRecord / durationOfDataRecord; Loading @@ -207,36 +205,37 @@ autoEEG EEG_readFromBdfFile (MelderFile file) { fread (buffer, 1, 32, f); buffer [32] = '\0'; // reserved } double duration = numberOfDataRecords * durationOfDataRecord; const double duration = numberOfDataRecords * durationOfDataRecord; autoEEG him = EEG_create (0, duration); his numberOfChannels = numberOfChannels; autoSound me = Sound_createSimple (numberOfChannels, duration, samplingFrequency); Melder_assert (my nx == numberOfSamplesPerDataRecord * numberOfDataRecords); autoNUMvector <uint8> dataBuffer ((integer) 0, 3 * numberOfSamplesPerDataRecord - 1); autoBYTEVEC dataBuffer = newBYTEVECzero (3 * numberOfSamplesPerDataRecord); for (integer record = 1; record <= numberOfDataRecords; record ++) { for (integer channel = 1; channel <= numberOfChannels; channel ++) { double factor = channel == numberOfChannels ? 1.0 : physicalMinimum [channel] / digitalMinimum [channel]; if (channel < numberOfChannels - EEG_getNumberOfExtraSensors (him.get())) factor /= 1000000.0; double factor = ( channel == numberOfChannels ? 1.0 : physicalMinimum [channel] / digitalMinimum [channel] ); if (channel < numberOfChannels - EEG_getNumberOfExtraSensors (him.get())) factor /= 1000000.0; if (is24bit) { fread (& dataBuffer [0], 3, (size_t) numberOfSamplesPerDataRecord, f); uint8 *p = & dataBuffer [0]; fread (dataBuffer.asArgumentToFunctionThatExpectsZeroBasedArray(), 3, (size_t) numberOfSamplesPerDataRecord, f); byte *p = & dataBuffer [1]; for (integer i = 1; i <= numberOfSamplesPerDataRecord; i ++) { integer sample = i + (record - 1) * numberOfSamplesPerDataRecord; const integer sample = i + (record - 1) * numberOfSamplesPerDataRecord; Melder_assert (sample <= my nx); uint8 lowByte = *p ++, midByte = *p ++, highByte = *p ++; const uint8 lowByte = *p ++, midByte = *p ++, highByte = *p ++; uint32 externalValue = ((uint32) highByte << 16) | ((uint32) midByte << 8) | (uint32) lowByte; if ((highByte & 128) != 0) // is the 24-bit sign bit on? externalValue |= 0xFF00'0000; // extend negative sign to 32 bits my z [channel] [sample] = (int32) externalValue * factor; } } else { fread (& dataBuffer [0], 2, (size_t) numberOfSamplesPerDataRecord, f); uint8 *p = & dataBuffer [0]; fread (dataBuffer.asArgumentToFunctionThatExpectsZeroBasedArray(), 2, (size_t) numberOfSamplesPerDataRecord, f); byte *p = & dataBuffer [1]; for (integer i = 1; i <= numberOfSamplesPerDataRecord; i ++) { integer sample = i + (record - 1) * numberOfSamplesPerDataRecord; const integer sample = i + (record - 1) * numberOfSamplesPerDataRecord; Melder_assert (sample <= my nx); uint8 lowByte = *p ++, highByte = *p ++; uint16 externalValue = (uint16) ((uint16) highByte << 8) | (uint16) lowByte; const uint8 lowByte = *p ++, highByte = *p ++; const uint16 externalValue = (uint16) ((uint16) highByte << 8) | (uint16) lowByte; my z [channel] [sample] = (int16) externalValue * factor; } } Loading @@ -244,21 +243,20 @@ autoEEG EEG_readFromBdfFile (MelderFile file) { } int numberOfStatusBits = 8; for (integer i = 1; i <= my nx; i ++) { uint32 value = (uint32) (int32) my z [numberOfChannels] [i]; if (value & 0x0000'FF00) { const uint32 value = (uint32) (int32) my z [numberOfChannels] [i]; if (value & 0x0000'FF00) numberOfStatusBits = 16; } } autoTextGrid thee; if (hasLetters) { thee = TextGrid_create (0, duration, U"Mark Trigger", U"Mark Trigger"); autoMelderString letters; double time = undefined; for (integer i = 1; i <= my nx; i ++) { uint32 value = (uint32) (int32) my z [numberOfChannels] [i]; const uint32 value = (uint32) (int32) my z [numberOfChannels] [i]; for (int ibyte = 1; ibyte <= numberOfStatusBits / 8; ibyte ++) { uint32 mask = ( ibyte == 1 ? 0x0000'00ff : 0x0000'ff00 ); char32 kar = ( ibyte == 1 ? (value & mask) : (value & mask) >> 8 ); const uint32 mask = ( ibyte == 1 ? 0x0000'00ff : 0x0000'ff00 ); const char32 kar = ( ibyte == 1 ? (value & mask) : (value & mask) >> 8 ); if (kar != U'\0' && kar != 20) { MelderString_appendCharacter (& letters, kar); } else if (letters. string [0] != U'\0') { Loading Loading @@ -307,13 +305,13 @@ autoEEG EEG_readFromBdfFile (MelderFile file) { U"" ); for (int bit = 1; bit <= numberOfStatusBits; bit ++) { uint32 bitValue = 1 << (bit - 1); const uint32 bitValue = 1 << (bit - 1); IntervalTier tier = (IntervalTier) thy tiers->at [bit]; for (integer i = 1; i <= my nx; i ++) { uint32 previousValue = i == 1 ? 0 : (uint32) (int32) my z [numberOfChannels] [i - 1]; uint32 thisValue = (uint32) (int32) my z [numberOfChannels] [i]; const uint32 previousValue = ( i == 1 ? 0 : (uint32) (int32) my z [numberOfChannels] [i - 1] ); const uint32 thisValue = (uint32) (int32) my z [numberOfChannels] [i]; if ((thisValue & bitValue) != (previousValue & bitValue)) { double time = i == 1 ? 0.0 : my x1 + (i - 1.5) * my dx; const double time = ( i == 1 ? 0.0 : my x1 + (i - 1.5) * my dx ); if (time != 0.0) TextGrid_insertBoundary (thee.get(), bit, time); if ((thisValue & bitValue) != 0) Loading Loading @@ -432,7 +430,7 @@ autoEEG EEG_readFromBdfFile (MelderFile file) { } static void detrend (VEC const& channel) { double firstValue = channel [1], lastValue = channel [channel.size]; const double firstValue = channel [1], lastValue = channel [channel.size]; channel [1] = channel [channel.size] = 0.0; for (integer isamp = 2; isamp < channel.size; isamp ++) channel [isamp] -= ((isamp - 1.0) * lastValue + (channel.size - isamp) * firstValue) / (channel.size - 1); Loading Loading @@ -529,7 +527,7 @@ void EEG_setChannelToZero (EEG me, integer channelNumber) { void EEG_setChannelToZero (EEG me, conststring32 channelName) { try { integer channelNumber = EEG_getChannelNumber (me, channelName); const integer channelNumber = EEG_getChannelNumber (me, channelName); if (channelNumber == 0) Melder_throw (U"No channel named \"", channelName, U"\"."); EEG_setChannelToZero (me, channelNumber); Loading @@ -554,7 +552,7 @@ autoEEG EEG_extractChannel (EEG me, integer channelNumber) { Melder_throw (U"No channel ", channelNumber, U"."); autoEEG thee = EEG_create (my xmin, my xmax); thy numberOfChannels = 1; thy channelNames = autostring32vector (1); thy channelNames = autoSTRVEC (1); thy channelNames [1] = Melder_dup (my channelNames [1].get()); thy sound = Sound_extractChannel (my sound.get(), channelNumber); thy textgrid = Data_copy (my textgrid.get()); Loading @@ -566,7 +564,7 @@ autoEEG EEG_extractChannel (EEG me, integer channelNumber) { autoEEG EEG_extractChannel (EEG me, conststring32 channelName) { try { integer channelNumber = EEG_getChannelNumber (me, channelName); const integer channelNumber = EEG_getChannelNumber (me, channelName); if (channelNumber == 0) Melder_throw (U"No channel named \"", channelName, U"\"."); return EEG_extractChannel (me, channelNumber); Loading @@ -577,15 +575,15 @@ autoEEG EEG_extractChannel (EEG me, conststring32 channelName) { autoEEG EEG_extractChannels (EEG me, constVECVU const& channelNumbers) { try { integer numberOfChannels = channelNumbers.size; const integer numberOfChannels = channelNumbers.size; Melder_require (numberOfChannels > 0, U"The number of channels should be greater than 0."); autoEEG you = EEG_create (my xmin, my xmax); your sound = Sound_extractChannels (my sound.get(), channelNumbers); your numberOfChannels = numberOfChannels; your channelNames = autostring32vector (numberOfChannels); your channelNames = autoSTRVEC (numberOfChannels); for (integer ichan = 1; ichan <= numberOfChannels; ichan ++) { integer originalChannelNumber = Melder_iround (channelNumbers [ichan]); const integer originalChannelNumber = Melder_iround (channelNumbers [ichan]); your channelNames [ichan] = Melder_dup (my channelNames [originalChannelNumber].get()); } your textgrid = Data_copy (my textgrid.get()); Loading Loading @@ -614,9 +612,8 @@ void EEG_removeChannel (EEG me, integer channelNumber) { try { if (channelNumber < 1 || channelNumber > my numberOfChannels) Melder_throw (U"No channel ", channelNumber, U"."); for (integer ichan = channelNumber; ichan < my numberOfChannels; ichan ++) { for (integer ichan = channelNumber; ichan < my numberOfChannels; ichan ++) my channelNames [ichan] = my channelNames [ichan + 1].move(); } my channelNames [my numberOfChannels]. reset(); my numberOfChannels -= 1; Sound_removeChannel (my sound.get(), channelNumber); Loading @@ -627,7 +624,7 @@ void EEG_removeChannel (EEG me, integer channelNumber) { void EEG_removeChannel (EEG me, conststring32 channelName) { try { integer channelNumber = EEG_getChannelNumber (me, channelName); const integer channelNumber = EEG_getChannelNumber (me, channelName); if (channelNumber == 0) Melder_throw (U"No channel named \"", channelName, U"\"."); EEG_removeChannel (me, channelNumber); Loading @@ -641,8 +638,8 @@ autoEEG EEGs_concatenate (OrderedOf<structEEG>* me) { if (my size < 1) Melder_throw (U"Cannot concatenate zero EEG objects."); EEG first = my at [1]; integer numberOfChannels = first -> numberOfChannels; autostring32vector channelNames = newSTRVECcopy (first -> channelNames.get()); const integer numberOfChannels = first -> numberOfChannels; autoSTRVEC channelNames = newSTRVECcopy (first -> channelNames.get()); for (integer ieeg = 2; ieeg <= my size; ieeg ++) { EEG other = my at [ieeg]; if (other -> numberOfChannels != numberOfChannels) Loading
FFNet/FFNet.cpp +35 −24 Original line number Diff line number Diff line Loading @@ -77,7 +77,8 @@ autostring32 FFNet_createNameFromTopology (FFNet me) { static double sigmoid (FFNet /*me*/, double x, double *out_deriv) { const double act = NUMsigmoid (x); if (out_deriv) *out_deriv = act * (1.0 - act); if (out_deriv) *out_deriv = act * (1.0 - act); return act; } Loading Loading @@ -111,7 +112,6 @@ static double minimumCrossEntropy (FFNet me, constVEC& target) { for (integer i = 1; i <= my numberOfOutputs; i ++, k ++) { const double t1 = 1.0 - target [i]; const double o1 = 1.0 - my activity [k]; cost -= target [i] * log (my activity [k]) + t1 * log (o1); my error [k] = -t1 / o1 + target [i] / my activity [k]; } Loading @@ -134,8 +134,9 @@ static void bookkeeping (FFNet me) { U"Number of weights is incorrect."); my numberOfWeights = numberOfWeights; // The following test is essential because when an FFNet is read from file the w array already exists /* The following test is essential because when an FFNet is read from file the w array already exists */ if (! my w.at) my w = newVECzero (my numberOfWeights); Loading Loading @@ -257,7 +258,8 @@ void FFNet_setCostFunction (FFNet me, int costType) { double FFNet_getBias (FFNet me, integer layer, integer unit) { try { const integer node = FFNet_getNodeNumberFromUnitNumber (me, unit, layer); Melder_require (node > 0, U"Not a valid unit / layer combination."); Melder_require (node > 0, U"Not a valid unit / layer combination."); const integer bias_unit = my wLast [node]; return my w [bias_unit]; } catch (MelderError) { Loading Loading @@ -312,7 +314,7 @@ void FFNet_reset (FFNet me, double weightRange) { conststring32 FFNet_getCategoryOfOutputUnit (FFNet me, integer outputUnit) { conststring32 result = U"-- undefined --"; if (my outputCategories && outputUnit <= my outputCategories -> size) { SimpleString ss = my outputCategories->at [outputUnit]; const SimpleString ss = my outputCategories->at [outputUnit]; result = ss -> string.get(); } return result; Loading @@ -322,7 +324,7 @@ integer FFNet_getOutputUnitOfCategory (FFNet me, const char32* category) { integer result = 0; if (my outputCategories) { for (integer i = 1; i <= my outputCategories -> size; i ++) { SimpleString s = my outputCategories->at [i]; const SimpleString s = my outputCategories->at [i]; if (Melder_equ (s -> string.get(), category)) { result = i; break; Loading @@ -336,11 +338,15 @@ integer FFNet_getOutputUnitOfCategory (FFNet me, const char32* category) { /* step 1 */ void FFNet_propagate (FFNet me, constVEC input, autoVEC *output) { Melder_assert (my numberOfInputs == input.size); // clamp input pattern on the network /* Clamp input pattern on the network */ my activity.part (1, my numberOfInputs) <<= input; // on hidden units use activation function integer k = 1, numberOfNodes = my outputsAreLinear ? my numberOfNodes - my numberOfOutputs : my numberOfNodes; /* On hidden units use activation function */ const integer numberOfNodes = my outputsAreLinear ? my numberOfNodes - my numberOfOutputs : my numberOfNodes; integer k = 1; for (integer i = my numberOfInputs + 2; i <= numberOfNodes; i ++) { if (my isbias [i]) continue; Loading @@ -350,7 +356,9 @@ void FFNet_propagate (FFNet me, constVEC input, autoVEC *output) { my activity [i] = my nonLinearity (me, act, & my deriv [i]); } // on output units use another activation function /* On output units use another activation function */ if (my outputsAreLinear) { for (integer i = numberOfNodes + 1; i <= my numberOfNodes; i ++) { if (my isbias [i]) Loading @@ -373,12 +381,15 @@ void FFNet_propagate (FFNet me, constVEC input, autoVEC *output) { double FFNet_computeError (FFNet me, constVEC target) { Melder_assert (my numberOfOutputs == target.size); // compute error at output layer /* Compute error at output layer */ const double cost = my costFunction (me, target); for (integer i = 1; i <= my numberOfNodes - my numberOfOutputs; i ++) my error [i] = 0.0; // backpropagation of errors from output to first hidden layer /* Backpropagation of errors from output to first hidden layer */ for (integer i = my numberOfNodes; i > my numberOfInputs + 1; i--) { if (my isbias [i]) continue; Loading @@ -395,12 +406,11 @@ double FFNet_computeError (FFNet me, constVEC target) { void FFNet_computeDerivative (FFNet me) { integer k = 1; for (integer i = my numberOfInputs + 2; i <= my numberOfNodes; i ++) { for (integer i = my numberOfInputs + 2; i <= my numberOfNodes; i ++) if (! my isbias [i]) for (integer node = my nodeFirst [i]; node <= my nodeLast [i]; node ++, k ++) my dwi [k] = - my error [i] * my activity [node]; } } /******* end operation ******************************************************/ Loading @@ -413,10 +423,9 @@ integer FFNet_getWinningUnit (FFNet me, integer labeling) { sum += my activity [k + ioutput]; const double random = NUMrandomUniform (0.0, sum); for (winningUnit = my numberOfOutputs; winningUnit >= 2; winningUnit--) { for (winningUnit = my numberOfOutputs; winningUnit >= 2; winningUnit--) if (random > (sum -= my activity [k + winningUnit])) break; } } else { /* winner-takes-all */ double max = my activity [k + 1]; for (integer ioutput = 2; ioutput <= my numberOfOutputs; ioutput ++) Loading Loading @@ -546,7 +555,9 @@ void FFNet_drawTopology (FFNet me, Graphics g) { const double y2WC = dy / 2 + layer * dy; double dx2 = dx, x2WC; double x2 = (maxNumOfUnits - numberOfUnitsInLayer + 1) * dx2 / 2; /* draw the units */ /* Draw the units */ if (! dxIsFixed) { dx2 = 1.0 / numberOfUnitsInLayer; x2 = dx2 / 2.0; Loading Loading @@ -629,8 +640,8 @@ void FFNet_drawActivation (FFNet me, Graphics g) { } x2WC = x2; for (integer iunit = 1; iunit <= numberOfUnitsInLayer; iunit ++, node ++) { double activity = my activity [node]; double radius = r1 * (fabs (activity) < 0.05 ? 0.05 : fabs (activity)); const double activity = my activity [node]; const double radius = r1 * (fabs (activity) < 0.05 ? 0.05 : fabs (activity)); /*Graphics_setColour (g, activity < 0 ? Melder_BLACK : Melder_RED);*/ Graphics_circle (g, x2WC, y2WC, radius); if (activity < 0) Loading
FFNet/FFNet_ActivationList_Categories.cpp +7 −8 Original line number Diff line number Diff line Loading @@ -28,10 +28,9 @@ static integer winnerTakesAll (FFNet me, constVEC activation) { integer pos = 1; double max = activation[1]; for (integer i = 2; i <= my numberOfOutputs; i ++) { for (integer i = 2; i <= my numberOfOutputs; i ++) if (activation [i] > max) max = activation [pos = i]; } return pos; } Loading @@ -43,7 +42,8 @@ static integer stochastic (FFNet me, constVEC activation) { const double number = NUMrandomUniform (0.0, range); for (i = 1; i <= my numberOfOutputs; i ++) { lower += activation [i]; if (number < lower) break; if (number < lower) break; } return i; } Loading Loading @@ -74,17 +74,16 @@ autoActivationList FFNet_Categories_to_ActivationList (FFNet me, Categories thee autoCategories uniq = Categories_selectUniqueItems (thee); Melder_require (my outputCategories, U"The FFNet does not have categories."); const integer nl = OrderedOfString_isSubsetOf (uniq.get(), my outputCategories.get(), 0); Melder_require (nl > 0, U"The Categories should match the categories of the FFNet."); autoActivationList him = ActivationList_create (thy size, my numberOfOutputs); for (integer i = 1; i <= thy size; i ++) { SimpleString category = thy at [i]; const SimpleString category = thy at [i]; const integer pos = OrderedOfString_indexOfItem_c (my outputCategories.get(), category -> string.get()); if (pos < 1) Melder_throw (U"The FFNet doesn't know the category ", category -> string.get(), U"."); Melder_require (pos > 0, U"The FFNet doesn't know the category ", category -> string.get(), U"."); his z [i] [pos] = 1.0; } return him; Loading
FFNet/FFNet_Eigen.cpp +6 −10 Original line number Diff line number Diff line Loading @@ -50,28 +50,26 @@ void FFNet_Eigen_drawIntersection (FFNet me, Eigen eigen, Graphics g, integer pc Graphics_setWindow (g, xmin, xmax, ymin, ymax); for (integer i = 1; i <= my numberOfUnitsInLayer [1]; i ++) { const integer unitOffset = my numberOfInputs + 1; const double bias = my w [my wLast [unitOffset + i]]; double c1 = 0.0, c2 = 0.0; double x [6], y [6], xs [3], ys [3]; integer ns = 0; for (integer j = 1; j <= my numberOfInputs; j ++) { c1 += my w [my wFirst [unitOffset + i] + j - 1] * eigen -> eigenvectors [ix] [j]; c2 += my w [my wFirst [unitOffset + i] + j - 1] * eigen -> eigenvectors [iy] [j]; } double x [6], y [6], xs [3], ys [3]; x [1] = x [2] = x [5] = xmin; x [3] = x [4] = xmax; y [1] = y [4] = y [5] = ymin; y [2] = y [3] = ymax; integer ns = 0; const double bias = my w [my wLast [unitOffset + i]]; for (integer j = 1; j <= 4; j++) { const double p1 = c1 * x [j] + c2 * y [j] + bias; const double p2 = c1 * x [j + 1] + c2 * y [j + 1] + bias; const double r = fabs (p1) / (fabs (p1) + fabs (p2)); if (p1 *p2 > 0 || r == 0.0) continue; if (++ ns > 2) break; xs [ns] = x [j] + (x [j + 1] - x [j]) * r; ys [ns] = y [j] + (y [j + 1] - y [j]) * r; } Loading @@ -88,8 +86,7 @@ void FFNet_Eigen_drawIntersection (FFNet me, Eigen eigen, Graphics g, integer pc from layer j with the plane spanned by eigenvectors pcx and pcy. */ void FFNet_Eigen_drawDecisionPlaneInEigenspace (FFNet me, Eigen thee, Graphics g, integer unit, integer layer, integer pcx, integer pcy, double xmin, double xmax, double ymin, double ymax) { integer pcx, integer pcy, double xmin, double xmax, double ymin, double ymax) { if (layer < 1 || layer > my numberOfLayers) return; if (unit < 1 || unit > my numberOfUnitsInLayer [layer]) Loading @@ -100,7 +97,6 @@ void FFNet_Eigen_drawDecisionPlaneInEigenspace (FFNet me, Eigen thee, Graphics g if (numberOfUnitsInLayer_m1 != thy dimension) return; double x1, x2, y1, y2; Graphics_inqWindow (g, & x1, & x2, & y1, & y2); if (xmax <= xmin) { Loading Loading @@ -169,7 +165,7 @@ void FFNet_Eigen_drawDecisionPlaneInEigenspace (FFNet me, Eigen thee, Graphics g "for unit ", unit, U" in layer ", layer, U" with the plane spanned by the eigenvectors because \nboth planes are parallel."); return; } double xi [3], yi [3]; /* Intersections */ double xi [3], yi [3]; // Intersections const double ni = NUMgetIntersectionsWithRectangle (x1, y1, x2, y2, xmin, ymin, xmax, ymax, xi, yi); if (ni == 2) Graphics_line (g, xi [1], yi [1], xi [2], yi [2]); Loading
FFNet/FFNet_PatternList_ActivationList.cpp +28 −26 File changed.Preview size limit exceeded, changes collapsed. Show changes