package org.epics.archiverappliance.retrieval.matlab;
import static org.junit.Assert.assertTrue;
import java.io.File;
import java.util.LinkedList;
import java.util.Map;
import org.apache.commons.io.FileUtils;
import org.apache.log4j.Logger;
import org.epics.archiverappliance.Event;
import org.epics.archiverappliance.EventStream;
import org.epics.archiverappliance.common.BasicContext;
import org.epics.archiverappliance.common.TimeUtils;
import org.epics.archiverappliance.config.ArchDBRTypes;
import org.epics.archiverappliance.config.ConfigService;
import org.epics.archiverappliance.config.ConfigServiceForTests;
import org.epics.archiverappliance.config.StoragePluginURLParser;
import org.epics.archiverappliance.data.ScalarValue;
import org.epics.archiverappliance.engine.membuf.ArrayListEventStream;
import org.epics.archiverappliance.retrieval.RemotableEventStreamDesc;
import org.epics.archiverappliance.retrieval.workers.CurrentThreadWorkerEventStream;
import org.epics.archiverappliance.utils.simulation.SimulationEvent;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import com.jmatio.io.MatFileReader;
import com.jmatio.io.MatFileWriter;
import com.jmatio.types.MLArray;
import com.jmatio.types.MLChar;
import com.jmatio.types.MLDouble;
import com.jmatio.types.MLStructure;
import com.jmatio.types.MLUInt64;
import com.jmatio.types.MLUInt8;
import edu.stanford.slac.archiverappliance.PlainPB.PlainPBStoragePlugin;
/**
* Test generation of Matlab files from event streams
* @author mshankar
*
*/
public class MatlabFileTest {
private static Logger logger = Logger.getLogger(MatlabFileTest.class.getName());
ConfigService configService;
PlainPBStoragePlugin storageplugin;
String rootFolderName = ConfigServiceForTests.getDefaultPBTestFolder() + "/" + "MatlabFileTest";
String pvName = "Test_MatlabPV";
@Before
public void setUp() throws Exception {
configService = new ConfigServiceForTests(new File("./bin"));
storageplugin = (PlainPBStoragePlugin) StoragePluginURLParser.parseStoragePlugin("pb://localhost?name=STS&rootFolder=" + rootFolderName + "/&partitionGranularity=PARTITION_YEAR", configService);
if(new File(rootFolderName).exists()) {
FileUtils.deleteDirectory(new File(rootFolderName));
}
try(BasicContext context = new BasicContext()) {
int totalNum=6*60*24;
short currentYear = TimeUtils.getCurrentYear();
ArrayListEventStream testData = new ArrayListEventStream(totalNum, new RemotableEventStreamDesc(ArchDBRTypes.DBR_SCALAR_DOUBLE, pvName, currentYear));
for(int s = 0; s < totalNum; s++) {
testData.add(new SimulationEvent(s*10, currentYear, ArchDBRTypes.DBR_SCALAR_DOUBLE, new ScalarValue<Double>((double) s*10)));
}
storageplugin.appendData(context, pvName, testData);
}
}
@After
public void tearDown() throws Exception {
}
interface GenMLArray {
public MLArray generateColumn(ArrayListEventStream dest);
}
class GenTimeArray implements GenMLArray {
public MLArray generateColumn(ArrayListEventStream dest) {
MLUInt64 ret = new MLUInt64("epochSeconds", new int[] {dest.size(), 1} );
int i = 0;
for(Event e : dest) {
ret.set(e.getEpochSeconds(), i++);
}
return ret;
}
}
class GenValueArray implements GenMLArray {
public MLArray generateColumn(ArrayListEventStream dest) {
MLDouble ret = new MLDouble("values", new int[] {dest.size(), 1} );
int i = 0;
for(Event e : dest) {
ret.set(e.getSampleValue().getValue().doubleValue(), i++);
}
return ret;
}
}
class GenNanosArray implements GenMLArray {
public MLArray generateColumn(ArrayListEventStream dest) {
MLUInt64 ret = new MLUInt64("nanos", new int[] {dest.size(), 1} );
int i = 0;
for(Event e : dest) {
ret.set((long) e.getEventTimeStamp().getNanos(), i++);
}
return ret;
}
}
class GenisDSTArray implements GenMLArray {
public MLArray generateColumn(ArrayListEventStream dest) {
MLUInt8 ret = new MLUInt8("isDST", new int[] {dest.size(), 1} );
int i = 0;
for(Event e : dest) {
ret.set(TimeUtils.isDST(e.getEventTimeStamp()) ? (byte) 1 : (byte) 0, i++);
}
return ret;
}
}
@Test
public void testGenerateMatlabFile() throws Exception {
short currentYear = TimeUtils.getCurrentYear();
String fileName = rootFolderName + "/" + "sample1.mat";
try(BasicContext context = new BasicContext();
EventStream strm = new CurrentThreadWorkerEventStream(pvName, storageplugin.getDataForPV(context, pvName, TimeUtils.getStartOfYear(currentYear), TimeUtils.getEndOfYear(currentYear)))
) {
ArrayListEventStream dest = new ArrayListEventStream(0, new RemotableEventStreamDesc(ArchDBRTypes.DBR_SCALAR_DOUBLE, pvName, currentYear));
for(Event e : strm) {
dest.add(e.makeClone());
}
logger.info("Generating matlab file to " + fileName);
MLStructure dataStruct = new MLStructure("data", new int[] {1, 1});
dataStruct.setField("epochSeconds", new GenTimeArray().generateColumn(dest));
dataStruct.setField("values", new GenValueArray().generateColumn(dest));
dataStruct.setField("nanos", new GenNanosArray().generateColumn(dest));
dataStruct.setField("isDST", new GenisDSTArray().generateColumn(dest));
MLStructure headerStruct = new MLStructure("header", new int[] {1, 1});
headerStruct.setField("source", new MLChar("source", "Archiver appliance"));
headerStruct.setField("pvName", new MLChar("pvName", pvName));
headerStruct.setField("from", new MLChar("pvName", TimeUtils.convertToISO8601String(TimeUtils.getStartOfYear(currentYear))));
headerStruct.setField("to", new MLChar("pvName", TimeUtils.convertToISO8601String(TimeUtils.getEndOfYear(currentYear))));
LinkedList<MLArray> dataList = new LinkedList<MLArray>();
dataList.add(headerStruct);
dataList.add(dataStruct);
new MatFileWriter(new File(fileName), dataList);
logger.info("Done generating matlab file to " + fileName);
}
MatFileReader reader = new MatFileReader(fileName);
Map<String, MLArray> content = reader.getContent();
logger.info(fileName + " has " + content.size() + " arrays");
for(String key : content.keySet()) {
logger.info("Key: " + key);
}
MLStructure pvDataFileFile = (MLStructure) content.get("data");
assertTrue("Cannot find data for pv in file ", pvDataFileFile != null);
MLArray epochSecondsArray = pvDataFileFile.getField("epochSeconds");
assertTrue("Cannot find epochSeconds for pv in file ", epochSecondsArray != null);
MLArray valueArray = pvDataFileFile.getField("values");
assertTrue("Cannot find value for pv in file ", valueArray != null);
}
}