2011-09-14 6 views
6

मैं डेटा एकत्र कर रहा हूं और वास्तविक समय में उस डेटा को साजिश कर रहा हूं। डेटा मोशन कैप्चर सिस्टम द्वारा उत्पादित किया जाता है। मेरे पास एक वर्ग DynamicDataset है जो कि 2-कॉलम मैट्रिक्स के आसपास सिर्फ एक रैपर है (हालांकि यह उससे अधिक प्रचलित है) नए डेटा के लिए एक ईवेंट नोटिफ़ायर के साथ; एक और वर्ग DynamicPlotter जो डेटा-जोड़े गए ईवेंट की सुनता है और साजिश को गतिशील रूप से अपडेट करता है। उचित कोड के टुकड़े:MATLAB - एक लाइन हैंडल 'XData और YData को गतिशील रूप से अपडेट करने का सबसे अच्छा तरीका है?

classdef DynamicDataset < handle 
    properties 
     newestData = []; 
     data = [] 
    end 
    events 
     DataAdded 
    end 
    methods 
     function append(obj, val) 
      obj.data(end+1,:) = val; 
      obj.newestData = val; 
      notify(obj, 'DataAdded'); 
     end 
    end 
end 

classdef DynamicPlotter < dynamicprops 
    properties 
     FH %# figure handle 
     AH %# axes handle 
     LH %# array of line handles - may have multiple lines on the plot 

     dynProps = {} %# cell array of dynamic property names - 
         %# use to access individual datasets 
    end 
    methods 
     function obj = DynamicPlotter(props) %# props is a cell array of dynamic 
              %# properties to store information 
      for i = 1:length(props) 
       addprop(obj, props{i}); 
       obj.(props{i}) = DynamicDataset; 
       obj.dynProps = [obj.dynProps props{i}]; 

       addlistener(obj.(props{i}), 'DataAdded', @obj.updatePlot(i)); 
      end 
      obj.createBlankPlot(); 
     end 

     function createBlankPlot(obj) 
      obj.FH = figure; 
      obj.AH = axes; 

      hold all; 

      for i = 1:length(obj.dynProps) 
       obj.LH(i) = plot(nan); %# only used to produce a line handle 
        set(obj.LH(i), 'XData', [], 'YData', []); 
      end 
     end 

     function updatePlot(obj, propNum) 
      X = get(obj.LH(propNum), 'XData'); 
      Y = get(obj.LH(propNum), 'YData'); 

      X(end+1) = obj.(dynProps{propNum}).newestData(1); 
      Y(end+1) = obj.(dynProps{propNum}).newestData(2); 

      set(obj.LH(propNum), 'XData', X, 'YData', Y); 
     end 
    end 
end 

MATLAB कोड प्रोफाइल के आधार पर, updatePlot() में set आदेश नहीं बल्कि महंगा है। मैं सोच रहा हूं कि क्या व्यक्तिगत अंक प्लॉट करने के लिए एक बेहतर तरीका है? आदर्श रूप में मैं एकल बिंदु को XData और YData में धक्का दूंगा और केवल उस बिंदु को खींचूंगा, लेकिन मुझे नहीं पता कि यह संभव है या नहीं।

कृपया ध्यान दें कि कई लाइनरीज़ ऑब्जेक्ट्स हो सकती हैं (यानी, एक ही प्लॉट पर एकाधिक ग्राफ); plot() अक्ष के हैंडल को तर्क के रूप में लेता है, इसलिए यह पहले खींचे गए लाइन हैंडल के गुणों पर विचार नहीं करेगा (या ऐसा करने का कोई तरीका है?); मैंने बस plot(x,y);hold all; करने के बारे में सोचा था, लेकिन यह मुझे हर बार अलग लाइन हैंडल देगा, प्रत्येक एक बिंदु से संबंधित होगा।

ऐसा हो सकता है कि आने वाले बिंदुओं को किसी भी तेजी से साजिश करने का कोई तरीका नहीं है, लेकिन मुझे लगा कि मैं पूछूंगा।

