views:

1099

answers:

3

Hello,

I would like to use core plot to chart my data as follows: for each data point (x,y), draw a vertical line starting at (x,0) and running to (x,y).

The data are medication doses, mapped against time of dose.

Any help would be greatly appreciated!

+1  A: 

Sounds like a bar plot. Set barsAreHorizontal = NO to make vertical bars. Use barWidth, lineStyle, and fill to customize the appearance. Several of the example programs use bar plots—look at them for ideas.

Eric Skroch
My understanding of a bar plot is that it divides the data range into buckets and displays the average y value for each bucket. So, the bars cover the entire range. For my application, I would like a line for each and every data point, with height equal to the y value of that point. If I can do this with a bar plot, that would be fabuluous.
Jacko
A: 

Hi I think this might help you.

- (void)viewDidLoad {
    [super viewDidLoad];

    self.title = @"Core-Plot";

    graph = [[CPXYGraph alloc] initWithFrame:CGRectZero];
    CPTheme *theme = [CPTheme themeNamed:kCPDarkGradientTheme];
    [graph applyTheme:theme];

    CGAffineTransform verticalFlip = CGAffineTransformMakeScale(1,-1);

    UILabel *lbl;
    for( int i = 21; i <= 24; i++ ){

        lbl = (UILabel *)[self.view viewWithTag:i];
        lbl.transform = CGAffineTransformTranslate(verticalFlip, 0, -300);
    }   

    CPLayerHostingView *hostingView = (CPLayerHostingView *)self.view;
    hostingView.hostedLayer = graph;
    graph.plotArea.masksToBorder = NO;

    graph.paddingLeft = 50.0;
    graph.paddingTop = 60.0;
    graph.paddingRight = 20.0;
    graph.paddingBottom = 50.0;

    CPXYPlotSpace *plotSpace = (CPXYPlotSpace *)graph.defaultPlotSpace;
    plotSpace.xRange = [CPPlotRange plotRangeWithLocation:CPDecimalFromFloat(0) length:CPDecimalFromFloat(6)];
    plotSpace.yRange = [CPPlotRange plotRangeWithLocation:CPDecimalFromFloat(0) length:CPDecimalFromFloat(([[expectedCigArray objectAtIndex:0] floatValue]+5))];
    plotSpace.allowsUserInteraction=YES;

    CPXYAxisSet *axisSet = (CPXYAxisSet *)graph.axisSet;
    CPXYAxis *x = axisSet.xAxis;
    x.axisLineStyle = nil;
    x.majorTickLineStyle = nil;
    x.minorTickLineStyle = nil;
    x.majorIntervalLength = CPDecimalFromString(@"1");
    x.constantCoordinateValue = CPDecimalFromString(@"0");
    x.title = @"Days";
    x.titleLocation = CPDecimalFromFloat(1.5f);

    CPXYAxis *y = axisSet.yAxis;
    y.axisLineStyle = nil;
    y.majorTickLineStyle = nil;
    y.minorTickLineStyle = nil;
    y.majorIntervalLength = CPDecimalFromString(@"5");
    y.constantCoordinateValue = CPDecimalFromString(@"0");
    y.title = @"Money";
    y.titleOffset = 30.0f;
    y.titleLocation = CPDecimalFromFloat(10.0f);


    CPBarPlot *expectedMoney = [CPBarPlot tubularBarPlotWithColor:[CPColor darkGrayColor] horizontalBars:NO];
    expectedCigPlot.identifier = @"expectedCigPlot";
    expectedCigPlot.cornerRadius = 2.0f;
    expectedCigPlot.barWidth = 15.0f;
    expectedCigPlot.dataSource = self;
    [graph addPlot:expectedCigPlot toPlotSpace:plotSpace];

}


-(NSUInteger)numberOfRecordsForPlot:(CPPlot *)plot{
    return (moneyArray.count + 1);
}

