diff --git a/Analysis/SdasImport2File.py b/Analysis/SdasImport2File.py new file mode 100644 index 0000000..eb0e826 --- /dev/null +++ b/Analysis/SdasImport2File.py @@ -0,0 +1,112 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- +""" +Python3 App to Import data from ISTTOK SDAS to MDSPlus +author: B. Carvalho / IPFN-IST +email: bernardo.carvalho@tecnico.ulisboa.pt + +Install sdas: +http://metis.ipfn.tecnico.ulisboa.pt/CODAC/IPFN_Software/SDAS/Access/Python +""" + +import numpy as np +import argparse +# import matplotlib.pyplot as plt +from MdsImportSdas import StartSdas, LoadSdasData +ISTTOK_RT_PERIOD = 0.0001 + +def build_import_table_langmuir(): + SDAS_NODEFMT = 'MARTE_NODE_IVO3.DataCollection.Channel_{}' + LANGMUIR_OFF = 24 + NUM_PROBES = 4 + """ + ADC_electric_top_near: MARTE_NODE_IVO3.DataCollection.Channel_024 + ADC_electric_outer_near: MARTE_NODE_IVO3.DataCollection.Channel_025 + ADC_electric_bottom_near: MARTE_NODE_IVO3.DataCollection.Channel_026 + ADC_electric_inner_near: MARTE_NODE_IVO3.DataCollection.Channel_027 + """ + table = [] + for n in range(NUM_PROBES): + sdas_str = SDAS_NODEFMT.format(str(LANGMUIR_OFF + n).zfill(3)) + nd = {'sdas': sdas_str, 'name': f'Langmuir Probe no. {n+1}'} + table.append(nd) + return table + +""" +def plot_signals(pulse, nodeTable): + try: + tree = Tree(MDSTREENAME, pulse) + except mdsExceptions.TreeNOPATH: + print(f'Failed opening {MDSTREENAME}') + except mdsExceptions.TreeFOPENR: + print(f'Failed opening {MDSTREENAME} for pulse number {pulse:d}') + exit() + NoOfColors = len(nodeTable) + cm = plt.get_cmap('jet') + fig = plt.figure(figsize=(5, 7), tight_layout=True) + ax = fig.add_subplot(111) + ax.set_prop_cycle(color=[cm(1.*i/NoOfColors) for i in range(NoOfColors)]) + plt.title(f'#{pulse}: Mirnov coil signals') + + for nd in nodeTable: + nd_mds = tree.getNode(nd['mds']) + mdsData = nd_mds.getData() + signal = mdsData.data() + if len(signal) > 0: + times = mdsData.dims[0] + plt.plot(times, signal, label=nd['name']) + + plt.xlabel('Time / s ') + plt.legend() + plt.grid(True) + plt.show() +""" + + +def get_arguments(): + parser = argparse.ArgumentParser(description='ISTTOK ') + parser.add_argument('-p', '--pulse', + help='pulse (shot) number', default='46241', type=int) + # parser.add_argument('-s', '--shot', + # type=int, help='Mds+ pulse Number ([1, ...])', + # default=100) + parser.add_argument('-f', '--file', type=str, + help='filename device to save', default='LangmuirSdas') + parser.add_argument('-e', '--exportData', + action='store_true', help='Export to MDSPlus') + parser.add_argument('-m', '--mirnov', + action='store_true', help='Import Mirnov') + parser.add_argument('-l', '--langmuir', + action='store_true', help='Import Langmuir') + parser.add_argument('-t', '--ploT', + action='store_true', help='Plot Signals') + parser.add_argument('-n', '--names', + action='store_true', help='Print Node Table') + return parser.parse_args() + + +if (__name__ == "__main__"): + args = get_arguments() + pulseNo = args.pulse + + nodeTable = build_import_table_langmuir() + client = StartSdas() + langmuirData = [] + for nd in nodeTable: + print(nd['sdas']) + data, tzero_us, period = LoadSdasData(client, nd['sdas'], pulseNo) + langmuirData.append(data) + time = np.arange(len(data), dtype='uint32') * int(period) + langmuirNp = np.array(langmuirData).T + data2file = np.insert(langmuirNp, 0, time, axis=1) + filename = f"{args.file:s}_{pulseNo}.csv" + head = ('#Time (uint32)[1],Langmuir0 (float32)[1],Langmuir1 (float32)[1],' + 'Langmuir2 (float32)[1],Langmuir3 (float32)[1]') + # formt = ['%d', '%.6f', '%.6f', '%.6f', '%.6f'] + formt = '%d,%.6f,%.6f,%.6f,%.6f' +# formt = '%d,{%.6f,%.6f,%.6f,%.6f}' +# head = '#TimeSdas (uint32)[1],LangmuirSignals (float32)[4]' + np.savetxt(filename, data2file, fmt=formt, + header=head, comments='') # , delimiter=',') + +# plot_signals(46241, table) diff --git a/Configurations/RTApp-Isttok-File.cfg b/Configurations/RTApp-Isttok-File.cfg new file mode 100644 index 0000000..6378051 --- /dev/null +++ b/Configurations/RTApp-Isttok-File.cfg @@ -0,0 +1,642 @@ ++EPICSCAInterface= { + Class = EPICS::EPICSCAClient + StackSize = 1048576 + CPUs = 0x1 + AutoStart = 0 + +PV_STATUS = { + Class = EPICS::EPICSPV + PVName = "MARTE2-DEMO-APP:STATUS" + PVType = int32 + } + +PV_COMMAND = { + Class = EPICS::EPICSPV + PVName = "MARTE2-DEMO-APP:COMMAND" + PVType = uint32 + Event = { + Destination = StateMachine + PVValue = Function + FunctionMap = {{"2", "GOTOPULSING"}, {"1", "GOTOWAITING_FOR_PRE"}, {"0", "GOTOIDLE"}} + } + } +} ++WebRoot = { + Class = HttpObjectBrowser + Root = "." + +ObjectBrowse = { + Class = HttpObjectBrowser + Root = "/" + } + +ResourcesHtml = { + Class = HttpDirectoryResource + BaseDir = "../../MARTe2/MARTe2/Resources/HTTP/" + } + +HttpMessageInterface = { + Class = HttpMessageInterface + +GOTOIDLE = { + Class = Message + Destination = StateMachine + Function = GOTOIDLE + Mode = ExpectsReply + } + +GOTOWAITING_FOR_PRE = { + Class = Message + Destination = StateMachine + Function = GOTOWAITING_FOR_PRE + Mode = ExpectsReply + } + +GOTOPULSING = { + Class = Message + Destination = StateMachine + Function = GOTOPULSING + Mode = ExpectsReply + } + +GOTOERR = { + Class = Message + Destination = StateMachineError + Function = GOTOERR + Mode = ExpectsReply + } + } +} ++WebServer = { + Class = HttpService + Port = 8084 + WebRoot = WebRoot + Timeout = 0 + ListenMaxConnections = 255 + AcceptTimeout = 1000 + MaxNumberOfThreads = 8 + MinNumberOfThreads = 1 +} ++StateMachine = { + Class = StateMachine + +INITIAL = { + Class = ReferenceContainer + +START = { + Class = StateMachineEvent + NextState = "IDLE" + NextStateError = "IDLE" + Timeout = 0 + +StartHttpServer = { + Class = Message + Destination = "WebServer" + Function = "Start" + Mode = ExpectsReply + } + +StartEPICSCAInterface = { + Class = Message + Destination = "EPICSCAInterface" + Mode = ExpectsReply + Function = "Start" + } + +OpenTreeMsg = { + Class = Message + Destination = "MdsLoopApp.Data.MDSWriter" + Function = OpenTree + Mode = ExpectsReply + +Parameters = { + Class = ConfigurationDatabase + param1 = 1 + } + } + +ChangeToStateIdleMsg = { + Class = Message + Destination = MdsLoopApp + Mode = ExpectsReply + Function = PrepareNextState + +Parameters = { + Class = ConfigurationDatabase + param1 = Idle + } + } + +StartNextStateExecutionMsg = { + Class = Message + Destination = MdsLoopApp + Function = StartNextStateExecution + Mode = ExpectsReply + } + } + } + +IDLE = { + Class = ReferenceContainer + +GOTOWAITING_FOR_PRE = { + Class = StateMachineEvent + NextState = "WAITING_FOR_PRE" + NextStateError = "IDLE" + Timeout = 0 + +ChangeToRunMsg = { + Class = Message + Destination = MdsLoopApp + Mode = ExpectsReply + Function = PrepareNextState + +Parameters = { + Class = ConfigurationDatabase + param1 = Online + } + } + +StopCurrentStateExecutionMsg = { + Class = Message + Destination = MdsLoopApp + Function = StopCurrentStateExecution + Mode = ExpectsReply + } + +StartNextStateExecutionMsg = { + Class = Message + Destination = MdsLoopApp + Function = StartNextStateExecution + Mode = ExpectsReply + } + } + } + +WAITING_FOR_PRE = { + Class = ReferenceContainer + +ENTER = { + Class = ReferenceContainer + +SetStatusPV = { + Class = Message + Destination = "EPICSCAInterface.PV_STATUS" + Function = CAPut + Mode = ExpectsReply + +Parameters = { + Class = ConfigurationDatabase + param1 = 1 + } + } + } + +GOTOPULSING = { + Class = StateMachineEvent + NextState = "PULSING" + NextStateError = "IDLE" + Timeout = 0 + +CalcOffSetsMsg = { + Class = "Message" + Destination = "MdsLoopApp.Functions.GAMElectricProbes" + Function = "CalcOffSets" + Mode = "ExpectsReply" + } + +StopCurrentStateExecutionMsg = { + Class = Message + Destination = MdsLoopApp + Function = StopCurrentStateExecution + Mode = ExpectsReply + } + +StartNextStateExecutionMsg = { + Class = Message + Destination = MdsLoopApp + Function = StartNextStateExecution + Mode = ExpectsReply + } + } + } + +PULSING = { + Class = ReferenceContainer + +ENTER = { + Class = ReferenceContainer + +SetStatusPV = { + Class = Message + Destination = "EPICSCAInterface.PV_STATUS" + Function = CAPut + Mode = ExpectsReply + +Parameters = { + Class = ConfigurationDatabase + param1 = 2 + } + } + } + +GOTOIDLE = { + Class = StateMachineEvent + NextState = "IDLE" + NextStateError = "IDLE" + Timeout = 0 + +ChangeToIdleMsg = { + Class = Message + Destination = MdsLoopApp + Mode = ExpectsReply + Function = PrepareNextState + +Parameters = { + Class = ConfigurationDatabase + param1 = Idle + } + } + +StopCurrentStateExecutionMsg = { + Class = Message + Destination = MdsLoopApp + Function = StopCurrentStateExecution + Mode = ExpectsReply + } + +StartNextStateExecutionMsg = { + Class = Message + Destination = MdsLoopApp + Function = StartNextStateExecution + Mode = ExpectsReply + } + +SetStatusPV = { + Class = Message + Destination = "EPICSCAInterface.PV_STATUS" + Function = CAPut + Mode = ExpectsReply + +Parameters = { + Class = ConfigurationDatabase + param1 = 0 + } + } + } + } +} +$MdsLoopApp = { + Class = RealTimeApplication + +Functions = { + Class = ReferenceContainer + +GAMTimer = { + Class = IOGAM + InputSignals = { + Counter = { + DataSource = Timer + Type = uint32 + } + Time = { + Frequency = 10000 + DataSource = Timer + Type = uint32 + } + Idle_Thread1_CycleTime = { + DataSource = Timings + Alias = "Idle.Thread1_CycleTime" + Type = uint32 + } + Run_Thread1_CycleTime = { + DataSource = Timings + Alias = "Online.Thread1_CycleTime" + Type = uint32 + } + } + OutputSignals = { + Counter = { + DataSource = DDB1 + Type = uint32 + } + Time = { + DataSource = DDB1 + Type = uint32 + } + Idle_Thread1_CycleTime = { + DataSource = DDB1 + Type = uint32 + } + Run_Thread1_CycleTime = { + DataSource = DDB1 + Type = uint32 + } + } + } + +GAMFileReader = { + Class = IOGAM + InputSignals = { + Time = { + DataSource = FileReader_DS + Type = uint32 + } + Langmuir0 = { + DataSource = FileReader_DS + Type = float32 + } + Langmuir1 = { + DataSource = FileReader_DS + Type = float32 + } + Langmuir2 = { + DataSource = FileReader_DS + Type = float32 + } + Langmuir3= { + DataSource = FileReader_DS + Type = float32 + } + } + OutputSignals = { + TimeSdas = { + DataSource = "DDB1" + Type = uint32 + } + Langmuir0= { + DataSource = "DDB1" + Type = float32 + } + Langmuir1= { + DataSource = "DDB1" + Type = float32 + } + Langmuir2= { + DataSource = "DDB1" + Type = float32 + } + Langmuir3= { + DataSource = "DDB1" + Type = float32 + } + } + } + /* + Langmuir0 = { + DataSource = "DDB1" + Type = float32 + } + Langmuir1 = { + DataSource = "DDB1" + Type = float32 + } + Langmuir2 = { + DataSource = "DDB1" + Type = float32 + } + Langmuir3 = { + DataSource = "DDB1" + Type = float32 + } + LangmuirS = { + DataSource = "DDB1" + Type = float32 + NumberOfElements = 4 + Ranges = {{1,1}} + } + LangmuirS = { + DataSource = "DDB1" + Type = float32 + NumberOfElements = 4 + Ranges = {{2,2}} + } + LangmuirS = { + DataSource = "DDB1" + Type = float32 + NumberOfElements = 4 + Ranges = {{3,3}} + } + OutMdsW1 = { + DataSource = FileSignalsWriter + Type = float32 + } + OutMdsW2 = { + DataSource = FileSignalsWriter + Type = float32 + } + OutMdsW3 = { + DataSource = FileSignalsWriter + Type = float32 + } + */ + +GAMSignalsWriter = { + Class = IOGAM + InputSignals = { + Time = { + DataSource = "DDB1" + Type = uint32 + } + Langmuir0 = { + DataSource = "DDB1" + Type = float32 + } + Langmuir1 = { + DataSource = "DDB1" + Type = float32 + } + Langmuir2 = { + DataSource = "DDB1" + Type = float32 + } + Langmuir3 = { + DataSource = "DDB1" + Type = float32 + } + } + OutputSignals = { + Time = { + DataSource = FileSignalsWriter + Type = uint32 + } + OutMdsW0 = { + DataSource = FileSignalsWriter + Type = float32 + } + OutMdsW1 = { + DataSource = FileSignalsWriter + Type = float32 + } + OutMdsW2 = { + DataSource = FileSignalsWriter + Type = float32 + } + OutMdsW3 = { + DataSource = FileSignalsWriter + Type = float32 + } + } + } + + +GAMElectricProbes = { + Class = ElectricProbesGAM + Gain = 5 //Compulsory + NumberOfSamplesAvg = 4 //Compulsory + ResetInEachState = 0//Compulsory. 1–> reset in each state, 0–> reset if the previous state is different from the next state + InputSignals = { + Langmuir0 = { + DataSource = "DDB1" + Type = float32 + } + Langmuir1 = { + DataSource = "DDB1" + Type = float32 + } + Langmuir2 = { + DataSource = "DDB1" + Type = float32 + } + Langmuir3 = { + DataSource = "DDB1" + Type = float32 + } + } + OutputSignals = { + SignalEP_OutR = { + DataSource = "DDB1" + Type = float32 + } + SignalEP_OutZ = { + DataSource = "DDB1" + Type = float32 + } + } + } + +GAMMDSWriter = { + Class = IOGAM + InputSignals = { + Langmuir0 = { + DataSource = "DDB1" + Type = float32 + } + Langmuir1 = { + DataSource = "DDB1" + Type = float32 + } + Langmuir2 = { + DataSource = "DDB1" + Type = float64 + } + CycleTime = { + DataSource = Timings + Alias = Idle.Thread1_CycleTime + Type = uint32 + } + } + OutputSignals = { + OutMdsW0 = { + DataSource = MDSWriter + Type = float32 + } + OutMdsW1 = { + DataSource = MDSWriter + Type = float32 + } + OutMdsW2 = { + DataSource = MDSWriter + Type = float64 + } + CycleTime = { + DataSource = MDSWriter + Type = uint32 + } + } + } + } + +Data = { + Class = ReferenceContainer + DefaultDataSource = DDB1 + +DDB1 = { + Class = GAMDataSource + } + +LoggerDataSource = { + Class = LoggerDataSource + } + +Timings = { + Class = TimingDataSource + } + +Timer = { + Class = LinuxTimer + SleepNature = "Default" + ExecutionMode = RealTimeThread + Signals = { + Counter = { + Type = uint32 + } + Time = { + Type = uint32 + } + } + } + +FileReader_DS = { + Class = FileDataSource::FileReader + Filename = "../Analysis/LangmuirSdas_46241.csv" + FileFormat = "csv" + CSVSeparator = "," + Interpolate = "no" + Preload = "yes" //Optional + EOF = "Last" // "Rewind" + } + + +FileSignalsWriter = { + Class = FileDataSource::FileWriter + NumberOfBuffers = 10000 + CPUMask = 1 + StackSize = 10000000 + Filename = "IsttokOutput.csv" + Overwrite = "yes" + FileFormat = "csv" + CSVSeparator = "," + StoreOnTrigger = 0 + Signals = { + Time = { + Type = uint32 + } + OutMdsW0 = { + Type = float32 + } + OutMdsW1 = { + Type = float32 + } + OutMdsW2 = { + Type = float32 + } + OutMdsW3 = { + Type = float32 + } + } + } + + +MDSWriter = { + Class = MDSWriter + NumberOfBuffers = 10 //Compulsory. Number of buffers in the circular buffer defined above. Each buffer is capable of holding a copy of all the DataSourceI signals. + CPUMask = 2 //Compulsory. Affinity assigned to the threads responsible for asynchronously flush data into the MDSplus database. + StackSize = 10000000 //Compulsory. Stack size of the thread above. + TreeName = "isttokoutput" //Compulsory. Name of the MDSplus tree. + PulseNumber = 1 //Optional. If -1 a new pulse will be created and the MDSplus pulse number incremented. + StoreOnTrigger = 0 //Compulsory. If 0 all the data in the circular buffer is continuously stored. If 1 data is stored when the Trigger signal is 1 (see below). + EventName = "updatejScope" //Compulsory. Event sent to jScope when TimeRefresh seconds have elapsed. + TimeRefresh = 5 //Compulsory. An event with the name set in the property EventName is sent to jScope when TimeRefresh seconds have elapsed. + Signals = { + OutMdsW0 = { //As many as required. + NodeName = "\TOP.OUT.OUT0" // node of the tree node + Period = 0.0001 //Compulsory. Period between signal samples. + AutomaticSegmentation = 0 + MakeSegmentAfterNWrites = 100 + } + OutMdsW1 = { //As many as required. + NodeName = "\TOP.OUT.OUT1" + Period = 0.0001 + AutomaticSegmentation = 1 + // MakeSegmentAfterNWrites = 100 + } + OutMdsW2 = { + NodeName = "\TOP.OUT.OUT2" + Period = 0.0001 + AutomaticSegmentation = 0 + MakeSegmentAfterNWrites = 100 + } + CycleTime = { //As many as required. + NodeName = "\TOP.OUT.Cycle_Time" // node of the tree node + Period = 0.0001 + AutomaticSegmentation = 0 + MakeSegmentAfterNWrites = 100 + } + } + } + } + +States = { + Class = ReferenceContainer + +Idle = { + Class = RealTimeState + +Threads = { + Class = ReferenceContainer + +Thread1 = { + Class = RealTimeThread + CPUs = 0x1 + Functions = {GAMTimer } + } + } + } + +Online = { + Class = RealTimeState + +Threads = { + Class = ReferenceContainer + +Thread1 = { + Class = RealTimeThread + CPUs = 0x1 + Functions = {GAMTimer GAMFileReader GAMElectricProbes GAMSignalsWriter GAMMDSWriter} + } + } + } + } + +Scheduler = { + Class = GAMScheduler + TimingDataSource = Timings + } +} +// vim: syntax=cpp ts=4 sw=4 sts=4 sr et