EDIT: वास्तविक कोड के साथ अपडेट किया गया ओपी, जो कि गलत व्याख्या के लिए एक सामान्य उदाहरण का उपयोग करने के बजाय मैं काम कर रहा हूं।

+0

मैं नहीं जानता कि आप इस देखा है अगर लेकिन http://stackoverflow.com/questions/1693429/matlab-oop-is-it-slow-or-am- पर एक नज़र मैं कर रहा हूँ-कुछ गलत। मूल रूप से मैटलैब में कक्षाओं का उपयोग करने से आम तौर पर खराब प्रदर्शन – Marm0t

+0

धन्यवाद होता है, मैंने इसे पहले देखा है। मेरे प्रोजेक्ट के कारणों के लिए कक्षाओं के उपयोग की आवश्यकता है, जिन कारणों में मैं नहीं जाऊंगा, इसलिए उसके आस-पास कोई रास्ता नहीं है .. लेकिन क्या 'सेट' कॉल धीमा हो जाएगा क्योंकि इसे किसी विधि के अंदर बुलाया जाता है? –

+0

@ hardlyrude27: आपको एडलिस्टर लाइन को इस प्रकार सही करना चाहिए: 'addlistener (obj। (Props {i}),' DataAdded ', @ (src, ev) obj.updatePlot (i)); '। आप 'UpdatePlot' फ़ंक्शन – Amro

उत्तर

4

डेटा आप प्रत्येक अपडेट में संभाल रहे हैं की राशि, बड़ी है (हालांकि केवल एक बिंदु वास्तव में बदल रहा है), अपने कोड हे (एन^2) बना रही है।

डेटा के एक बड़े समूह को बनाने के लिए दूसरी लाइनरीज़ का उपयोग करके, आप प्रत्येक बिंदु को एक छोटी "सक्रिय" रेखा में जोड़ने और मुख्य लाइनरीज़ में बड़े ब्लॉक जोड़ने के बीच वैकल्पिक हो सकते हैं। हालांकि यह ओ (एन^2) से बिल्कुल नहीं बचता है, यह आपको निरंतर महत्वपूर्ण रूप से कम करने देता है।

यदि आप ऐसा करते हैं, तो "पुरानी" लाइनरीज़ और "सक्रिय" लाइनरीज़ को एक बिंदु से ओवरलैप करना याद रखें, ताकि वे कनेक्ट हो जाएं।

मूलतः: क्योंकि आप सभी मूल्यों हर कि आप updatePlot फोन replotting रहे

function updatePlot(obj, propNum) 
     X = get(obj.LHactive(propNum), 'XData'); 
     Y = get(obj.LHactive(propNum), 'YData'); 

     X(end+1) = obj.(dynProps{propNum}).newestData(1); 
     Y(end+1) = obj.(dynProps{propNum}).newestData(2); 

     if numel(X) > 100 
      Xold = [get(obj.LH(propNum), 'XData'); X(2:end)]; 
      Yold = [get(obj.LH(propNum), 'YData'); Y(2:end)]; 
      set(obj.LH(propNum), 'XData', Xold, 'YData', Yold); 

      X = X(end); 
      Y = Y(end); 
     end 

     set(obj.LHactive(propNum), 'XData', X, 'YData', Y); 
    end 
+0

इसने साजिश के समय को बहुत कम कर दिया! यदि आपके पास समय कम करने के लिए कोई और विचार है, तो मुझे बताएं .. –

1

आपके कोड को चलाने में लंबा समय लगने का कारण यह है कि आप अपने चर को असाइन करने के लिए लूप के लिए उपयोग कर रहे हैं। आप जिस मैटलैब का उपयोग कर रहे हैं उसके आधार पर, यह आपकी प्रक्रिया को काफी धीमा कर देगा। मैं vectorization उपयोग करने का सुझाव इस तरह से अपनी x और y के लिए प्रदान करना:

x = 1:1000; 
y = cosd(x); 