-(NSNumber *)numberForPlot:(CPPlot *)plot field:(NSUInteger)fieldEnum recordIndex:(NSUInteger)index
{   
    if(fieldEnum == CPScatterPlotFieldX)
    { 
        return [NSNumber numberWithInt: index];
    }
    else
    {
        if(plot.identifier == @"money")
        {
            if(index == 0)
                return [NSNumber numberWithDouble:0.0];
            return [NSNumber numberWithDouble:[[moneyArray objectAtIndex:(index-1)] doubleValue]];
        }

    }
}

Note that in the above code money array has value of money, So I think your purpose can be solved by passing the y value in the array.

Hope this helps.

Thanks,

Madhup

Madhup
A: 

This is my code; I would like the medicine plot to appear as a bar chart. I tried modifying this based on above, but I got one single bar centered on one single day.

-(void)viewDidLoad { [super viewDidLoad];

// If you make sure your dates are calculated at noon, you shouldn't have to 
// worry about daylight savings. If you use midnight, you will have to adjust
// for daylight savings time.
NSDate *refDate = [NSDate date];
NSTimeInterval oneDay = 24 * 60 * 60;

// Create graph from theme
graph = [(CPXYGraph *)[CPXYGraph alloc] initWithFrame:CGRectZero];
CPTheme *theme = [CPTheme themeNamed:kCPDarkGradientTheme];
[graph applyTheme:theme];
graph.paddingLeft = -100.0;
graph.paddingTop = 0.0;
graph.paddingRight = -100.0;
graph.paddingBottom = 0.0;




CPLayerHostingView *hostingView = (CPLayerHostingView *)self.view;
hostingView.hostedLayer = graph;


// Setup scatter plot space
CPXYPlotSpace *plotSpace = (CPXYPlotSpace *)graph.defaultPlotSpace;
plotSpace.allowsUserInteraction = YES;
NSTimeInterval xLow = 0.0f;
plotSpace.xRange = [CPPlotRange plotRangeWithLocation:CPDecimalFromFloat(xLow) length:CPDecimalFromFloat(oneDay*5.0f)];
plotSpace.yRange = [CPPlotRange plotRangeWithLocation:CPDecimalFromFloat(0.0) length:CPDecimalFromFloat(20.0)];

// Axes
CPXYAxisSet *axisSet = (CPXYAxisSet *)graph.axisSet;
CPXYAxis *x = axisSet.xAxis;
x.majorIntervalLength = CPDecimalFromFloat(oneDay);
x.constantCoordinateValue = CPDecimalFromString(@"2");
x.minorTicksPerInterval = 0;
NSDateFormatter *dateFormatter = [[[NSDateFormatter alloc] init] autorelease];
dateFormatter.dateStyle = kCFDateFormatterShortStyle;
CPTimeFormatter *timeFormatter = [[[CPTimeFormatter alloc] initWithDateFormatter:dateFormatter] autorelease];
timeFormatter.referenceDate = refDate;
x.labelFormatter = timeFormatter;

CPXYAxis *y = axisSet.yAxis;
y.majorIntervalLength = CPDecimalFromString(@"5");
y.minorTicksPerInterval = 2;
y.constantCoordinateValue = CPDecimalFromFloat(oneDay);

////////////////////
// glucose plot
CPScatterPlot *glucosePlot = [[[CPScatterPlot alloc] init] autorelease];
glucosePlot.identifier = glucosePlotName;
glucosePlot.dataLineStyle.lineWidth = 3.f;
glucosePlot.dataLineStyle.lineColor = [CPColor greenColor];
glucosePlot.dataSource = self;

// Create a green plot area
CPColor *areaColor = [CPColor colorWithComponentRed:0.3 green:1.0 blue:0.3 alpha:0.8];
CPGradient *areaGradient = [CPGradient gradientWithBeginningColor:areaColor endingColor:[CPColor clearColor]];
areaGradient.angle = -90.0f;
CPFill* areaGradientFill = [CPFill fillWithGradient:areaGradient];
glucosePlot.areaFill = areaGradientFill;
glucosePlot.areaBaseValue = CPDecimalFromString(@"1.75");

// Animate in the new plot, as an example
glucosePlot.opacity = 0.0f;

CABasicAnimation *fadeInAnimation = [CABasicAnimation animationWithKeyPath:@"opacity"];
fadeInAnimation.duration = 1.0f;
fadeInAnimation.removedOnCompletion = NO;
fadeInAnimation.fillMode = kCAFillModeForwards;
fadeInAnimation.toValue = [NSNumber numberWithFloat:1.0];
[glucosePlot addAnimation:fadeInAnimation forKey:@"animateOpacity"];

[graph addPlot:glucosePlot];


/////////////////////////////////////
// medicine plot
CPScatterPlot *medicinePlot = [[[CPScatterPlot alloc] init] autorelease];
medicinePlot.identifier = medicationPlotName;
medicinePlot.dataLineStyle.lineWidth = 3.f;
medicinePlot.dataLineStyle.lineColor = [CPColor redColor];
medicinePlot.dataSource = self;

// Create a red plot area
areaColor = [CPColor colorWithComponentRed:1.0 green:0.3 blue:0.3 alpha:0.8];
areaGradient = [CPGradient gradientWithBeginningColor:areaColor endingColor:[CPColor clearColor]];
areaGradient.angle = -90.0f;
areaGradientFill = [CPFill fillWithGradient:areaGradient];
medicinePlot.areaFill = areaGradientFill;
medicinePlot.areaBaseValue = CPDecimalFromString(@"1.75");

// Animate in the new plot, as an example
medicinePlot.opacity = 0.0f;

fadeInAnimation = [CABasicAnimation animationWithKeyPath:@"opacity"];
fadeInAnimation.duration = 1.0f;
fadeInAnimation.removedOnCompletion = NO;
fadeInAnimation.fillMode = kCAFillModeForwards;
fadeInAnimation.toValue = [NSNumber numberWithFloat:1.0];
[medicinePlot addAnimation:fadeInAnimation forKey:@"animateOpacity"];

[graph addPlot:medicinePlot];


// Add some data
glucosiaAppDelegate* delegate = [[UIApplication sharedApplication] delegate];
int count = [delegate.dataModel.entries count];
NSMutableArray *newData = [NSMutableArray arrayWithCapacity:count];
NSUInteger i=0;
DiaryEntry* currentEntry;
NSEnumerator* enumerator = [delegate.dataModel.entries objectEnumerator];
while (currentEntry=[enumerator nextObject]) 
{
    NSNumber* type = [currentEntry valueForKey:@"type"];
    if ( [type intValue] != GLUCOSE)
        continue;
    NSDate* date = [currentEntry valueForKey:@"date"];
    NSNumber* amount = [currentEntry valueForKey:@"amount"];
    NSTimeInterval x = [date timeIntervalSinceDate:refDate];

    [newData addObject: [NSDictionary dictionaryWithObjectsAndKeys:
                         [NSDecimalNumber numberWithFloat:x], @"x",[NSDecimalNumber numberWithFloat:[amount floatValue]] , @"y",  nil]];
    i++;
}
self.dataForPlot = newData;

}

-(void)changePlotRange { // Setup plot space CPXYPlotSpace *plotSpace = (CPXYPlotSpace *)graph.defaultPlotSpace; plotSpace.xRange = [CPPlotRange plotRangeWithLocation:CPDecimalFromFloat(0.0) length:CPDecimalFromFloat(3.0 + 2.0*rand()/RAND_MAX)]; plotSpace.yRange = [CPPlotRange plotRangeWithLocation:CPDecimalFromFloat(0.0) length:CPDecimalFromFloat(3.0 + 2.0*rand()/RAND_MAX)]; }

pragma mark -

pragma mark Plot Data Source Methods

-(NSUInteger)numberOfRecordsForPlot:(CPPlot *)plot { return [dataForPlot count]; }

-(NSNumber *)numberForPlot:(CPPlot *)plot field:(NSUInteger)fieldEnum recordIndex:(NSUInteger)index { NSNumber *num = [[dataForPlot objectAtIndex:index] valueForKey:(fieldEnum == CPScatterPlotFieldX ? @"x" : @"y")]; return num; }

Jacko