private void Init()
 {
     _version = -1;
     _minmaxDefined = false;
     knownMovements = null;
     requestedMovements = null;
     _converter = null;
     _movCodeToStringConverter = null;
 }
        public void WriteFile(string filename, Recording recording)
        {
            byte[] byteArray;
            double[] doubleArray = new double[1];
            string result;
            RecordingConfig recordingConfig = recording.parameters;

            H5DataTypeId dataTypeId;
            H5DataSpaceId dataSpaceId;
            H5AttributeId attributeId;

            long[] attributeDims;

            _movCodeToStringConverter = new MovCodeToStringConverter(knownMovements, allowedComplexMovements);

            try
            {
                H5FileId fileId = H5F.create(filename, H5F.CreateMode.ACC_TRUNC);

                H5GroupId groupId = H5G.create(fileId, "/recSession");

                //Writing recSession attributes

                //sF - sampling frequency
                dataTypeId = H5T.copy(H5T.H5Type.NATIVE_DOUBLE);
                attributeDims = new long[1];
                attributeDims[0] = doubleArray.Length;
                dataSpaceId = H5S.create_simple(1, attributeDims);
                attributeId = H5A.create(groupId, "sF", dataTypeId, dataSpaceId);
                doubleArray[0] = recording.parameters.sampleFreq;
                H5A.write<double>(attributeId, dataTypeId, new H5Array<double>(doubleArray));

                H5A.close(attributeId);
                H5T.close(dataTypeId);
                H5S.close(dataSpaceId);

                //sT - sample time
                dataTypeId = H5T.copy(H5T.H5Type.NATIVE_DOUBLE);
                attributeDims = new long[1];
                attributeDims[0] = doubleArray.Length;
                dataSpaceId = H5S.create_simple(1, attributeDims);
                attributeId = H5A.create(groupId, "sT", dataTypeId, dataSpaceId);
                doubleArray[0] = recording.parameters.scheduleItemTime * recording.parameters.repetitions * 2; //*2 because rests also count!
                H5A.write<double>(attributeId, dataTypeId, new H5Array<double>(doubleArray));

                H5A.close(attributeId);
                H5T.close(dataTypeId);
                H5S.close(dataSpaceId);

                //cT - contraction time
                dataTypeId = H5T.copy(H5T.H5Type.NATIVE_DOUBLE);
                attributeDims = new long[1];
                attributeDims[0] = doubleArray.Length;
                dataSpaceId = H5S.create_simple(1, attributeDims);
                attributeId = H5A.create(groupId, "cT", dataTypeId, dataSpaceId);
                doubleArray[0] = recording.parameters.scheduleItemTime;
                H5A.write<double>(attributeId, dataTypeId, new H5Array<double>(doubleArray));

                H5A.close(attributeId);
                H5T.close(dataTypeId);
                H5S.close(dataSpaceId);

                //rT - relaxation time
                dataTypeId = H5T.copy(H5T.H5Type.NATIVE_DOUBLE);
                attributeDims = new long[1];
                attributeDims[0] = doubleArray.Length;
                dataSpaceId = H5S.create_simple(1, attributeDims);
                attributeId = H5A.create(groupId, "rT", dataTypeId, dataSpaceId);
                doubleArray[0] = recording.parameters.scheduleItemTime;
                H5A.write<double>(attributeId, dataTypeId, new H5Array<double>(doubleArray));

                H5A.close(attributeId);
                H5T.close(dataTypeId);
                H5S.close(dataSpaceId);

                //nM - number of movements
                dataTypeId = H5T.copy(H5T.H5Type.NATIVE_DOUBLE);
                attributeDims = new long[1];
                attributeDims[0] = doubleArray.Length;
                dataSpaceId = H5S.create_simple(1, attributeDims);
                attributeId = H5A.create(groupId, "nM", dataTypeId, dataSpaceId);
                doubleArray[0] = (recording.parameters.schedule.Count - recording.parameters.scheduleWarmupItems) / (recording.parameters.repetitions * 2);
                H5A.write<double>(attributeId, dataTypeId, new H5Array<double>(doubleArray));

                H5A.close(attributeId);
                H5T.close(dataTypeId);
                H5S.close(dataSpaceId);

                //nR - number of repetitions
                dataTypeId = H5T.copy(H5T.H5Type.NATIVE_DOUBLE);
                attributeDims = new long[1];
                attributeDims[0] = doubleArray.Length;
                dataSpaceId = H5S.create_simple(1, attributeDims);
                attributeId = H5A.create(groupId, "nR", dataTypeId, dataSpaceId);
                doubleArray[0] = recording.parameters.repetitions;
                H5A.write<double>(attributeId, dataTypeId, new H5Array<double>(doubleArray));

                H5A.close(attributeId);
                H5T.close(dataTypeId);
                H5S.close(dataSpaceId);

                //nCh - number of channels
                dataTypeId = H5T.copy(H5T.H5Type.NATIVE_DOUBLE);
                attributeDims = new long[1];
                attributeDims[0] = doubleArray.Length;
                dataSpaceId = H5S.create_simple(1, attributeDims);
                attributeId = H5A.create(groupId, "nCh", dataTypeId, dataSpaceId);
                doubleArray[0] = recording.parameters.nChannels;
                H5A.write<double>(attributeId, dataTypeId, new H5Array<double>(doubleArray));

                H5A.close(attributeId);
                H5T.close(dataTypeId);
                H5S.close(dataSpaceId);

                //date
                doubleArray = new double[6];
                dataTypeId = H5T.copy(H5T.H5Type.NATIVE_DOUBLE);
                attributeDims = new long[1];
                attributeDims[0] = doubleArray.Length;
                dataSpaceId = H5S.create_simple(1, attributeDims);
                DateTime now = DateTime.Now;
                attributeId = H5A.create(groupId, "date", dataTypeId, dataSpaceId);

                doubleArray[0] = now.Year;
                doubleArray[1] = now.Month;
                doubleArray[2] = now.Day;
                doubleArray[3] = now.Hour;
                doubleArray[4] = now.Minute;
                doubleArray[5] = now.Second;

                H5A.write<double>(attributeId, dataTypeId, new H5Array<double>(doubleArray));

                //mov - list of movements
                int lastUsedCode = 0;
                int movsProcessed = 0;
                result = "";

                //foreach (ScheduleItem item in recording.parameters.schedule)
                for (int i = 0; i < recording.parameters.schedule.Count; i++)
                {
                    ScheduleItem item = recording.parameters.schedule[i];

                    int currentCode = item.movementCode;

                    if (currentCode != 0 && currentCode != lastUsedCode)
                    {
                        string movementName = (string)_movCodeToStringConverter.Convert(currentCode, null, null, null);

                        if (movsProcessed > 0)
                            result = result + ";";

                        result = result + movementName;

                        lastUsedCode = currentCode;
                        movsProcessed++;
                    }
                }

                byteArray = System.Text.Encoding.UTF8.GetBytes(result);

                dataTypeId = H5T.copy(H5T.H5Type.C_S1);
                H5T.setSize(dataTypeId, byteArray.Length);
                dataSpaceId = H5S.create(H5S.H5SClass.SCALAR);
                attributeId = H5A.create(groupId, "mov", dataTypeId, dataSpaceId);

                H5A.write<byte>(attributeId, dataTypeId, new H5Array<byte>(byteArray));

                H5A.close(attributeId);
                H5T.close(dataTypeId);
                H5S.close(dataSpaceId);

                //dev - device name
                result = "MPTCE";

                byteArray = System.Text.Encoding.UTF8.GetBytes(result);

                dataTypeId = H5T.copy(H5T.H5Type.C_S1);
                H5T.setSize(dataTypeId, byteArray.Length);
                dataSpaceId = H5S.create(H5S.H5SClass.SCALAR);
                attributeId = H5A.create(groupId, "dev", dataTypeId, dataSpaceId);

                H5A.write<byte>(attributeId, dataTypeId, new H5Array<byte>(byteArray));

                H5A.close(attributeId);
                H5T.close(dataTypeId);
                H5S.close(dataSpaceId);

                //cmt -comments
                result = "Created with MPTCE";

                byteArray = System.Text.Encoding.UTF8.GetBytes(result);

                dataTypeId = H5T.copy(H5T.H5Type.C_S1);
                H5T.setSize(dataTypeId, byteArray.Length);
                dataSpaceId = H5S.create(H5S.H5SClass.SCALAR);
                attributeId = H5A.create(groupId, "cmt", dataTypeId, dataSpaceId);

                H5A.write<byte>(attributeId, dataTypeId, new H5Array<byte>(byteArray));

                H5A.close(attributeId);
                H5T.close(dataTypeId);
                H5S.close(dataSpaceId);

                /*
                 * Now writing the recording data
                 */

                //We will reuse the movsProcessed variable to help on defining the dimensions of the data array
                attributeDims = new long[3];
                attributeDims[0] = movsProcessed;
                attributeDims[1] = recording.parameters.nChannels;
                attributeDims[2] = (int)(recording.parameters.scheduleItemnSamples * recording.parameters.repetitions * 2);

                double[, ,] data = new double[attributeDims[0], attributeDims[1], attributeDims[2]];

                //Filling up the data array
                for (int i = 0; i < attributeDims[0]; i++)
                {
                    for (int j = 0; j < attributeDims[1]; j++)
                    {
                        for (int k = 0; k < attributeDims[2]; k++)
                        {
                            Frame currentFrame = recording.data[(int)((i * attributeDims[2]) + k)];
                            data[i, j, k] = currentFrame.samples[j];
                        }
                    }
                }

                //Writing the data array to the file
                dataTypeId = H5T.copy(H5T.H5Type.NATIVE_DOUBLE);
                dataSpaceId = H5S.create_simple(attributeDims.Length, attributeDims);

                H5DataSetId dataSetId = H5D.create(groupId, "tdata", dataTypeId, dataSpaceId);
                H5D.write(dataSetId, dataTypeId, new H5Array<double>(data));
                H5D.close(dataSetId);

                H5G.close(groupId);

                H5F.close(fileId);
            }
            catch (HDFException e)
            {
                Debug.WriteLine("Error saving HDF5 file");
                throw new IFileReadWriterException("Error saving HDF5 file", e);
            }
        }