Commit e5676709 authored by Rafael Laboissière's avatar Rafael Laboissière
Browse files

New upstream version 6.0.46

parent 0eafc4b2
Loading
Loading
Loading
Loading
+18 −24
Original line number Diff line number Diff line
@@ -409,18 +409,16 @@ autoEEG EEG_readFromBdfFile (MelderFile file) {
	}
}

static void detrend (double *a, integer numberOfSamples) {
	double firstValue = a [1], lastValue = a [numberOfSamples];
	a [1] = a [numberOfSamples] = 0.0;
	for (integer isamp = 2; isamp < numberOfSamples; isamp ++) {
		a [isamp] -= ((isamp - 1.0) * lastValue + (numberOfSamples - isamp) * firstValue) / (numberOfSamples - 1);
	}
static void detrend (VEC const& channel) {
	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);
}

void EEG_detrend (EEG me) {
	for (integer ichan = 1; ichan <= my numberOfChannels - EEG_getNumberOfExtraSensors (me); ichan ++) {
		detrend (my sound -> z [ichan], my sound -> nx);
	}
	for (integer ichan = 1; ichan <= my numberOfChannels - EEG_getNumberOfExtraSensors (me); ichan ++)
		detrend (my sound -> z.row (ichan));
}

void EEG_filter (EEG me, double lowFrequency, double lowWidth, double highFrequency, double highWidth, bool doNotch50Hz) {
@@ -441,7 +439,7 @@ void EEG_filter (EEG me, double lowFrequency, double lowWidth, double highFreque
				Spectrum_stopHannBand (spec.get(), 48.0, 52.0, 1.0);
			}
			autoSound him = Spectrum_to_Sound (spec.get());
			NUMvector_copyElements (his z [1], my sound -> z [ichan], 1, my sound -> nx);
			NUMvector_copyElements (& his z [1] [0], & my sound -> z [ichan] [0], 1, my sound -> nx);
		}
	} catch (MelderError) {
		Melder_throw (me, U": not filtered.");
@@ -496,25 +494,22 @@ void EEG_subtractMeanChannel (EEG me, integer fromChannel, integer toChannel) {
	const integer numberOfElectrodeChannels = my numberOfChannels - EEG_getNumberOfExtraSensors (me);
	for (integer isamp = 1; isamp <= my sound -> nx; isamp ++) {
		double referenceValue = 0.0;
		for (integer ichan = fromChannel; ichan <= toChannel; ichan ++) {
		for (integer ichan = fromChannel; ichan <= toChannel; ichan ++)
			referenceValue += my sound -> z [ichan] [isamp];
		}
		referenceValue /= (toChannel - fromChannel + 1);
		for (integer ichan = 1; ichan <= numberOfElectrodeChannels; ichan ++) {
		for (integer ichan = 1; ichan <= numberOfElectrodeChannels; ichan ++)
			my sound -> z [ichan] [isamp] -= referenceValue;
	}
}
}

void EEG_setChannelToZero (EEG me, integer channelNumber) {
	try {
		if (channelNumber < 1 || channelNumber > my numberOfChannels)
			Melder_throw (U"No channel ", channelNumber, U".");
		integer numberOfSamples = my sound -> nx;
		double *channel = my sound -> z [channelNumber];
		for (integer isample = 1; isample <= numberOfSamples; isample ++) {
		VEC channel = my sound -> z.row (channelNumber);
		for (integer isample = 1; isample <= numberOfSamples; isample ++)
			channel [isample] = 0.0;
		}
	} catch (MelderError) {
		Melder_throw (me, U": channel ", channelNumber, U" not set to zero.");
	}
@@ -594,9 +589,8 @@ static void Sound_removeChannel (Sound me, integer channelNumber) {
			U"No channel ", channelNumber, U".");
		Melder_require (my ny > 1,
			U"Cannot remove last remaining channel.");
		for (integer ichan = channelNumber; ichan < my ny; ichan ++) {
			NUMvector_copyElements (my z [ichan + 1], my z [ichan], 1, my nx);
		}
		for (integer ichan = channelNumber; ichan < my ny; ichan ++)
			NUMvector_copyElements (& my z [ichan + 1] [0], & my z [ichan] [0], 1, my nx);
		my ymax -= 1.0;
		my ny -= 1;
	} catch (MelderError) {
@@ -636,7 +630,7 @@ autoEEG EEGs_concatenate (OrderedOf<structEEG>* me) {
			Melder_throw (U"Cannot concatenate zero EEG objects.");
		EEG first = my at [1];
		integer numberOfChannels = first -> numberOfChannels;
		autostring32vector channelNames = STRVECclone (first -> channelNames.get());
		autostring32vector channelNames = newSTRVECcopy (first -> channelNames.get());
		for (integer ieeg = 2; ieeg <= my size; ieeg ++) {
			EEG other = my at [ieeg];
			if (other -> numberOfChannels != numberOfChannels)
@@ -671,7 +665,7 @@ autoEEG EEG_extractPart (EEG me, double tmin, double tmax, bool preserveTimes) {
	try {
		autoEEG thee = Thing_new (EEG);
		thy numberOfChannels = my numberOfChannels;
		thy channelNames = STRVECclone (my channelNames.get());
		thy channelNames = newSTRVECcopy (my channelNames.get());
		thy sound = Sound_extractPart (my sound.get(), tmin, tmax, kSound_windowShape::RECTANGULAR, 1.0, preserveTimes);
		thy textgrid = TextGrid_extractPart (my textgrid.get(), tmin, tmax, preserveTimes);
		thy xmin = thy textgrid -> xmin;
@@ -723,7 +717,7 @@ autoEEG EEG_MixingMatrix_to_EEG_unmix (EEG me, MixingMatrix you) {
	his sound = Sound_MixingMatrix_unmix (my sound.get(), you);
	his textgrid = Data_copy (my textgrid.get());
	his numberOfChannels = your numberOfColumns;
	his channelNames = STRVECclone (your columnLabels.get());
	his channelNames = newSTRVECcopy (your columnLabels.get());
	return him;
}

@@ -741,7 +735,7 @@ autoEEG EEG_MixingMatrix_to_EEG_mix (EEG me, MixingMatrix you) {
	his sound = Sound_MixingMatrix_mix (my sound.get(), you);
	his textgrid = Data_copy (my textgrid.get());
	his numberOfChannels = your numberOfRows;
	his channelNames = STRVECclone (your rowLabels.get());
	his channelNames = newSTRVECcopy (your rowLabels.get());
	return him;
}

+1 −1
Original line number Diff line number Diff line
@@ -78,7 +78,7 @@ void ERP_drawChannel_number (ERP me, Graphics graphics, integer channelNumber, d
	 */
	Graphics_setInner (graphics);
	Graphics_setWindow (graphics, tmin, tmax, vmin, vmax);
	Graphics_function (graphics, my z [channelNumber], ixmin, ixmax, Matrix_columnToX (me, ixmin), Matrix_columnToX (me, ixmax));
	Graphics_function (graphics, & my z [channelNumber] [0], ixmin, ixmax, Matrix_columnToX (me, ixmin), Matrix_columnToX (me, ixmax));
	Graphics_unsetInner (graphics);
	if (garnish) {
		Graphics_drawInnerBox (graphics);
+13 −34
Original line number Diff line number Diff line
@@ -70,7 +70,7 @@ static autoERPTier EEG_PointProcess_to_ERPTier (EEG me, PointProcess events, dou
		Function_init (thee.get(), fromTime, toTime);
		thy numberOfChannels = my numberOfChannels - EEG_getNumberOfExtraSensors (me);
		Melder_assert (thy numberOfChannels > 0);
		thy channelNames = STRVECclone (my channelNames.get());
		thy channelNames = newSTRVECcopy (my channelNames.get());
		integer numberOfEvents = events -> nt;
		double soundDuration = toTime - fromTime;
		double samplingPeriod = my sound -> dx;
@@ -191,7 +191,7 @@ void ERPTier_subtractBaseline (ERPTier me, double tmin, double tmax) {
		ERPPoint event = my points.at [ievent];
		for (integer ichannel = 1; ichannel <= numberOfChannels; ichannel ++) {
			double mean = Vector_getMean (event -> erp.get(), tmin, tmax, ichannel);
			double *channel = event -> erp -> z [ichannel];
			VEC channel = event -> erp -> z.row (ichannel);
			for (integer isample = 1; isample <= numberOfSamples; isample ++) {
				channel [isample] -= mean;
			}
@@ -213,7 +213,7 @@ void ERPTier_rejectArtefacts (ERPTier me, double threshold) {
		double minimum = event -> erp -> z [1] [1];
		double maximum = minimum;
		for (integer ichannel = 1; ichannel <= (numberOfChannels & ~ 15); ichannel ++) {
			double *channel = event -> erp -> z [ichannel];
			constVEC channel = event -> erp -> z.row (ichannel);
			for (integer isample = 1; isample <= numberOfSamples; isample ++) {
				double value = channel [isample];
				if (value < minimum) minimum = value;
@@ -233,19 +233,10 @@ autoERP ERPTier_extractERP (ERPTier me, integer eventNumber) {
			Melder_throw (U"No events.");
		ERPTier_checkEventNumber (me, eventNumber);
		ERPPoint event = my points.at [eventNumber];
		integer numberOfChannels = event -> erp -> ny;
		Melder_assert (numberOfChannels == my numberOfChannels);
		integer numberOfSamples = event -> erp -> nx;
		Melder_assert (event -> erp -> ny == my numberOfChannels);
		autoERP thee = Thing_new (ERP);
		event -> erp -> structSound :: v_copy (thee.get());
		for (integer ichannel = 1; ichannel <= numberOfChannels; ichannel ++) {
			double *oldChannel = event -> erp -> z [ichannel];
			double *newChannel = thy z [ichannel];
			for (integer isample = 1; isample <= numberOfSamples; isample ++) {
				newChannel [isample] = oldChannel [isample];
			}
		}
		thy channelNames = STRVECclone (my channelNames.get());
		thy channelNames = newSTRVECcopy (my channelNames.get());
		return thee;
	} catch (MelderError) {
		Melder_throw (me, U": ERP not extracted.");
@@ -258,29 +249,17 @@ autoERP ERPTier_to_ERP_mean (ERPTier me) {
		if (numberOfEvents < 1)
			Melder_throw (U"No events.");
		ERPPoint firstEvent = my points.at [1];
		integer numberOfChannels = firstEvent -> erp -> ny;
		integer numberOfSamples = firstEvent -> erp -> nx;
		Melder_assert (firstEvent -> erp -> ny == my numberOfChannels);
		autoERP mean = Thing_new (ERP);
		firstEvent -> erp -> structSound :: v_copy (mean.get());
		Melder_assert (mean -> ny == my numberOfChannels);
		for (integer ievent = 2; ievent <= numberOfEvents; ievent ++) {
			ERPPoint event = my points.at [ievent];
			for (integer ichannel = 1; ichannel <= numberOfChannels; ichannel ++) {
				double *erpChannel = event -> erp -> z [ichannel];
				double *meanChannel = mean -> z [ichannel];
				for (integer isample = 1; isample <= numberOfSamples; isample ++) {
					meanChannel [isample] += erpChannel [isample];
				}
			}
		}
		double factor = 1.0 / numberOfEvents;
		for (integer ichannel = 1; ichannel <= numberOfChannels; ichannel ++) {
			double *meanChannel = mean -> z [ichannel];
			for (integer isample = 1; isample <= numberOfSamples; isample ++) {
				meanChannel [isample] *= factor;
			Melder_assert (event -> erp -> ny == my numberOfChannels);
			mean -> z.all()  +=  event -> erp -> z.all();
		}
		}
		Melder_assert (mean -> ny == my numberOfChannels);
		mean -> channelNames = STRVECclone (my channelNames.get());
		mean -> z.all()  *=  1.0 / numberOfEvents;
		mean -> channelNames = newSTRVECcopy (my channelNames.get());
		return mean;
	} catch (MelderError) {
		Melder_throw (me, U": mean not computed.");
@@ -297,7 +276,7 @@ autoERPTier ERPTier_extractEventsWhereColumn_number (ERPTier me, Table table, in
		autoERPTier thee = Thing_new (ERPTier);
		Function_init (thee.get(), my xmin, my xmax);
		thy numberOfChannels = my numberOfChannels;
		thy channelNames = STRVECclone (my channelNames.get());
		thy channelNames = newSTRVECcopy (my channelNames.get());
		for (integer ievent = 1; ievent <= my points.size; ievent ++) {
			ERPPoint oldEvent = my points.at [ievent];
			TableRow row = table -> rows.at [ievent];
@@ -326,7 +305,7 @@ autoERPTier ERPTier_extractEventsWhereColumn_string (ERPTier me, Table table,
		autoERPTier thee = Thing_new (ERPTier);
		Function_init (thee.get(), my xmin, my xmax);
		thy numberOfChannels = my numberOfChannels;
		thy channelNames = STRVECclone (my channelNames.get());
		thy channelNames = newSTRVECcopy (my channelNames.get());
		for (integer ievent = 1; ievent <= my points.size; ievent ++) {
			ERPPoint oldEvent = my points.at [ievent];
			TableRow row = table -> rows.at [ievent];
+5 −4
Original line number Diff line number Diff line
@@ -158,7 +158,7 @@ void ERP_drawScalp_garnish (Graphics graphics, double vmin, double vmax, enum kG
		}
	}
	Graphics_setColourScale (graphics, colourScale);
	Graphics_image (graphics, legend.at, 1, 2, 0.85, 0.98, 1, n, -0.8, +0.8, 0.0, 1.0);
	Graphics_image (graphics, legend.all(), 0.85, 0.98, -0.8, +0.8, 0.0, 1.0);
	Graphics_setColourScale (graphics, kGraphics_colourScale::GREY);
	Graphics_rectangle (graphics, 0.85, 0.98, -0.8, +0.8);
	Graphics_setTextAlignment (graphics, Graphics_RIGHT, Graphics_TOP);
@@ -232,7 +232,7 @@ void ERP_drawScalp (ERP me, Graphics graphics, double tmin, double tmax, double
			}
		}
	}
	Graphics_image (graphics, image.at, 1, n, -1.0-0.5/n, 1.0+0.5/n, 1, n, -1.0-0.5/n, 1.0+0.5/n, vmin, vmax);
	Graphics_image (graphics, image.all(), -1.0-0.5/n, 1.0+0.5/n, -1.0-0.5/n, 1.0+0.5/n, vmin, vmax);
	Graphics_setColourScale (graphics, kGraphics_colourScale::GREY);
	Graphics_setLineWidth (graphics, 2.0);
	/*
@@ -357,7 +357,7 @@ void structERPWindow :: v_drawSelectionViewer () {
		}
	}
	Graphics_setColourScale (our graphics.get(), our p_scalp_colourScale);
	Graphics_image (our graphics.get(), image.at, 1, n, -1.0-0.5/n, 1.0+0.5/n, 1, n, -1.0-0.5/n, 1.0+0.5/n, minimum, maximum);
	Graphics_image (our graphics.get(), image.all(), -1.0-0.5/n, 1.0+0.5/n, -1.0-0.5/n, 1.0+0.5/n, minimum, maximum);
	Graphics_setColourScale (our graphics.get(), kGraphics_colourScale::GREY);
	Graphics_setLineWidth (our graphics.get(), 2.0);
	/*
@@ -393,7 +393,8 @@ void structERPWindow :: v_drawSelectionViewer () {

OPTIONMENU_ENUM_VARIABLE (kGraphics_colourScale, v_prefs_scalpColourSpace)
void structERPWindow :: v_prefs_addFields (EditorCommand cmd) {
	OPTIONMENU_ENUM_FIELD (v_prefs_scalpColourSpace, U"Scalp colour space", kGraphics_colourScale, kGraphics_colourScale::BLUE_TO_RED)
	OPTIONMENU_ENUM_FIELD (kGraphics_colourScale, v_prefs_scalpColourSpace,
			U"Scalp colour space", kGraphics_colourScale::BLUE_TO_RED)
}
void structERPWindow :: v_prefs_setValues (EditorCommand cmd) {
	SET_ENUM (v_prefs_scalpColourSpace, kGraphics_colourScale, p_scalp_colourScale)
+18 −12
Original line number Diff line number Diff line
@@ -125,12 +125,13 @@ DO
}

FORM (MODIFY_EEG_removeTriggers, U"Remove triggers", nullptr) {
	OPTIONMENU_ENUM (removeEveryTriggerThat___, U"Remove every trigger that...", kMelder_string, DEFAULT)
	OPTIONMENU_ENUM (kMelder_string, removeEveryTriggerThat___,
			U"Remove every trigger that...", kMelder_string::DEFAULT)
	SENTENCE (___theText, U"...the text", U"hi")
	OK
DO
	MODIFY_EACH (EEG)
		EEG_removeTriggers (me, (kMelder_string) removeEveryTriggerThat___, ___theText);
		EEG_removeTriggers (me, removeEveryTriggerThat___, ___theText);
	MODIFY_EACH_END
}

@@ -266,27 +267,30 @@ DO
FORM (NEW_EEG_to_ERPTier_triggers, U"To ERPTier (triggers)", nullptr) {
	REAL (fromTime, U"From time (s)", U"-0.11")
	REAL (toTime, U"To time (s)", U"0.39")
	OPTIONMENU_ENUM (getEveryEventWithATriggerThat, U"Get every event with a trigger that", kMelder_string, DEFAULT)
	OPTIONMENU_ENUM (kMelder_string, getEveryEventWithATriggerThat,
			U"Get every event with a trigger that", kMelder_string::DEFAULT)
	SENTENCE (theText, U"...the text", U"1")
	OK
DO
	CONVERT_EACH (EEG)
		autoERPTier result = EEG_to_ERPTier_triggers (me, fromTime, toTime, (kMelder_string) getEveryEventWithATriggerThat, theText);
		autoERPTier result = EEG_to_ERPTier_triggers (me, fromTime, toTime, getEveryEventWithATriggerThat, theText);
	CONVERT_EACH_END (my name.get(), U"_trigger", theText)
}

FORM (NEW_EEG_to_ERPTier_triggers_preceded, U"To ERPTier (triggers, preceded)", nullptr) {
	REAL (fromTime, U"From time (s)", U"-0.11")
	REAL (toTime, U"To time (s)", U"0.39")
	OPTIONMENU_ENUM (getEveryEventWithATriggerThat, U"Get every event with a trigger that", kMelder_string, DEFAULT)
	OPTIONMENU_ENUM (kMelder_string, getEveryEventWithATriggerThat,
			U"Get every event with a trigger that", kMelder_string::DEFAULT)
	SENTENCE (text1, U"...the text", U"1")
	OPTIONMENU_ENUM (andIsPrecededByATriggerThat, U"and is preceded by a trigger that", kMelder_string, DEFAULT)
	OPTIONMENU_ENUM (kMelder_string, andIsPrecededByATriggerThat,
			U"and is preceded by a trigger that", kMelder_string::DEFAULT)
	SENTENCE (text2, U" ...the text", U"4")
	OK
DO
	CONVERT_EACH (EEG)
		autoERPTier result = EEG_to_ERPTier_triggers_preceded (me, fromTime, toTime,
			(kMelder_string) getEveryEventWithATriggerThat, text1, (kMelder_string) andIsPrecededByATriggerThat, text2);
			(kMelder_string) getEveryEventWithATriggerThat, text1, andIsPrecededByATriggerThat, text2);
	CONVERT_EACH_END (my name.get(), U"_trigger", text2)
}

@@ -422,7 +426,8 @@ FORM (GRAPHICS_ERP_drawScalp_colour, U"ERP: Draw scalp (colour)", nullptr) {
	REAL (toTime, U"right Time range", U"0.2")
	REAL (fromVoltage, U"left Voltage range (V)", U"10e-6")
	REAL (toVoltage, U"right Voltage range", U"-10e-6")
	RADIO_ENUM (colourScale, U"Colour scale", kGraphics_colourScale, BLUE_TO_RED)
	RADIO_ENUM (kGraphics_colourScale, colourScale,
			U"Colour scale", kGraphics_colourScale::BLUE_TO_RED)
	BOOLEAN (garnish, U"Garnish", true)
	OK
DO
@@ -435,7 +440,8 @@ DO
FORM (GRAPHICS_ERP_drawScalp_garnish, U"ERP: Draw scalp (garnish)", nullptr) {
	REAL (fromVoltage, U"left Voltage range (V)", U"10e-6")
	REAL (toVoltage, U"right Voltage range", U"-10e-6")
	RADIO_ENUM (colourScale, U"Colour scale", kGraphics_colourScale, BLUE_TO_RED)
	RADIO_ENUM (kGraphics_colourScale, colourScale,
			U"Colour scale", kGraphics_colourScale::BLUE_TO_RED)
	OK
DO
	GRAPHICS_NONE
@@ -704,7 +710,7 @@ DIRECT (NEW_ERPTier_to_ERP_mean) {

FORM (NEW1_ERPTier_Table_extractEventsWhereColumn_number, U"Extract events where column (number)", nullptr) {
	WORD (extractAllEventsWhereColumn___, U"Extract all events where column...", U"")
	RADIO_ENUM (___is___, U"...is...", kMelder_number, DEFAULT)
	RADIO_ENUM (kMelder_number, ___is___, U"...is...", kMelder_number::DEFAULT)
	REAL (___theNumber, U"...the number", U"0.0")
	OK
DO
@@ -716,13 +722,13 @@ DO

FORM (NEW1_ERPTier_Table_extractEventsWhereColumn_text, U"Extract events where column (text)", nullptr) {
	WORD (extractAllEventsWhereColumn___, U"Extract all events where column...", U"")
	OPTIONMENU_ENUM (___, U"...", kMelder_string, DEFAULT)
	OPTIONMENU_ENUM (kMelder_string, ___, U"...", kMelder_string::DEFAULT)
	SENTENCE (___theText, U"...the text", U"hi")
	OK
DO
	CONVERT_TWO (ERPTier, Table)
		integer columnNumber = Table_getColumnIndexFromColumnLabel (you, extractAllEventsWhereColumn___);
		autoERPTier result = ERPTier_extractEventsWhereColumn_string (me, you, columnNumber, (kMelder_string) ___, ___theText);
		autoERPTier result = ERPTier_extractEventsWhereColumn_string (me, you, columnNumber, ___, ___theText);
	CONVERT_TWO_END (my name.get())
}

Loading