microsoft / Qcodes

Modular data acquisition framework
http://microsoft.github.io/Qcodes/
MIT License
353 stars 318 forks source link

[feature request] get_parameter_data option to not return setpoints #1601

Open thibaudruelle opened 5 years ago

thibaudruelle commented 5 years ago

In the case of a Multiparameter with many internal setpoints that stay constant while an external setpoint is swept, the output of Dataset.get_parameter_data can get unwieldy. A useful option would be to only return setpoints once, then something similar to Dataset.get_data.

import qcodes as qc
from qcodes import MultiParameter, Measurement, Parameter
from qcodes.dataset.data_set import load_by_id
import numpy as np

qc.new_experiment(name='get_data_issue', sample_name='none')

class MockMultiParam(MultiParameter):
    def __init__(self):
        super().__init__("multiparam", names=('A','B'), shapes=((100,),)*2, setpoints = ((np.arange(100),),)*2, setpoint_names = (('t',),)*2 )
        self.i = 0

    def get_raw(self):
        val = (np.arange(100) + self.i*10*100,)*2
        self.i +=1
        return val

mock_param = MockMultiParam()
t2_param = Parameter('t2', set_cmd=None, get_cmd=None)

meas = Measurement()
meas.register_parameter(t2_param)
meas.register_parameter(mock_param, paramtype='array', setpoints=(t2_param,))

with meas.run() as datasaver:  
    for t2 in range(10):
        datasaver.add_result((t2_param, t2), (mock_param, mock_param()))
        run_id = datasaver.run_id

ds = load_by_id(run_id)

print(ds.get_data('B'))
print(ds.get_parameter_data('B'))
jenshnielsen commented 5 years ago

@thibaudruelle I had to modify your example a bit to get it to run, can you please confirm if the below is what you intend

import qcodes as qc
from qcodes import MultiParameter, Measurement, Parameter
from qcodes.dataset.data_set import load_by_id
import numpy as np

qc.new_experiment(name='get_data_issue', sample_name='none')

class MockMultiParam(MultiParameter):
    def __init__(self):
        super().__init__("multiparam", names=('A','B'), shapes=((1_000_000,),)*2, setpoints = ((np.arange(1e6),),)*2, setpoint_names = (('t',),)*2 )
        self.i = 0

    def get_raw(self):
        val = (np.arange(1e6) + self.i*10*1e6,)*2
        self.i +=1
        return val

mock_param = MockMultiParam()
t2_param = Parameter('t2', set_cmd=None, get_cmd=None)

meas = Measurement()
meas.register_parameter(t2_param)
meas.register_parameter(mock_param, paramtype='array', setpoints=(t2_param,))

with meas.run() as datasaver:  
    for t2 in range(100):
        datasaver.add_result((t2_param, t2), (mock_param, mock_param()))
        run_id = datasaver.run_id

ds = datasaver.dataset

print(ds.get_data('B'))
print(ds.get_parameter_data('B'))
jenshnielsen commented 5 years ago

This works exactly as I would expect. Can you elaborate on what you mean by unwieldy it has the same shape as the data so it's no more unwieldy than the data

thibaudruelle commented 5 years ago

@jenshnielsen Sorry for the mistakes in the working example, I corrected them. It does work as expected. However in the specific case when the values of 't' do not depend on 't2', get_parameter_data returns a lot of redundant data. For my use case it would be useful to have an option to return only the top_level_parameter data. It might be a niche case and not worth working on it though.