Skip to content

Commit 14858b9

Browse files
author
Julian Kates-Harbeck
committed
added support for channel signals (i.e. signals that come as channels but we only want individual chords
1 parent 5f09a5c commit 14858b9

File tree

3 files changed

+94
-33
lines changed

3 files changed

+94
-33
lines changed

data/signals.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
import time
44
import sys
55

6-
from plasma.primitives.data import Signal,ProfileSignal,Machine
6+
from plasma.primitives.data import Signal,ProfileSignal,ChannelSignal,Machine
77

88
def create_missing_value_filler():
99
time = np.linspace(0,100,100)
@@ -176,8 +176,8 @@ def fetch_nstx_data(signal_path,shot_num,c):
176176
pin = Signal("Input Power (beam for d3d)",['jpf/gs/bl-ptot<s','d3d/bmspinj'],[jet,d3d]) #Total Beam Power
177177

178178
pradtot = Signal("Radiated Power",['jpf/db/b5r-ptot>out'],[jet])
179-
pradcore = Signal("Radiated Power Core",['d3d/'+r'\bol_l15_p'],[d3d])
180-
pradedge = Signal("Radiated Power Edge",['d3d/'+r'\bol_l03_p'],[d3d])
179+
pradcore = ChannelSignal("Radiated Power Core",['ppf/bolo/kb5h/channel14', 'd3d/'+r'\bol_l15_p'],[jet,d3d])
180+
pradedge = ChannelSignal("Radiated Power Edge",['ppf/bolo/kb5h/channel10','d3d/'+r'\bol_l03_p'],[jet,d3d])
181181
# pechin = Signal("ECH input power, not always on",['d3d/pcechpwrf'],[d3d])
182182
pechin = Signal("ECH input power, not always on",['RF/ECH.TOTAL.ECHPWRC'],[d3d])
183183

plasma/primitives/data.py

Lines changed: 90 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,27 @@ def load_data(self,prepath,shot,dtype='float32'):
118118

119119
return t,sig,True
120120

121+
122+
def fetch_data_basic(self,machine,shot_num,c):
123+
path = self.get_path(machine)
124+
mapping_path = self.get_mapping_path(machine)
125+
success = False
126+
mapping = None
127+
try:
128+
time,data,mapping,success = machine.fetch_data_fn(path,shot_num,c)
129+
except Exception as e:
130+
print(e)
131+
sys.stdout.flush()
132+
133+
if not success:
134+
return None,None,None,False
135+
136+
time = np.array(time) + 1e-3*self.get_causal_shift(machine)
137+
return time,np.array(data),mapping,success
138+
139+
def fetch_data(self,machine,shot_num,c):
140+
return self.fetch_data_basic(machine,shot_num,c)
141+
121142
def is_defined_on_machine(self,machine):
122143
return machine in self.machines
123144

@@ -206,6 +227,75 @@ def load_data(self,prepath,shot,dtype='float32'):
206227

207228
return t,sig_interp,True
208229

230+
def fetch_data(self,machine,shot_num,c):
231+
time,data,mapping,success = self.fetch_data_basic(machine,shot_num,c)
232+
233+
if mapping is not None and np.ndim(mapping) == 1:#make sure there is a mapping for every timestep
234+
T = len(time)
235+
mapping = np.tile(mapping,(T,1)).transpose()
236+
assert(mapping.shape == data.shape), "shape of mapping and data is different"
237+
if mapping_path is not None:#fetch the mapping separately
238+
time_map,data_map,mapping_map,success_map = machine.fetch_data_fn(mapping_path,shot_num,c)
239+
success = (success and success_map)
240+
if not success:
241+
print("No success for signal {} and mapping {}".format(path,mapping_path))
242+
else:
243+
assert(np.all(time == time_map)), "time for signal {} and mapping {} don't align: \n{}\n\n{}\n".format(path,mapping_path,time,time_map)
244+
mapping = data_map
245+
246+
if not success:
247+
return None,None,None,False
248+
return time,data,mapping,success
249+
250+
251+
class ChannelSignal(Signal):
252+
def __init__(self,description,paths,machines,tex_label=None,causal_shifts=None,mapping_range=(0,1),num_channels=32,data_avail_tolerances=None,is_strictly_positive=False,mapping_paths=None):
253+
super(ChannelSignal, self).__init__(description,paths,machines,tex_label,causal_shifts,is_ip=False,data_avail_tolerances=data_avail_tolerances,is_strictly_positive=is_strictly_positive,mapping_paths=mapping_paths)
254+
nums,new_paths = self.get_channel_nums(paths)
255+
self.channel_nums = nums
256+
self.paths = new_paths
257+
258+
def get_channel_nums(self,paths):
259+
regex = re.compile('channel\d+')
260+
regex_int = re.compile('\d+')
261+
nums = []
262+
new_paths = []
263+
for p in paths:
264+
assert(p[-1] != '/')
265+
elements = p.split('/')
266+
res = regex.findall(elements[-1])
267+
assert(len(res) < 2)
268+
if len(res) == 0:
269+
nums.append(None)
270+
new_paths.append(p)
271+
else:
272+
nums.append(int(regex_int.findall(res[0])[0]))
273+
new_paths.append("/".join(elements[:-1]))
274+
return nums,new_paths
275+
276+
def get_channel_num(self,machine):
277+
idx = self.get_idx(machine)
278+
return self.channel_nums[idx]
279+
280+
def fetch_data(self,machine,shot_num,c):
281+
time,data,mapping,success = self.fetch_data_basic(machine,shot_num,c)
282+
channel_num = self.get_channel_num(machine)
283+
if channel_num is not None and success:
284+
if np.ndim(data) != 2:
285+
print("Channel Signal {} expected 2D array for shot {}".format(self,shot))
286+
success = False
287+
else:
288+
data = data[:,channel_num]
289+
return time,data,mapping,success
290+
291+
def get_file_path(self,prepath,machine,shot_number):
292+
dirname = self.get_path(machine)
293+
num = self.get_channel_num(machine)
294+
if num is not None:
295+
dirname += "/channel{}".format(num)
296+
return get_individual_shot_file(prepath + '/' + machine.name + '/' +dirname + '/',shot_number)
297+
298+
209299

210300
class Machine(object):
211301
def __init__(self,name,server,fetch_data_fn,max_cores = 8,current_threshold=0):
@@ -218,35 +308,6 @@ def __init__(self,name,server,fetch_data_fn,max_cores = 8,current_threshold=0):
218308
def get_connection(self):
219309
return Connection(server)
220310

221-
def fetch_data(self,signal,shot_num,c):
222-
path = signal.get_path(self)
223-
mapping_path = signal.get_mapping_path(self)
224-
success = False
225-
mapping = None
226-
try:
227-
time,data,mapping,success = self.fetch_data_fn(path,shot_num,c)
228-
if mapping is not None and np.ndim(mapping) == 1:#make sure there is a mapping for every timestep
229-
T = len(time)
230-
mapping = np.tile(mapping,(T,1)).transpose()
231-
assert(mapping.shape == data.shape), "shape of mapping and data is different"
232-
if mapping_path is not None:#fetch the mapping separately
233-
time_map,data_map,mapping_map,success_map = self.fetch_data_fn(mapping_path,shot_num,c)
234-
success = (success and success_map)
235-
if not success:
236-
print("No success for signal {} and mapping {}".format(path,mapping_path))
237-
else:
238-
assert(np.all(time == time_map)), "time for signal {} and mapping {} don't align: \n{}\n\n{}\n".format(path,mapping_path,time,time_map)
239-
mapping = data_map
240-
except Exception as e:
241-
print(e)
242-
sys.stdout.flush()
243-
244-
if not success:
245-
return None,None,None,False
246-
247-
time = np.array(time) + 1e-3*signal.get_causal_shift(self)
248-
return time,np.array(data),mapping,success
249-
250311
def __eq__(self,other):
251312
return self.name.__eq__(other.name)
252313

plasma/utils/downloading.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,7 @@ def save_shot(shot_num_queue,c,signals,save_prepath,machine,sentinel=-1):
9090
if not success:
9191
try:
9292
try:
93-
time,data,mapping,success = machine.fetch_data(signal,shot_num,c)
93+
time,data,mapping,success = signal.fetch_data(machine,shot_num,c)
9494
if not success:
9595
print('No success shot {}, signal {}'.format(shot_num,signal))
9696
except:

0 commit comments

Comments
 (0)