तब आप अपने डेटा में पहली अंक प्रदान कर सकते हैं।

xi = x(1); 
yi = y(1); 

जब आप प्लॉट करते हैं, तो XDataSource और YDataSource असाइन करें।

h = plot(xi, yi, 'YDataSource', 'yi', 'XDataSource', 'xi'); 

अब आप पाश के माध्यम से मूल्यों को बदलने के लिए जब, Xdata और Ydata मूल्यों को अद्यतन करने के refreshdata का उपयोग करें। आकृति विंडो को अद्यतन करने के लिए खींचा गया फ़ंक्शन का उपयोग करें।

for k = 2:1000, 
xi = x(1:k); 
yi = y(1:k); 
refreshdata(h, 'caller') 
drawnow; 
end 
+0

यह दुर्भाग्य से मेरी ज़रूरतों के लिए काम नहीं करेगा - मेरा डेटा वास्तव में फॉर-लूप में उत्पन्न नहीं होता है, लेकिन वास्तविक समय में गति कैप्चर सिस्टम द्वारा उत्पादित किया जाता है। उपरोक्त कोड स्निपेट दर्शाता है कि मैं अपने डेटा को गतिशील रूप से साजिश कर रहा हूं। मैं अपने विशिष्ट मामले को प्रतिबिंबित करने के लिए ओपी अपडेट करूंगा; मैं और अधिक सामान्य होने की कोशिश कर रहा था लेकिन मेरा उदाहरण स्पष्ट रूप से भ्रामक था। –

1

आपका कोड, धीमी है। इसलिए मैं केवल अपडेटप्लॉट में यह नवीनतम बिंदु प्लॉट करूंगा (यह भी समस्या है जो आपने कहा है: आदर्श रूप से मैं एकल बिंदु को XData और YData में धक्का दूंगा और केवल उस बिंदु को खींचूंगा, लेकिन मुझे नहीं पता कि यह क्या है संभव है।)

  1. संपत्ति LH_point_counter

    classdef DynamicPlotter < dynamicprops 
        properties 
         FH %# figure handle 
         AH %# axes handle 
         LH %# cell array of line handles - may have multiple lines on the plot 
    
         % counter that counts home many points we have for each dynProps 
         LH_point_counter = []; 
    
         dynProps = {} %# cell array of dynamic property names - 
           %# use to access individual datasets 
        end 
    
  2. संशोधित जोड़ने updatePlot

    function updatePlot(obj, propNum) 
        % plot new point 
        new_x = obj.(dynProps{propNum}).newestData(1); 
        new_y = obj.(dynProps{propNum}).newestData(2); 
        new_handle = plot(new_x, new_y); 
    
        % add new handle to list of handles of this property 
        counter_this_prop = obj.LH_point_counter(propNum); 
        counter_this_prop = counter_this_prop + 1; 
        obj.LH{propNum}(counter_this_prop) = new_handle; 
    
        % save new counter value 
        obj.LH_point_counter(propNum) = counter_this_prop; 
    end 
    
+0

यह काम कर सकता है - मुझे यकीन है कि संपत्तियों पर पुनर्विचार करना दुनिया में सबसे महंगा बात नहीं होगी। हालांकि, मुझे आश्चर्य है कि यह मेरे मुख्य अक्ष संभाल में हस्तक्षेप कैसे करेगा? मैं प्लॉट विंडो और अन्य अक्ष संभाल गुणों को मैन्युअल रूप से समायोजित करता हूं, इसलिए इसे लगातार लिखना शायद सबसे अच्छा विकल्प नहीं हो सकता है। –

+1

कोड किसी भी संपत्ति को दोहराने नहीं है। यह सब हैंडल की सूची में नवीनतम हैंडल जोड़ता है - यह एक बहुत सस्ता ऑपरेशन है। आपका मैन्युअल अक्ष समायोजन एक अलग मुद्दा है और आपने इसके लिए कोड पोस्ट नहीं किया है। – memyself

संबंधित मुद्दे